From 7aae8cc5262c1b36e3196845d62489b76af9063f Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Mon, 21 Dec 2009 10:53:41 -0500 Subject: Set up work for making a 3.5 prerelease. Set version stuff to 3.5.0-rc1. Copy the CHANGELOG from 3.4-working. Rename the obt-4.0 and obrender-4.0 pkgconfig stuff to obt-3.5 and obrender-3.5 Rename the "render" directory to "obrender" so that the public headers can be installed in --- .gitignore | 4 +- CHANGELOG | 273 ++++++ Makefile.am | 98 +- configure.ac | 18 +- obrender/Makefile | 4 + obrender/color.c | 361 +++++++ obrender/color.h | 51 + obrender/font.c | 380 ++++++++ obrender/font.h | 42 + obrender/geom.h | 38 + obrender/gradient.c | 836 ++++++++++++++++ obrender/gradient.h | 27 + obrender/icon.h | 422 ++++++++ obrender/image.c | 516 ++++++++++ obrender/image.h | 35 + obrender/imagecache.c | 144 +++ obrender/imagecache.h | 51 + obrender/instance.c | 309 ++++++ obrender/instance.h | 57 ++ obrender/mask.c | 82 ++ obrender/mask.h | 32 + obrender/obrender-3.5.pc.in | 14 + obrender/render.c | 564 +++++++++++ obrender/render.h | 350 +++++++ obrender/test.c | 115 +++ obrender/theme.c | 2007 +++++++++++++++++++++++++++++++++++++++ obrender/theme.h | 266 ++++++ obrender/version.h.in | 15 + obt/obt-3.5.pc.in | 14 + obt/obt-4.0.pc.in | 14 - openbox/client.c | 2 +- openbox/client.h | 2 +- openbox/config.h | 2 +- openbox/dock.c | 2 +- openbox/dock.h | 2 +- openbox/focus_cycle_indicator.c | 2 +- openbox/focus_cycle_popup.c | 2 +- openbox/frame.c | 2 +- openbox/frame.h | 2 +- openbox/framerender.c | 2 +- openbox/menu.h | 2 +- openbox/menuframe.c | 2 +- openbox/menuframe.h | 2 +- openbox/moveresize.c | 4 +- openbox/openbox.c | 4 +- openbox/openbox.h | 4 +- openbox/popup.c | 4 +- openbox/popup.h | 2 +- openbox/prompt.h | 2 +- openbox/screen.c | 2 +- render/Makefile | 4 - render/color.c | 361 ------- render/color.h | 51 - render/font.c | 380 -------- render/font.h | 42 - render/geom.h | 38 - render/gradient.c | 836 ---------------- render/gradient.h | 27 - render/icon.h | 422 -------- render/image.c | 516 ---------- render/image.h | 35 - render/imagecache.c | 144 --- render/imagecache.h | 51 - render/instance.c | 309 ------ render/instance.h | 57 -- render/mask.c | 82 -- render/mask.h | 32 - render/obrender-4.0.pc.in | 14 - render/render.c | 564 ----------- render/render.h | 350 ------- render/test.c | 115 --- render/theme.c | 2007 --------------------------------------- render/theme.h | 266 ------ render/version.h.in | 15 - 74 files changed, 7089 insertions(+), 6816 deletions(-) create mode 100644 obrender/Makefile create mode 100644 obrender/color.c create mode 100644 obrender/color.h create mode 100644 obrender/font.c create mode 100644 obrender/font.h create mode 100644 obrender/geom.h create mode 100644 obrender/gradient.c create mode 100644 obrender/gradient.h create mode 100644 obrender/icon.h create mode 100644 obrender/image.c create mode 100644 obrender/image.h create mode 100644 obrender/imagecache.c create mode 100644 obrender/imagecache.h create mode 100644 obrender/instance.c create mode 100644 obrender/instance.h create mode 100644 obrender/mask.c create mode 100644 obrender/mask.h create mode 100644 obrender/obrender-3.5.pc.in create mode 100644 obrender/render.c create mode 100644 obrender/render.h create mode 100644 obrender/test.c create mode 100644 obrender/theme.c create mode 100644 obrender/theme.h create mode 100644 obrender/version.h.in create mode 100644 obt/obt-3.5.pc.in delete mode 100644 obt/obt-4.0.pc.in delete mode 100644 render/Makefile delete mode 100644 render/color.c delete mode 100644 render/color.h delete mode 100644 render/font.c delete mode 100644 render/font.h delete mode 100644 render/geom.h delete mode 100644 render/gradient.c delete mode 100644 render/gradient.h delete mode 100644 render/icon.h delete mode 100644 render/image.c delete mode 100644 render/image.h delete mode 100644 render/imagecache.c delete mode 100644 render/imagecache.h delete mode 100644 render/instance.c delete mode 100644 render/instance.h delete mode 100644 render/mask.c delete mode 100644 render/mask.h delete mode 100644 render/obrender-4.0.pc.in delete mode 100644 render/render.c delete mode 100644 render/render.h delete mode 100644 render/test.c delete mode 100644 render/theme.c delete mode 100644 render/theme.h delete mode 100644 render/version.h.in diff --git a/.gitignore b/.gitignore index 39c864c0..92481bc3 100644 --- a/.gitignore +++ b/.gitignore @@ -48,8 +48,8 @@ po/en@boldquot.insert-header po/en@quot.insert-header po/remove-potcdate.sed *.gmo -render/obrender-4.0.pc -obt/obt-4.0.pc +obrender/obrender-3.5.pc +obt/obt-3.5.pc tools/gnome-panel-control/gnome-panel-control tools/gdm-control/gdm-control tools/obxprop/obxprop diff --git a/CHANGELOG b/CHANGELOG index fd68f09b..8636efb3 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,276 @@ +3.5.0-rc1: + +3.4.9: + * Allow focus to move while inside an Openbox menu, or during an interactive + action such as window cycling. + * Fixed bug #3717 (Empty dock interfered with move/grow to edge actions). + * Fixed bug #4411 (Crash when switching desktops and window cycling). + * Fixed bug #4377 (Window resistance against struts). + * Fixed bug #4035 (Prevent focus from moving under the mouse after + activating a window with an Openbox menu. + * Correct the value provided by the _NET_WORKAREA hint, so desktop icons + will place across all monitors. + * Don't hide submenus immediately when moving through the parent menu. + (Resolves request #3762). + * Fix for showing Openbox menus with multiple monitors, don't restrict them + to the monitor where the mouse is. + * Fixed bug #4023 (Allow the user to have multiple keys which perform the + same function in Openbox menus/move/resize. E.g. two keys which are + both bound to Escape. + * Add a new obprop tool, which can be used to read the _OB_ROLE, _OB_NAME, + and _OB_CLASS (as well as any other UTF-8 window properties) off of a + window. + * Add _OB_ROLE, _OB_NAME, and _OB_CLASS hints on each window that show the + respective values for use in the rc.xml applications section, to modify + the window when it appears. + * Improve Openbox interoperability with gnome-session >= 2.24. + * Fixed bug #4040 (Remove desktop hints set by gdm in the openbox-session + scripts, so that Openbox can set the number of desktops (assuming + gnome-settings-daemon doesn't first)). + * Fix a bug in xdg-autostart preventing some .desktop files from working. + * Show the desktop pager popup on the primary monitor instead of on all + monitors. + * Add a new primaryMonitor config option, which is where Openbox popups + will appear. Defaults to a fixed monitor, but can be made to behave as + before with the "active" value for it. + * Correct edge detection for move/grow to edge to properly use monitor edges + for multi-monitor setups. + * Change default window placement policy to stay on the active monitor for + multi-monitor setups. + * Fixed bug #1149 (Crash with some window icon sizes). + * Respond to all strut changes, fixes moving/hiding panels. + * Fix internal code to focus windows on other desktops correctly (Fixes + bug #4413). + * Focus correctness fixups for switching desktops. + * Fixed bug #4373 (Decoration bug for shaded maximized windows). + * Fixed bug #4350 (Allow a window to be made skip_taskbar but still get + focused by the user's rc.xml). + * Fixed bug #4307 (Set a minimum time for screenEdgeWarpTime). + * Fixed bug #4253 (Support for Solaris in openbox-session scripts). + * Fixed bug #3851 (Allow transient windows to be above helper windows). + +3.4.8: + * Updated translations: Slovak. + * Allow windows to change their decorations at any time (Fix for + Google Chrome). + * Make openbox-session to respect the $XDG_CONFIG_HOME environment variable. + * Fixed bug #4344 where borders were given to windows that should not have + them. + * Merge the SessionLogout and Exit actions. They now test if connected to a + session manager and ask it to exit if so, or simply kill Openbox if not. + * Further tweaks to the _NET_ACTIVE_WINDOW message handling. Use the same + logic for focus-stealing as is used when mapping a new window. + * Don't go out of our way any more to prevent focus from moving while the + keyboard is grabbed. + * Fix openbox-gnome-session when using gnome-session > 2.22. + +3.4.8-rc2: + * Updated translations: Italian, Croatian, Ukrainian. + * When resizing a window while focus cycling with bar=no, the bar no longer + reappears. + * Correctly handle shaped windows using the ShapeInput kind, this is used + by many composited apps to pass through clicks in their transparent areas. + * Fix the per-app setting. + * Avoid using anonymous unions. + * Windows that had their decorations removed by per-app settings were still + placed as if they still had their decorations. + * Fix event handling not to ignore events on a window when they have an unmap + event in the queue, if that unmap event doesn't cause the window to be + unmanaged. + * Show the desktop switch on every monitor in xinerama. + * Fix interpretation of struts in xinerama where the screens have different + sizes. + * Add "next" and "prev" as possible targets in the moveto and + resizeto actions. + * Allow escaping the _ used to mark the shortcut character in menu labels. + You can now change the (first) _ in a label to __, this will be displayed + as a single underscore. The rest of the _ in the string will be unaffected, + so only double the first one. + * Only replace ~ with the home directory when it is preceded by whitespace or + is at the start of the string, and when it is followed by a space, slash, or + the end of the string. This is implemented with GRegex, and so the required + glib version has been bumped to 2.14. + * Some other small fixes. + +3.4.8-rc1: + * Updated translations: Basque, Catalan, Turkish, Italian, Spanish, Russian. + * New translations: Danish, Turkish, Lithuanian. + * Set the _MOTIF_WM_INFO atom so urxvt uses motif hints for borderless mode. + * Properly escape the xml used in session files. + * Correct a 64-bit issue related to comparing timestamps. + * There is a sneaky sentence right at the end of a big paragraph in the + wm-spec document that says windows mapping with _NET_WM_USER_TIME=0 should + not be focused initially, honor this request. + * When moving a window to another desktop with following on, bring the + window's helper windows (for example gimp image windows with the toolbox + set to utility window). + * Change the _NET_ACTIVE_WINDOW messages again, if they originate from the + app and the window is on another desktop, just set the demands_attention + flag. If the event came from the user (ie pager/panel), then the window + is still moved to the current desktop. + +3.4.7.2: + * The system I used to generate the dist tarball didn't have the + docbook-to-man command so the manpages were empty. + +3.4.7.1: + * Not to be outdone by the cairo team, I introduced a bug in the last release + which made resizing not give any feedback. This is now fixed. + +3.4.7: + * Fully updated Czech, Simplified Chinese, Traditional Chinese, German, + French, Hungarian, Norwegian, Vietnamese, Dutch, Swedish, Finnish, + Brazilian Portuguese, Japanese and Portuguese translations + * Partially updated Spanish translation + * Add an example of the "force" option for the per-app placement options to + the default rc.xml file + * Add a new xdg-autostart script. This will eventually end up in the PyXDG + distribution hopefully, but it is included in Openbox for now. This script + runs things based on the freedesktop.org autostart specification. You can + have it run GNOME, KDE, ROX, or XFCE specific things if you want. The + new default system-wide autostart.sh script runs it automatically + * Update the default menu.xml to include a lot of common apps + * Fix white font shadows (negative shadowtint) + * Update the autostart.sh to find gnome-settings-daemon correctly, as the + GNOME people have moved it to libexec + * Fix focus possibly getting stolen when using the Focus action + * Drastically speed up rendering of Vertical and SplitVertical gradients + * Speed improvements also for Horizonal and Pyramid gradients + * Add new theme options, menu.overlap.x and menu.overlap.y options, that let + you independently control the horizontal and vertical position of submenus + * Change _NET_ACTIVE_WINDOW messages to not change the current desktop, but + to bring the window to the current desktop instead. This is the industry + standard policy + * Use the pretty new openbox.png icon as the default window icon + * Allow matching per-application rules to windows by their window type + (normal, dialog, splash, etc). The default rc.xml has more details + * Add new Openbox-themed prompt windows. Use these prompt windows to ask + before killing off windows that aren't responding. This also means we + don't need to ping every window constantly forever + * Add a new option to the Execute action. If this is set to a + string, a dialog will be shown with that string in it and "yes"/"no" + buttons. The command to be executed will only be run if the user selects + "yes" in the dialog + * Add a new option to the Exit action, which is a boolean (not a + string). When true, Openbox will show a dialog confirming if you want to + exit. The default is to show the prompt + * Reduce Openbox's memory footprint and speed up rendering through the use + of a new icon cache, so that Openbox only needs to keep 1 copy of an icon + when 100 different windows share it + * Make Openbox menus have the "menu type" hint for compositors to see and use + * Fix the MoveResizeTo action for negative coords (opposite edges) + * Fix key bindings getting lost if multiple bindings at the same level could + not be translated (Fixes VMWare causing Openbox keybindings to stop + working) + * Fix the resize popup box for terminal windows with a base size of 0 (show + the right size values for urxvt terminals) + * Fix some off-by-one bugs with the edge growing/shrinking code + * Add new theme options for menu line separators: menu.separator.color, + menu.separator.width, menu.separator.padding.width, + menu.separator.padding.height + * Add xfce-mcs-manager to the default autostart.sh, and run it automatically + when gnome-settings-daemon is not present to have GTK apps inherit settings + from the XFCE configuration tools + * Make the send-to-desktop menu in the client-menu indicate which is the current + desktop for omnipresent windows, and don't close it if just toggling + omni-presence when ctrl-clicking + * Add a new SessionLogout action that logs out through the session manager, + when running Openbox within a session manager such as within an + GNOME/Openbox or KDE/Openbox session. The action includes a + option which is similar to the Exit action's + * Add a new gdm-control command that lets you control gdm from within an X + session. The gdm-control lets you change GDM's behaviour for when you end + the current session. For instance, you can tell GDM to reboot, and + then immediately log out of the current session, and the computer will be + rebooted + * Show an information dialog when an error occurs for Openbox, such as when + the Execute action fails or when XML syntax errors are present in the + configuration files + * When making a window very narrow, don't draw buttons to the right of the title + on top of the ones on its left. + +3.4.6.1: + * Updated Clearlooks theme + * Add the force="yes/no" option for the per-app settings' tag + * Raise and focus modal children and their direct parents together, improved + usability with direct modal transient windows + * Fix crash when using for NextWindow and there are no windows + to move focus to + * Add the option in the rc.xml section, which toggles + the "Manage Desktops" section appearing in the combined-client-list-menu + * Fix for menu headers showing the wrong text + * Fix for the behavior + * Treat modal direct children as one window with their parent consistently + +3.4.6: + * Added Basque translation + * Updated French, Vietnamese German, Simplified Chinese, Russian, Portuguese, + Brasilian Portuguese, Norwegian, and Finnish translations + * New Clearlooks theme, updated by David Barr + * Updated the previous Clearlooks theme, and renamed it to Clearlooks-3.4 + * Allow dialog type windows to go fullscreen (Fixes Kpdf) + * Remove the extraneous top border for undecorated windows while maximized + * Fixes for keyboard modifiers (Alt-tab dialog getting stuck on screen for + some users) + * Automatically catch changes to the keyboard map and reconfigure the key + bindings on the fly + * Fix focus moving incorrectly sometimes with focus under mouse enabled + * Make default configuration focus the desktop when you right click + * Add the and options for all window cycling actions, allowing + you to have your target window temporarily raised above all others, and to + turn the focus target indicator bar off + * Improve the LastDesktop action to not remember desktops you skipped across + * Ignore mouse clicks that are made on override-redirect (unmanaged) windows + * When opening a menu with a key binding, don't use the key binding to run + something in the menu + * Add a option for window placement, which gives you the option + to place new windows on the active monitor, or the monitor where the mouse + is, instead of on any monitor (for xinerama multihead setups) + * Add options for placing the window move/resize coordinate popup window in + a fixed position on screen, rather than relative to the window being + moved or resized + * Prevent the dock from auto-hiding completely offscreen if the theme has + no borders for it + * New icon + * Fix race condition when running things that want to grab the keyboard + (e.g. gnome-panel-control --main-menu) + * When dialog windows ask to not appear in the taskbar, still give them focus + in normal ways (fixes new GNOME session logout dialogs) + * Fix bug with resizing corners on certain parts of the window frame + * Ping applications to tell when they are running or have become frozen. + Show a [Not Responding] message in the title bar of windows which are + frozen. + * When closing a window which is [Not Responding], kill the window's process + if it is running on the same machine as Openbox. Otherwise, just + disconnect + the window from the X display. A second attempt to close a [Not + Responding] + window will kill it forcefully (kill -9). + * Fixes for internal timers + * Add a option for the execute action's startup-notification. This + lets you tell Openbox that the application will map a window with the + specified class - for applications that do not support startup-notification + natively. + * Fix for empty dock taking up space onscreen after a reconfigure + * Reduce Openbox's additional memory footprint per-window and per-menu + * Faster horizontal gradient rendering + * Don't deiconify windows that aren't allowed to be directly iconified on + restart (eg toolbars), as they can be iconified by other means + * Improve support for fullscreen windows in xinerama (TwinView) and + multiple-screen setups + * Add a --config-file command line option, to specify an alternate + configuration file path + +3.4.5: + * Added Hungarian translation + * Updated Finnish, Russian, German and French translations + * Fixed some very minor memory leaks + * Hide the desktop popup when showing the focus popup + * Fix a crash when trying to access the More... menu of + client-list-combined-menu + * Fix the coordinate popup only showing up on the first monitor in xinerama + * Add --exit to exit the currently running openbox instance + 3.4.4: * Updated Traditional Chinese translation * Updated Norwegian translation diff --git a/Makefile.am b/Makefile.am index 3934b62f..0bcb8b28 100644 --- a/Makefile.am +++ b/Makefile.am @@ -9,7 +9,7 @@ xsessionsdir = $(datadir)/xsessions gnomewmfilesdir = $(datadir)/gnome/wm-properties pkgconfigdir = $(libdir)/pkgconfig obtpubincludedir= $(includedir)/openbox/@OBT_VERSION@/obt -rrpubincludedir = $(includedir)/openbox/@RR_VERSION@/render +rrpubincludedir = $(includedir)/openbox/@RR_VERSION@/obrender pixmapdir = $(datadir)/pixmaps xsddir = $(datadir)/openbox secretbindir = $(libdir)/openbox @@ -24,11 +24,11 @@ ACLOCAL_AMFLAGS = -I m4 INCLUDES = -I. check_PROGRAMS = \ - render/rendertest + obrender/rendertest lib_LTLIBRARIES = \ obt/libobt.la \ - render/libobrender.la + obrender/libobrender.la bin_PROGRAMS = \ openbox/openbox \ @@ -44,58 +44,58 @@ nodist_bin_SCRIPTS = \ data/xsession/openbox-gnome-session \ data/xsession/openbox-kde-session -## render ## +## obrender ## -render_rendertest_CPPFLAGS = \ +obrender_rendertest_CPPFLAGS = \ $(PANGO_CFLAGS) \ $(GLIB_CFLAGS) \ -DG_LOG_DOMAIN=\"RenderTest\" -render_rendertest_LDADD = \ +obrender_rendertest_LDADD = \ obt/libobt.la \ - render/libobrender.la \ + obrender/libobrender.la \ $(GLIB_LIBS) \ $(PANGO_LIBS) \ $(XML_LIBS) \ $(X_LIBS) -render_rendertest_SOURCES = render/test.c +obrender_rendertest_SOURCES = obrender/test.c -render_libobrender_la_CPPFLAGS = \ +obrender_libobrender_la_CPPFLAGS = \ $(X_CFLAGS) \ $(GLIB_CFLAGS) \ $(XML_CFLAGS) \ $(PANGO_CFLAGS) \ -DG_LOG_DOMAIN=\"ObRender\" \ -DDEFAULT_THEME=\"$(theme)\" -render_libobrender_la_LDFLAGS = \ +obrender_libobrender_la_LDFLAGS = \ -version-info $(RR_CURRENT):$(RR_REVISION):$(RR_AGE) -render_libobrender_la_LIBADD = \ +obrender_libobrender_la_LIBADD = \ obt/libobt.la \ $(X_LIBS) \ $(PANGO_LIBS) \ $(GLIB_LIBS) \ $(XML_LIBS) -render_libobrender_la_SOURCES = \ +obrender_libobrender_la_SOURCES = \ gettext.h \ - render/color.h \ - render/color.c \ - render/font.h \ - render/font.c \ - render/geom.h \ - render/gradient.h \ - render/gradient.c \ - render/icon.h \ - render/image.h \ - render/image.c \ - render/imagecache.h \ - render/imagecache.c \ - render/instance.h \ - render/instance.c \ - render/mask.h \ - render/mask.c \ - render/render.h \ - render/render.c \ - render/theme.h \ - render/theme.c + obrender/color.h \ + obrender/color.c \ + obrender/font.h \ + obrender/font.c \ + obrender/geom.h \ + obrender/gradient.h \ + obrender/gradient.c \ + obrender/icon.h \ + obrender/image.h \ + obrender/image.c \ + obrender/imagecache.h \ + obrender/imagecache.c \ + obrender/instance.h \ + obrender/instance.c \ + obrender/mask.h \ + obrender/mask.c \ + obrender/render.h \ + obrender/render.c \ + obrender/theme.h \ + obrender/theme.c ## obt ## @@ -163,7 +163,7 @@ openbox_openbox_LDADD = \ $(XML_LIBS) \ $(EFENCE_LIBS) \ $(LIBINTL) \ - render/libobrender.la \ + obrender/libobrender.la \ obt/libobt.la openbox_openbox_LDFLAGS = -export-dynamic openbox_openbox_SOURCES = \ @@ -408,16 +408,16 @@ dist_syscrash_theme_DATA= \ ## public headers ## rrpubinclude_HEADERS = \ - render/color.h \ - render/font.h \ - render/geom.h \ - render/gradient.h \ - render/image.h \ - render/instance.h \ - render/mask.h \ - render/render.h \ - render/theme.h \ - render/version.h + obrender/color.h \ + obrender/font.h \ + obrender/geom.h \ + obrender/gradient.h \ + obrender/image.h \ + obrender/instance.h \ + obrender/mask.h \ + obrender/render.h \ + obrender/theme.h \ + obrender/version.h obtpubinclude_HEADERS = \ obt/display.h \ @@ -431,8 +431,8 @@ obtpubinclude_HEADERS = \ obt/xevent.h nodist_pkgconfig_DATA = \ - render/obrender-4.0.pc \ - obt/obt-4.0.pc + obrender/obrender-3.5.pc \ + obt/obt-3.5.pc ## data ## @@ -501,9 +501,9 @@ dist_noinst_DATA = \ doc/openbox-gnome-session.1.in \ doc/openbox-kde-session.1.sgml \ doc/openbox-kde-session.1.in \ - render/version.h.in \ - render/obrender-4.0.pc.in \ - obt/obt-4.0.pc.in \ + obrender/version.h.in \ + obrender/obrender-3.5.pc.in \ + obt/obt-3.5.pc.in \ obt/version.h.in \ tools/themeupdate/themeupdate.py \ tests/hideshow.py \ @@ -560,7 +560,7 @@ CLEANFILES = \ # $(MAKE) -$(MAKEFLAGS) -C doc/doxygen doc distclean-local: - for d in . m4 po render parser obt openbox; do \ + for d in . m4 po obrender parser obt openbox; do \ for p in core core.* gmon.out *\~ *.orig *.rej .\#*; do \ rm -f "$$d/$$p"; \ done \ diff --git a/configure.ac b/configure.ac index 78d0753e..379440a2 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ([2.54]) -AC_INIT([openbox], [3.999.0], [http://bugzilla.icculus.org]) +AC_INIT([openbox], [3.5.0-rc1], [http://bugzilla.icculus.org]) AM_INIT_AUTOMAKE AC_CONFIG_SRCDIR([openbox/openbox.c]) @@ -13,15 +13,15 @@ dnl set RR_BINARY_AGE and RR_INTERFACE_AGE to 0. dnl dnl if MAJOR or MINOR version changes, be sure to change AC_INIT above to match dnl -RR_MAJOR_VERSION=4 -RR_MINOR_VERSION=0 -RR_MICRO_VERSION=17 +RR_MAJOR_VERSION=3 +RR_MINOR_VERSION=5 +RR_MICRO_VERSION=27 RR_INTERFACE_AGE=0 RR_BINARY_AGE=0 RR_VERSION=$RR_MAJOR_VERSION.$RR_MINOR_VERSION -OBT_MAJOR_VERSION=4 -OBT_MINOR_VERSION=0 +OBT_MAJOR_VERSION=3 +OBT_MINOR_VERSION=5 OBT_MICRO_VERSION=0 OBT_INTERFACE_AGE=0 OBT_BINARY_AGE=0 @@ -174,9 +174,9 @@ AC_CONFIG_FILES([ Makefile m4/Makefile po/Makefile.in - render/obrender-4.0.pc - obt/obt-4.0.pc - render/version.h + obrender/obrender-3.5.pc + obt/obt-3.5.pc + obrender/version.h obt/version.h ]) AC_CONFIG_COMMANDS([doc], diff --git a/obrender/Makefile b/obrender/Makefile new file mode 100644 index 00000000..b90edacf --- /dev/null +++ b/obrender/Makefile @@ -0,0 +1,4 @@ +all clean install: + $(MAKE) -C .. -$(MAKEFLAGS) $@ + +.PHONY: all clean install diff --git a/obrender/color.c b/obrender/color.c new file mode 100644 index 00000000..5e3f2169 --- /dev/null +++ b/obrender/color.c @@ -0,0 +1,361 @@ +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + color.c for the Openbox window manager + Copyright (c) 2006 Mikael Magnusson + Copyright (c) 2003-2007 Dana Jansens + Copyright (c) 2003 Derek Foreman + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + See the COPYING file for a copy of the GNU General Public License. +*/ + +#include "render.h" +#include "color.h" +#include "instance.h" + +#include +#include +#include + +void RrColorAllocateGC(RrColor *in) +{ + XGCValues gcv; + + gcv.foreground = in->pixel; + gcv.cap_style = CapProjecting; + in->gc = XCreateGC(RrDisplay(in->inst), + RrRootWindow(in->inst), + GCForeground | GCCapStyle, &gcv); +} + +RrColor *RrColorParse(const RrInstance *inst, gchar *colorname) +{ + XColor xcol; + + g_assert(colorname != NULL); + /* get rgb values from colorname */ + + xcol.red = 0; + xcol.green = 0; + xcol.blue = 0; + xcol.pixel = 0; + if (!XParseColor(RrDisplay(inst), RrColormap(inst), colorname, &xcol)) { + g_message("Unable to parse color '%s'", colorname); + return NULL; + } + return RrColorNew(inst, xcol.red >> 8, xcol.green >> 8, xcol.blue >> 8); +} + +/*#define NO_COLOR_CACHE*/ +#ifdef DEBUG +gint id; +#endif + +RrColor *RrColorNew(const RrInstance *inst, gint r, gint g, gint b) +{ + /* this should be replaced with something far cooler */ + RrColor *out = NULL; + XColor xcol; + gint key; + + g_assert(r >= 0 && r < 256); + g_assert(g >= 0 && g < 256); + g_assert(b >= 0 && b < 256); + + key = (r << 24) + (g << 16) + (b << 8); +#ifndef NO_COLOR_CACHE + if ((out = g_hash_table_lookup(RrColorHash(inst), &key))) { + out->refcount++; + } else { +#endif + xcol.red = (r << 8) | r; + xcol.green = (g << 8) | g; + xcol.blue = (b << 8) | b; + if (XAllocColor(RrDisplay(inst), RrColormap(inst), &xcol)) { + out = g_new(RrColor, 1); + out->inst = inst; + out->r = xcol.red >> 8; + out->g = xcol.green >> 8; + out->b = xcol.blue >> 8; + out->gc = None; + out->pixel = xcol.pixel; + out->key = key; + out->refcount = 1; +#ifdef DEBUG + out->id = id++; +#endif +#ifndef NO_COLOR_CACHE + g_hash_table_insert(RrColorHash(inst), &out->key, out); + } +#endif + } + return out; +} + +void RrColorFree(RrColor *c) +{ + if (c) { + if (--c->refcount < 1) { +#ifndef NO_COLOR_CACHE + g_assert(g_hash_table_lookup(RrColorHash(c->inst), &c->key)); + g_hash_table_remove(RrColorHash(c->inst), &c->key); +#endif + if (c->pixel) XFreeColors(RrDisplay(c->inst), RrColormap(c->inst), + &c->pixel, 1, 0); + if (c->gc) XFreeGC(RrDisplay(c->inst), c->gc); + g_free(c); + } + } +} + +void RrReduceDepth(const RrInstance *inst, RrPixel32 *data, XImage *im) +{ + gint r, g, b; + gint x,y; + RrPixel32 *p32 = (RrPixel32 *) im->data; + RrPixel16 *p16 = (RrPixel16 *) im->data; + RrPixel8 *p8 = (RrPixel8 *) im->data; + switch (im->bits_per_pixel) { + case 32: + if ((RrRedOffset(inst) != RrDefaultRedOffset) || + (RrBlueOffset(inst) != RrDefaultBlueOffset) || + (RrGreenOffset(inst) != RrDefaultGreenOffset)) { + for (y = 0; y < im->height; y++) { + for (x = 0; x < im->width; x++) { + r = (data[x] >> RrDefaultRedOffset) & 0xFF; + g = (data[x] >> RrDefaultGreenOffset) & 0xFF; + b = (data[x] >> RrDefaultBlueOffset) & 0xFF; + p32[x] = (r << RrRedOffset(inst)) + + (g << RrGreenOffset(inst)) + + (b << RrBlueOffset(inst)); + } + data += im->width; + p32 += im->width; + } + } else im->data = (gchar*) data; + break; + case 24: + { + /* reverse the ordering, shifting left 16bit should be the first byte + out of three, etc */ + const guint roff = (16 - RrRedOffset(inst)) / 8; + const guint goff = (16 - RrGreenOffset(inst)) / 8; + const guint boff = (16 - RrBlueOffset(inst)) / 8; + gint outx; + for (y = 0; y < im->height; y++) { + for (x = 0, outx = 0; x < im->width; x++, outx += 3) { + r = (data[x] >> RrDefaultRedOffset) & 0xFF; + g = (data[x] >> RrDefaultGreenOffset) & 0xFF; + b = (data[x] >> RrDefaultBlueOffset) & 0xFF; + p8[outx+roff] = r; + p8[outx+goff] = g; + p8[outx+boff] = b; + } + data += im->width; + p8 += im->bytes_per_line; + } + break; + } + case 16: + for (y = 0; y < im->height; y++) { + for (x = 0; x < im->width; x++) { + r = (data[x] >> RrDefaultRedOffset) & 0xFF; + r = r >> RrRedShift(inst); + g = (data[x] >> RrDefaultGreenOffset) & 0xFF; + g = g >> RrGreenShift(inst); + b = (data[x] >> RrDefaultBlueOffset) & 0xFF; + b = b >> RrBlueShift(inst); + p16[x] = (r << RrRedOffset(inst)) + + (g << RrGreenOffset(inst)) + + (b << RrBlueOffset(inst)); + } + data += im->width; + p16 += im->bytes_per_line/2; + } + break; + case 8: + if (RrVisual(inst)->class == TrueColor) { + for (y = 0; y < im->height; y++) { + for (x = 0; x < im->width; x++) { + r = (data[x] >> RrDefaultRedOffset) & 0xFF; + r = r >> RrRedShift(inst); + g = (data[x] >> RrDefaultGreenOffset) & 0xFF; + g = g >> RrGreenShift(inst); + b = (data[x] >> RrDefaultBlueOffset) & 0xFF; + b = b >> RrBlueShift(inst); + p8[x] = (r << RrRedOffset(inst)) + + (g << RrGreenOffset(inst)) + + (b << RrBlueOffset(inst)); + } + data += im->width; + p8 += im->bytes_per_line; + } + } else { + for (y = 0; y < im->height; y++) { + for (x = 0; x < im->width; x++) { + p8[x] = RrPickColor(inst, + data[x] >> RrDefaultRedOffset, + data[x] >> RrDefaultGreenOffset, + data[x] >> RrDefaultBlueOffset)->pixel; + } + data += im->width; + p8 += im->bytes_per_line; + } + } + break; + default: + g_error("This image bit depth (%i) is currently unhandled", im->bits_per_pixel); + + } +} + +XColor *RrPickColor(const RrInstance *inst, gint r, gint g, gint b) +{ + r = (r & 0xff) >> (8-RrPseudoBPC(inst)); + g = (g & 0xff) >> (8-RrPseudoBPC(inst)); + b = (b & 0xff) >> (8-RrPseudoBPC(inst)); + return &RrPseudoColors(inst)[(r << (2*RrPseudoBPC(inst))) + + (g << (1*RrPseudoBPC(inst))) + + b]; +} + +static void swap_byte_order(XImage *im) +{ + gint x, y, di; + + di = 0; + for (y = 0; y < im->height; ++y) { + for (x = 0; x < im->height; ++x) { + gchar *c = &im->data[di + x * im->bits_per_pixel / 8]; + gchar t; + + switch (im->bits_per_pixel) { + case 32: + t = c[2]; + c[2] = c[3]; + c[3] = t; + case 16: + t = c[0]; + c[0] = c[1]; + c[1] = t; + case 8: + case 1: + break; + default: + g_error("Your bit depth (%i) is currently unhandled", + im->bits_per_pixel); + } + } + di += im->bytes_per_line; + } + + if (im->byte_order == LSBFirst) + im->byte_order = MSBFirst; + else + im->byte_order = LSBFirst; +} + +void RrIncreaseDepth(const RrInstance *inst, RrPixel32 *data, XImage *im) +{ + gint r, g, b; + gint x,y; + RrPixel32 *p32 = (RrPixel32 *) im->data; + RrPixel16 *p16 = (RrPixel16 *) im->data; + guchar *p8 = (guchar *)im->data; + + if (im->byte_order != LSBFirst) + swap_byte_order(im); + + switch (im->bits_per_pixel) { + case 32: + for (y = 0; y < im->height; y++) { + for (x = 0; x < im->width; x++) { + r = (p32[x] >> RrRedOffset(inst)) & 0xff; + g = (p32[x] >> RrGreenOffset(inst)) & 0xff; + b = (p32[x] >> RrBlueOffset(inst)) & 0xff; + data[x] = (r << RrDefaultRedOffset) + + (g << RrDefaultGreenOffset) + + (b << RrDefaultBlueOffset) + + (0xff << RrDefaultAlphaOffset); + } + data += im->width; + p32 += im->bytes_per_line/4; + } + break; + case 16: + for (y = 0; y < im->height; y++) { + for (x = 0; x < im->width; x++) { + r = (p16[x] & RrRedMask(inst)) >> + RrRedOffset(inst) << + RrRedShift(inst); + g = (p16[x] & RrGreenMask(inst)) >> + RrGreenOffset(inst) << + RrGreenShift(inst); + b = (p16[x] & RrBlueMask(inst)) >> + RrBlueOffset(inst) << + RrBlueShift(inst); + data[x] = (r << RrDefaultRedOffset) + + (g << RrDefaultGreenOffset) + + (b << RrDefaultBlueOffset) + + (0xff << RrDefaultAlphaOffset); + } + data += im->width; + p16 += im->bytes_per_line/2; + } + break; + case 8: + g_error("This image bit depth (%i) is currently unhandled", 8); + break; + case 1: + for (y = 0; y < im->height; y++) { + for (x = 0; x < im->width; x++) { + if (!(((p8[x / 8]) >> (x % 8)) & 0x1)) + data[x] = 0xff << RrDefaultAlphaOffset; /* black */ + else + data[x] = 0xffffffff; /* white */ + } + data += im->width; + p8 += im->bytes_per_line; + } + break; + default: + g_error("This image bit depth (%i) is currently unhandled", + im->bits_per_pixel); + } +} + +gint RrColorRed(const RrColor *c) +{ + return c->r; +} + +gint RrColorGreen(const RrColor *c) +{ + return c->g; +} + +gint RrColorBlue(const RrColor *c) +{ + return c->b; +} + +gulong RrColorPixel(const RrColor *c) +{ + return c->pixel; +} + +GC RrColorGC(RrColor *c) +{ + if (!c->gc) + RrColorAllocateGC(c); + return c->gc; +} diff --git a/obrender/color.h b/obrender/color.h new file mode 100644 index 00000000..26fa7afe --- /dev/null +++ b/obrender/color.h @@ -0,0 +1,51 @@ +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + color.h for the Openbox window manager + Copyright (c) 2003-2007 Dana Jansens + Copyright (c) 2003 Derek Foreman + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + See the COPYING file for a copy of the GNU General Public License. +*/ + +#ifndef __color_h +#define __color_h + +#include "render.h" + +#include +#include +#include + +struct _RrColor { + const RrInstance *inst; + + gint r; + gint g; + gint b; + gulong pixel; + GC gc; + + gint key; + gint refcount; + +#ifdef DEBUG + gint id; +#endif +}; + +void RrColorAllocateGC(RrColor *in); +XColor *RrPickColor(const RrInstance *inst, gint r, gint g, gint b); +void RrReduceDepth(const RrInstance *inst, RrPixel32 *data, XImage *im); +void RrIncreaseDepth(const RrInstance *inst, RrPixel32 *data, XImage *im); + +#endif /* __color_h */ diff --git a/obrender/font.c b/obrender/font.c new file mode 100644 index 00000000..cde0d030 --- /dev/null +++ b/obrender/font.c @@ -0,0 +1,380 @@ +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + font.c for the Openbox window manager + Copyright (c) 2006 Mikael Magnusson + Copyright (c) 2003-2007 Dana Jansens + Copyright (c) 2003 Derek Foreman + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + See the COPYING file for a copy of the GNU General Public License. +*/ + +#include "font.h" +#include "color.h" +#include "mask.h" +#include "theme.h" +#include "geom.h" +#include "instance.h" +#include "gettext.h" + +#include +#include +#include +#include + +static void measure_font(const RrInstance *inst, RrFont *f) +{ + PangoFontMetrics *metrics; + static PangoLanguage *lang = NULL; + + if (lang == NULL) { +#if PANGO_VERSION_MAJOR > 1 || \ + (PANGO_VERSION_MAJOR == 1 && PANGO_VERSION_MINOR >= 16) + lang = pango_language_get_default(); +#else + gchar *locale, *p; + /* get the default language from the locale + (based on gtk_get_default_language in gtkmain.c) */ + locale = g_strdup(setlocale(LC_CTYPE, NULL)); + if ((p = strchr(locale, '.'))) *p = '\0'; /* strip off the . */ + if ((p = strchr(locale, '@'))) *p = '\0'; /* strip off the @ */ + lang = pango_language_from_string(locale); + g_free(locale); +#endif + } + + /* measure the ascent and descent */ + metrics = pango_context_get_metrics(inst->pango, f->font_desc, lang); + f->ascent = pango_font_metrics_get_ascent(metrics); + f->descent = pango_font_metrics_get_descent(metrics); + pango_font_metrics_unref(metrics); + +} + +RrFont *RrFontOpen(const RrInstance *inst, const gchar *name, gint size, + RrFontWeight weight, RrFontSlant slant) +{ + RrFont *out; + PangoWeight pweight; + PangoStyle pstyle; + PangoAttrList *attrlist; + + out = g_new(RrFont, 1); + out->inst = inst; + out->ref = 1; + out->font_desc = pango_font_description_new(); + out->layout = pango_layout_new(inst->pango); + out->shortcut_underline = pango_attr_underline_new(PANGO_UNDERLINE_LOW); + out->shortcut_underline->start_index = 0; + out->shortcut_underline->end_index = 0; + + attrlist = pango_attr_list_new(); + /* shortcut_underline is owned by the attrlist */ + pango_attr_list_insert(attrlist, out->shortcut_underline); + /* the attributes are owned by the layout */ + pango_layout_set_attributes(out->layout, attrlist); + pango_attr_list_unref(attrlist); + + switch (weight) { + case RR_FONTWEIGHT_LIGHT: pweight = PANGO_WEIGHT_LIGHT; break; + case RR_FONTWEIGHT_NORMAL: pweight = PANGO_WEIGHT_NORMAL; break; + case RR_FONTWEIGHT_SEMIBOLD: pweight = PANGO_WEIGHT_SEMIBOLD; break; + case RR_FONTWEIGHT_BOLD: pweight = PANGO_WEIGHT_BOLD; break; + case RR_FONTWEIGHT_ULTRABOLD: pweight = PANGO_WEIGHT_ULTRABOLD; break; + default: g_assert_not_reached(); + } + + switch (slant) { + case RR_FONTSLANT_NORMAL: pstyle = PANGO_STYLE_NORMAL; break; + case RR_FONTSLANT_ITALIC: pstyle = PANGO_STYLE_ITALIC; break; + case RR_FONTSLANT_OBLIQUE: pstyle = PANGO_STYLE_OBLIQUE; break; + default: g_assert_not_reached(); + } + + /* setup the font */ + pango_font_description_set_family(out->font_desc, name); + pango_font_description_set_weight(out->font_desc, pweight); + pango_font_description_set_style(out->font_desc, pstyle); + pango_font_description_set_size(out->font_desc, size * PANGO_SCALE); + + /* setup the layout */ + pango_layout_set_font_description(out->layout, out->font_desc); + pango_layout_set_wrap(out->layout, PANGO_WRAP_WORD_CHAR); + + /* get the ascent and descent */ + measure_font(inst, out); + + return out; +} + +RrFont *RrFontOpenDefault(const RrInstance *inst) +{ + return RrFontOpen(inst, RrDefaultFontFamily, RrDefaultFontSize, + RrDefaultFontWeight, RrDefaultFontSlant); +} + +void RrFontRef(RrFont *f) +{ + ++f->ref; +} + +void RrFontClose(RrFont *f) +{ + if (f) { + if (--f->ref < 1) { + g_object_unref(f->layout); + pango_font_description_free(f->font_desc); + g_free(f); + } + } +} + +static void font_measure_full(const RrFont *f, const gchar *str, + gint *x, gint *y, gint shadow_x, gint shadow_y, + gboolean flow, gint maxwidth) +{ + PangoRectangle rect; + + pango_layout_set_text(f->layout, str, -1); + if (flow) { + pango_layout_set_single_paragraph_mode(f->layout, FALSE); + pango_layout_set_width(f->layout, maxwidth * PANGO_SCALE); + pango_layout_set_ellipsize(f->layout, PANGO_ELLIPSIZE_NONE); + } + else { + /* single line mode */ + pango_layout_set_single_paragraph_mode(f->layout, TRUE); + pango_layout_set_width(f->layout, -1); + pango_layout_set_ellipsize(f->layout, PANGO_ELLIPSIZE_MIDDLE); + } + + /* pango_layout_get_pixel_extents lies! this is the right way to get the + size of the text's area */ + pango_layout_get_extents(f->layout, NULL, &rect); +#if PANGO_VERSION_MAJOR > 1 || \ + (PANGO_VERSION_MAJOR == 1 && PANGO_VERSION_MINOR >= 16) + /* pass the logical rect as the ink rect, this is on purpose so we get the + full area for the text */ + pango_extents_to_pixels(&rect, NULL); +#else + rect.width = (rect.width + PANGO_SCALE - 1) / PANGO_SCALE; + rect.height = (rect.height + PANGO_SCALE - 1) / PANGO_SCALE; +#endif + *x = rect.width + ABS(shadow_x) + 4 /* we put a 2 px edge on each side */; + *y = rect.height + ABS(shadow_y); +} + +RrSize *RrFontMeasureString(const RrFont *f, const gchar *str, + gint shadow_x, gint shadow_y, + gboolean flow, gint maxwidth) +{ + RrSize *size; + + g_assert(!flow || maxwidth > 0); + + size = g_new(RrSize, 1); + font_measure_full(f, str, &size->width, &size->height, shadow_x, shadow_y, + flow, maxwidth); + return size; +} + +gint RrFontHeight(const RrFont *f, gint shadow_y) +{ + return (f->ascent + f->descent) / PANGO_SCALE + ABS(shadow_y); +} + +static inline int font_calculate_baseline(RrFont *f, gint height) +{ +/* For my own reference: + * _________ + * ^space/2 ^height ^baseline + * v_________|_ | + * | ^ascent | _ _ + * | | | | |_ _____ _| |_ _ _ + * | | | | _/ -_) \ / _| || | + * | v_________v \__\___/_\_\\__|\_, | + * | ^descent |__/ + * __________|_v + * ^space/2 | + * V_________v + */ + return (((height * PANGO_SCALE) /* height of the space in pango units */ + - (f->ascent + f->descent)) /* minus space taken up by text */ + / 2 /* divided by two -> half of the empty space (this is the top + of the text) */ + + f->ascent) /* now move down to the baseline */ + / PANGO_SCALE; /* back to pixels */ +} + +void RrFontDraw(XftDraw *d, RrTextureText *t, RrRect *area) +{ + gint x,y,w; + XftColor c; + gint mw; + PangoRectangle rect; + PangoAttrList *attrlist; + PangoEllipsizeMode ell; + + g_assert(!t->flow || t->maxwidth > 0); + + y = area->y; + if (!t->flow) + /* center the text vertically + We do this centering based on the 'baseline' since different fonts + have different top edges. It looks bad when the whole string is + moved when 1 character from a non-default language is included in + the string */ + y += font_calculate_baseline(t->font, area->height); + + /* the +2 and -4 leave a small blank edge on the sides */ + x = area->x + 2; + w = area->width; + if (t->flow) w = MAX(w, t->maxwidth); + w -= 4; + /* h = area->height; */ + + if (t->flow) + ell = PANGO_ELLIPSIZE_NONE; + else { + switch (t->ellipsize) { + case RR_ELLIPSIZE_NONE: + ell = PANGO_ELLIPSIZE_NONE; + break; + case RR_ELLIPSIZE_START: + ell = PANGO_ELLIPSIZE_START; + break; + case RR_ELLIPSIZE_MIDDLE: + ell = PANGO_ELLIPSIZE_MIDDLE; + break; + case RR_ELLIPSIZE_END: + ell = PANGO_ELLIPSIZE_END; + break; + default: + g_assert_not_reached(); + } + } + + pango_layout_set_text(t->font->layout, t->string, -1); + pango_layout_set_width(t->font->layout, w * PANGO_SCALE); + pango_layout_set_ellipsize(t->font->layout, ell); + pango_layout_set_single_paragraph_mode(t->font->layout, !t->flow); + + /* * * end of setting up the layout * * */ + + pango_layout_get_pixel_extents(t->font->layout, NULL, &rect); + mw = rect.width; + + /* pango_layout_set_alignment doesn't work with + pango_xft_render_layout_line */ + switch (t->justify) { + case RR_JUSTIFY_LEFT: + break; + case RR_JUSTIFY_RIGHT: + x += (w - mw); + break; + case RR_JUSTIFY_CENTER: + x += (w - mw) / 2; + break; + } + + if (t->shadow_offset_x || t->shadow_offset_y) { + /* From nvidia's readme (chapter 23): + + When rendering to a 32-bit window, keep in mind that the X RENDER + extension, used by most composite managers, expects "premultiplied + alpha" colors. This means that if your color has components (r,g,b) + and alpha value a, then you must render (a*r, a*g, a*b, a) into the + target window. + */ + c.color.red = (t->shadow_color->r | t->shadow_color->r << 8) * + t->shadow_alpha / 255; + c.color.green = (t->shadow_color->g | t->shadow_color->g << 8) * + t->shadow_alpha / 255; + c.color.blue = (t->shadow_color->b | t->shadow_color->b << 8) * + t->shadow_alpha / 255; + c.color.alpha = 0xffff * t->shadow_alpha / 255; + c.pixel = t->shadow_color->pixel; + + /* see below... */ + if (!t->flow) { + pango_xft_render_layout_line + (d, &c, +#if PANGO_VERSION_MAJOR > 1 || \ + (PANGO_VERSION_MAJOR == 1 && PANGO_VERSION_MINOR >= 16) + pango_layout_get_line_readonly(t->font->layout, 0), +#else + pango_layout_get_line(t->font->layout, 0), +#endif + (x + t->shadow_offset_x) * PANGO_SCALE, + (y + t->shadow_offset_y) * PANGO_SCALE); + } + else { + pango_xft_render_layout(d, &c, t->font->layout, + (x + t->shadow_offset_x) * PANGO_SCALE, + (y + t->shadow_offset_y) * PANGO_SCALE); + } + } + + c.color.red = t->color->r | t->color->r << 8; + c.color.green = t->color->g | t->color->g << 8; + c.color.blue = t->color->b | t->color->b << 8; + c.color.alpha = 0xff | 0xff << 8; /* fully opaque text */ + c.pixel = t->color->pixel; + + if (t->shortcut) { + const gchar *s = t->string + t->shortcut_pos; + + t->font->shortcut_underline->start_index = t->shortcut_pos; + t->font->shortcut_underline->end_index = t->shortcut_pos + + (g_utf8_next_char(s) - s); + + /* the attributes are owned by the layout. + re-add the attributes to the layout after changing the + start and end index */ + attrlist = pango_layout_get_attributes(t->font->layout); + pango_attr_list_ref(attrlist); + pango_layout_set_attributes(t->font->layout, attrlist); + pango_attr_list_unref(attrlist); + } + + /* layout_line() uses y to specify the baseline + The line doesn't need to be freed, it's a part of the layout */ + if (!t->flow) { + pango_xft_render_layout_line + (d, &c, +#if PANGO_VERSION_MAJOR > 1 || \ + (PANGO_VERSION_MAJOR == 1 && PANGO_VERSION_MINOR >= 16) + pango_layout_get_line_readonly(t->font->layout, 0), +#else + pango_layout_get_line(t->font->layout, 0), +#endif + x * PANGO_SCALE, + y * PANGO_SCALE); + } + else { + pango_xft_render_layout(d, &c, t->font->layout, + x * PANGO_SCALE, + y * PANGO_SCALE); + } + + if (t->shortcut) { + t->font->shortcut_underline->start_index = 0; + t->font->shortcut_underline->end_index = 0; + /* the attributes are owned by the layout. + re-add the attributes to the layout after changing the + start and end index */ + attrlist = pango_layout_get_attributes(t->font->layout); + pango_attr_list_ref(attrlist); + pango_layout_set_attributes(t->font->layout, attrlist); + pango_attr_list_unref(attrlist); + } +} diff --git a/obrender/font.h b/obrender/font.h new file mode 100644 index 00000000..07d648d1 --- /dev/null +++ b/obrender/font.h @@ -0,0 +1,42 @@ +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + font.h for the Openbox window manager + Copyright (c) 2003-2007 Dana Jansens + Copyright (c) 2003 Derek Foreman + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + See the COPYING file for a copy of the GNU General Public License. +*/ + +#ifndef __font_h +#define __font_h +#include "render.h" +#include "geom.h" +#include + +struct _RrFont { + const RrInstance *inst; + gint ref; + PangoFontDescription *font_desc; + PangoLayout *layout; /*!< Used for measuring and rendering strings */ + PangoAttribute *shortcut_underline; /*< For underlining the shortcut key */ + gint ascent; /*!< The font's ascent in pango-units */ + gint descent; /*!< The font's descent in pango-units */ +}; + +void RrFontDraw(XftDraw *d, RrTextureText *t, RrRect *position); + +/*! Increment the references for this font, RrFontClose will decrement until 0 + and then really close it */ +void RrFontRef(RrFont *f); + +#endif /* __font_h */ diff --git a/obrender/geom.h b/obrender/geom.h new file mode 100644 index 00000000..4d81e4b3 --- /dev/null +++ b/obrender/geom.h @@ -0,0 +1,38 @@ +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + geom.h for the Openbox window manager + Copyright (c) 2006 Mikael Magnusson + Copyright (c) 2003-2007 Dana Jansens + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + See the COPYING file for a copy of the GNU General Public License. +*/ + +#ifndef __render_geom_h +#define __render_geom_h + +typedef struct { + int width; + int height; +} RrSize; + +typedef struct { + int x; + int y; + int width; + int height; +} RrRect; + +#define RECT_SET(r, nx, ny, w, h) \ + (r).x = (nx), (r).y = (ny), (r).width = (w), (r).height = (h) + +#endif diff --git a/obrender/gradient.c b/obrender/gradient.c new file mode 100644 index 00000000..60a0a555 --- /dev/null +++ b/obrender/gradient.c @@ -0,0 +1,836 @@ +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + gradient.c for the Openbox window manager + Copyright (c) 2006 Mikael Magnusson + Copyright (c) 2003-2008 Dana Jansens + Copyright (c) 2003 Derek Foreman + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + See the COPYING file for a copy of the GNU General Public License. +*/ + +#include "render.h" +#include "gradient.h" +#include "color.h" +#include +#include + +static void highlight(RrSurface *s, RrPixel32 *x, RrPixel32 *y, + gboolean raised); +static void gradient_parentrelative(RrAppearance *a, gint w, gint h); +static void gradient_solid(RrAppearance *l, gint w, gint h); +static void gradient_splitvertical(RrAppearance *a, gint w, gint h); +static void gradient_vertical(RrSurface *sf, gint w, gint h); +static void gradient_horizontal(RrSurface *sf, gint w, gint h); +static void gradient_mirrorhorizontal(RrSurface *sf, gint w, gint h); +static void gradient_diagonal(RrSurface *sf, gint w, gint h); +static void gradient_crossdiagonal(RrSurface *sf, gint w, gint h); +static void gradient_pyramid(RrSurface *sf, gint inw, gint inh); + +void RrRender(RrAppearance *a, gint w, gint h) +{ + RrPixel32 *data = a->surface.pixel_data; + RrPixel32 current; + guint r,g,b; + register gint off, x; + + switch (a->surface.grad) { + case RR_SURFACE_PARENTREL: + gradient_parentrelative(a, w, h); + break; + case RR_SURFACE_SOLID: + gradient_solid(a, w, h); + break; + case RR_SURFACE_SPLIT_VERTICAL: + gradient_splitvertical(a, w, h); + break; + case RR_SURFACE_VERTICAL: + gradient_vertical(&a->surface, w, h); + break; + case RR_SURFACE_HORIZONTAL: + gradient_horizontal(&a->surface, w, h); + break; + case RR_SURFACE_MIRROR_HORIZONTAL: + gradient_mirrorhorizontal(&a->surface, w, h); + break; + case RR_SURFACE_DIAGONAL: + gradient_diagonal(&a->surface, w, h); + break; + case RR_SURFACE_CROSS_DIAGONAL: + gradient_crossdiagonal(&a->surface, w, h); + break; + case RR_SURFACE_PYRAMID: + gradient_pyramid(&a->surface, w, h); + break; + default: + g_assert_not_reached(); /* unhandled gradient */ + return; + } + + if (a->surface.interlaced) { + gint i; + RrPixel32 *p; + + r = a->surface.interlace_color->r; + g = a->surface.interlace_color->g; + b = a->surface.interlace_color->b; + current = (r << RrDefaultRedOffset) + + (g << RrDefaultGreenOffset) + + (b << RrDefaultBlueOffset); + p = data; + for (i = 0; i < h; i += 2, p += w) + for (x = 0; x < w; ++x, ++p) + *p = current; + } + + if (a->surface.relief == RR_RELIEF_FLAT && a->surface.border) { + r = a->surface.border_color->r; + g = a->surface.border_color->g; + b = a->surface.border_color->b; + current = (r << RrDefaultRedOffset) + + (g << RrDefaultGreenOffset) + + (b << RrDefaultBlueOffset); + for (off = 0, x = 0; x < w; ++x, off++) { + *(data + off) = current; + *(data + off + ((h-1) * w)) = current; + } + for (off = 0, x = 0; x < h; ++x, off++) { + *(data + (off * w)) = current; + *(data + (off * w) + w - 1) = current; + } + } + + if (a->surface.relief != RR_RELIEF_FLAT) { + if (a->surface.bevel == RR_BEVEL_1) { + for (off = 1, x = 1; x < w - 1; ++x, off++) + highlight(&a->surface, data + off, + data + off + (h-1) * w, + a->surface.relief==RR_RELIEF_RAISED); + for (off = 0, x = 0; x < h; ++x, off++) + highlight(&a->surface, data + off * w, + data + off * w + w - 1, + a->surface.relief==RR_RELIEF_RAISED); + } + + if (a->surface.bevel == RR_BEVEL_2) { + for (off = 2, x = 2; x < w - 2; ++x, off++) + highlight(&a->surface, data + off + w, + data + off + (h-2) * w, + a->surface.relief==RR_RELIEF_RAISED); + for (off = 1, x = 1; x < h-1; ++x, off++) + highlight(&a->surface, data + off * w + 1, + data + off * w + w - 2, + a->surface.relief==RR_RELIEF_RAISED); + } + } +} + +static void highlight(RrSurface *s, RrPixel32 *x, RrPixel32 *y, gboolean raised) +{ + register gint r, g, b; + + RrPixel32 *up, *down; + if (raised) { + up = x; + down = y; + } else { + up = y; + down = x; + } + + r = (*up >> RrDefaultRedOffset) & 0xFF; + r += (r * s->bevel_light_adjust) >> 8; + g = (*up >> RrDefaultGreenOffset) & 0xFF; + g += (g * s->bevel_light_adjust) >> 8; + b = (*up >> RrDefaultBlueOffset) & 0xFF; + b += (b * s->bevel_light_adjust) >> 8; + if (r > 0xFF) r = 0xFF; + if (g > 0xFF) g = 0xFF; + if (b > 0xFF) b = 0xFF; + *up = (r << RrDefaultRedOffset) + (g << RrDefaultGreenOffset) + + (b << RrDefaultBlueOffset); + + r = (*down >> RrDefaultRedOffset) & 0xFF; + r -= (r * s->bevel_dark_adjust) >> 8; + g = (*down >> RrDefaultGreenOffset) & 0xFF; + g -= (g * s->bevel_dark_adjust) >> 8; + b = (*down >> RrDefaultBlueOffset) & 0xFF; + b -= (b * s->bevel_dark_adjust) >> 8; + *down = (r << RrDefaultRedOffset) + (g << RrDefaultGreenOffset) + + (b << RrDefaultBlueOffset); +} + +static void create_bevel_colors(RrAppearance *l) +{ + register gint r, g, b; + + /* light color */ + r = l->surface.primary->r; + r += (r * l->surface.bevel_light_adjust) >> 8; + g = l->surface.primary->g; + g += (g * l->surface.bevel_light_adjust) >> 8; + b = l->surface.primary->b; + b += (b * l->surface.bevel_light_adjust) >> 8; + if (r > 0xFF) r = 0xFF; + if (g > 0xFF) g = 0xFF; + if (b > 0xFF) b = 0xFF; + g_assert(!l->surface.bevel_light); + l->surface.bevel_light = RrColorNew(l->inst, r, g, b); + + /* dark color */ + r = l->surface.primary->r; + r -= (r * l->surface.bevel_dark_adjust) >> 8; + g = l->surface.primary->g; + g -= (g * l->surface.bevel_dark_adjust) >> 8; + b = l->surface.primary->b; + b -= (b * l->surface.bevel_dark_adjust) >> 8; + g_assert(!l->surface.bevel_dark); + l->surface.bevel_dark = RrColorNew(l->inst, r, g, b); +} + +/*! Repeat the first pixel over the entire block of memory + @param start The block of memory. start[0] will be copied + to the rest of the block. + @param w The width of the block of memory (including the already-set first + element +*/ +static inline void repeat_pixel(RrPixel32 *start, gint w) +{ + register gint x; + RrPixel32 *dest; + + dest = start + 1; + + /* for really small things, just copy ourselves */ + if (w < 8) { + for (x = w-1; x > 0; --x) + *(dest++) = *start; + } + + /* for >= 8, then use O(log n) memcpy's... */ + else { + gchar *cdest; + gint lenbytes; + + /* copy the first 3 * 32 bits (3 words) ourselves - then we have + 3 + the original 1 = 4 words to make copies of at a time + + this is faster than doing memcpy for 1 or 2 words at a time + */ + for (x = 3; x > 0; --x) + *(dest++) = *start; + + /* cdest is a pointer to the pixel data that is typed char* so that + adding 1 to its position moves it only one byte + + lenbytes is the amount of bytes that we will be copying each + iteration. this doubles each time through the loop. + + x is the number of bytes left to copy into. lenbytes will alwaysa + be bounded by x + + this loop will run O(log n) times (n is the number of bytes we + need to copy into), since the size of the copy is doubled each + iteration. it seems that gcc does some nice optimizations to make + this memcpy very fast on hardware with support for vector operations + such as mmx or see. here is an idea of the kind of speed up we are + getting by doing this (splitvertical3 switches from doing + "*(data++) = color" n times to doing this memcpy thing log n times: + + % cumulative self self total + time seconds seconds calls ms/call ms/call name + 49.44 0.88 0.88 1063 0.83 0.83 splitvertical1 + 47.19 1.72 0.84 1063 0.79 0.79 splitvertical2 + 2.81 1.77 0.05 1063 0.05 0.05 splitvertical3 + */ + cdest = (gchar*)dest; + lenbytes = 4 * sizeof(RrPixel32); + for (x = (w - 4) * sizeof(RrPixel32); x > 0;) { + memcpy(cdest, start, lenbytes); + x -= lenbytes; + cdest += lenbytes; + lenbytes <<= 1; + if (lenbytes > x) + lenbytes = x; + } + } +} + +static void gradient_parentrelative(RrAppearance *a, gint w, gint h) +{ + RrPixel32 *source, *dest; + gint sw, sh, partial_w, partial_h; + register gint i; + + g_assert (a->surface.parent); + g_assert (a->surface.parent->w); + + sw = a->surface.parent->w; + sh = a->surface.parent->h; + + /* This is a little hack. When a texture is parentrelative, and the same + area as the parent, and has a bevel, it will draw its bevel on top + of the parent's, amplifying it. So instead, rerender the child with + the parent's settings, but the child's bevel and interlace */ + if (a->surface.relief != RR_RELIEF_FLAT && + (a->surface.parent->surface.relief != RR_RELIEF_FLAT || + a->surface.parent->surface.border) && + !a->surface.parentx && !a->surface.parenty && + sw == w && sh == h) + { + RrSurface old = a->surface; + a->surface = a->surface.parent->surface; + + /* turn these off for the parent */ + a->surface.relief = RR_RELIEF_FLAT; + a->surface.border = FALSE; + + a->surface.pixel_data = old.pixel_data; + + RrRender(a, w, h); + a->surface = old; + } else { + source = (a->surface.parent->surface.pixel_data + + a->surface.parentx + sw * a->surface.parenty); + dest = a->surface.pixel_data; + + if (a->surface.parentx + w > sw) { + partial_w = sw - a->surface.parentx; + } else partial_w = w; + + if (a->surface.parenty + h > sh) { + partial_h = sh - a->surface.parenty; + } else partial_h = h; + + for (i = 0; i < partial_h; i++, source += sw, dest += w) { + memcpy(dest, source, partial_w * sizeof(RrPixel32)); + } + } +} + +static void gradient_solid(RrAppearance *l, gint w, gint h) +{ + register gint i; + RrPixel32 pix; + RrPixel32 *data = l->surface.pixel_data; + RrSurface *sp = &l->surface; + gint left = 0, top = 0, right = w - 1, bottom = h - 1; + + pix = (sp->primary->r << RrDefaultRedOffset) + + (sp->primary->g << RrDefaultGreenOffset) + + (sp->primary->b << RrDefaultBlueOffset); + + for (i = 0; i < w * h; i++) + *data++ = pix; + + if (sp->interlaced) + return; + + XFillRectangle(RrDisplay(l->inst), l->pixmap, RrColorGC(sp->primary), + 0, 0, w, h); + + switch (sp->relief) { + case RR_RELIEF_RAISED: + if (!sp->bevel_dark) + create_bevel_colors(l); + + switch (sp->bevel) { + case RR_BEVEL_1: + XDrawLine(RrDisplay(l->inst), l->pixmap, RrColorGC(sp->bevel_dark), + left, bottom, right, bottom); + XDrawLine(RrDisplay(l->inst), l->pixmap, RrColorGC(sp->bevel_dark), + right, bottom, right, top); + + XDrawLine(RrDisplay(l->inst), l->pixmap,RrColorGC(sp->bevel_light), + left, top, right, top); + XDrawLine(RrDisplay(l->inst), l->pixmap,RrColorGC(sp->bevel_light), + left, bottom, left, top); + break; + case RR_BEVEL_2: + XDrawLine(RrDisplay(l->inst), l->pixmap, RrColorGC(sp->bevel_dark), + left + 2, bottom - 1, right - 2, bottom - 1); + XDrawLine(RrDisplay(l->inst), l->pixmap, RrColorGC(sp->bevel_dark), + right - 1, bottom - 1, right - 1, top + 1); + + XDrawLine(RrDisplay(l->inst), l->pixmap,RrColorGC(sp->bevel_light), + left + 2, top + 1, right - 2, top + 1); + XDrawLine(RrDisplay(l->inst), l->pixmap,RrColorGC(sp->bevel_light), + left + 1, bottom - 1, left + 1, top + 1); + break; + default: + g_assert_not_reached(); /* unhandled BevelType */ + } + break; + case RR_RELIEF_SUNKEN: + if (!sp->bevel_dark) + create_bevel_colors(l); + + switch (sp->bevel) { + case RR_BEVEL_1: + XDrawLine(RrDisplay(l->inst), l->pixmap,RrColorGC(sp->bevel_light), + left, bottom, right, bottom); + XDrawLine(RrDisplay(l->inst), l->pixmap,RrColorGC(sp->bevel_light), + right, bottom, right, top); + + XDrawLine(RrDisplay(l->inst), l->pixmap, RrColorGC(sp->bevel_dark), + left, top, right, top); + XDrawLine(RrDisplay(l->inst), l->pixmap, RrColorGC(sp->bevel_dark), + left, bottom, left, top); + break; + case RR_BEVEL_2: + XDrawLine(RrDisplay(l->inst), l->pixmap,RrColorGC(sp->bevel_light), + left + 2, bottom - 1, right - 2, bottom - 1); + XDrawLine(RrDisplay(l->inst), l->pixmap,RrColorGC(sp->bevel_light), + right - 1, bottom - 1, right - 1, top + 1); + + XDrawLine(RrDisplay(l->inst), l->pixmap, RrColorGC(sp->bevel_dark), + left + 2, top + 1, right - 2, top + 1); + XDrawLine(RrDisplay(l->inst), l->pixmap, RrColorGC(sp->bevel_dark), + left + 1, bottom - 1, left + 1, top + 1); + break; + default: + g_assert_not_reached(); /* unhandled BevelType */ + } + break; + case RR_RELIEF_FLAT: + if (sp->border) { + XDrawRectangle(RrDisplay(l->inst), l->pixmap, + RrColorGC(sp->border_color), + left, top, right, bottom); + } + break; + default: + g_assert_not_reached(); /* unhandled ReliefType */ + } +} + +/* * * * * * * * * * * * * * GRADIENT MAGIC WOOT * * * * * * * * * * * * * * */ + +#define VARS(x) \ + register gint len##x; \ + guint color##x[3]; \ + gint cdelta##x[3], error##x[3] = { 0, 0, 0 }, inc##x[3]; \ + gboolean bigslope##x[3] /* color slope > 1 */ + +#define SETUP(x, from, to, w) \ + len##x = w; \ + \ + color##x[0] = from->r; \ + color##x[1] = from->g; \ + color##x[2] = from->b; \ + \ + cdelta##x[0] = to->r - from->r; \ + cdelta##x[1] = to->g - from->g; \ + cdelta##x[2] = to->b - from->b; \ + \ + if (cdelta##x[0] < 0) { \ + cdelta##x[0] = -cdelta##x[0]; \ + inc##x[0] = -1; \ + } else \ + inc##x[0] = 1; \ + if (cdelta##x[1] < 0) { \ + cdelta##x[1] = -cdelta##x[1]; \ + inc##x[1] = -1; \ + } else \ + inc##x[1] = 1; \ + if (cdelta##x[2] < 0) { \ + cdelta##x[2] = -cdelta##x[2]; \ + inc##x[2] = -1; \ + } else \ + inc##x[2] = 1; \ + bigslope##x[0] = cdelta##x[0] > w;\ + bigslope##x[1] = cdelta##x[1] > w;\ + bigslope##x[2] = cdelta##x[2] > w + +#define COLOR_RR(x, c) \ + c->r = color##x[0]; \ + c->g = color##x[1]; \ + c->b = color##x[2] + +#define COLOR(x) \ + ((color##x[0] << RrDefaultRedOffset) + \ + (color##x[1] << RrDefaultGreenOffset) + \ + (color##x[2] << RrDefaultBlueOffset)) + +#define INCREMENT(x, i) \ + (inc##x[i]) + +#define NEXT(x) \ +{ \ + register gint i; \ + for (i = 2; i >= 0; --i) { \ + if (!cdelta##x[i]) continue; \ + \ + if (!bigslope##x[i]) { \ + /* Y (color) is dependant on X */ \ + error##x[i] += cdelta##x[i]; \ + if ((error##x[i] << 1) >= len##x) { \ + color##x[i] += INCREMENT(x, i); \ + error##x[i] -= len##x; \ + } \ + } else { \ + /* X is dependant on Y (color) */ \ + while (1) { \ + color##x[i] += INCREMENT(x, i); \ + error##x[i] += len##x; \ + if ((error##x[i] << 1) >= cdelta##x[i]) { \ + error##x[i] -= cdelta##x[i]; \ + break; \ + } \ + } \ + } \ + } \ +} + +static void gradient_splitvertical(RrAppearance *a, gint w, gint h) +{ + register gint y1, y2, y3; + RrSurface *sf = &a->surface; + RrPixel32 *data; + register gint y1sz, y2sz, y3sz; + + VARS(y1); + VARS(y2); + VARS(y3); + + /* if h <= 5, then a 0 or 1px middle gradient. + if h > 5, then always a 1px middle gradient. + */ + if (h <= 5) { + y1sz = MAX(h/2, 0); + y2sz = (h < 3) ? 0 : (h & 1); + y3sz = MAX(h/2, 1); + } + else { + y1sz = h/2 - (1 - (h & 1)); + y2sz = 1; + y3sz = h/2; + } + + SETUP(y1, sf->split_primary, sf->primary, y1sz); + if (y2sz) { + /* setup to get the colors _in between_ these other 2 */ + SETUP(y2, sf->primary, sf->secondary, y2sz + 2); + NEXT(y2); /* skip the first one, its the same as the last of y1 */ + } + SETUP(y3, sf->secondary, sf->split_secondary, y3sz); + + /* find the color for the first pixel of each row first */ + data = sf->pixel_data; + + for (y1 = y1sz-1; y1 > 0; --y1) { + *data = COLOR(y1); + data += w; + NEXT(y1); + } + *data = COLOR(y1); + data += w; + if (y2sz) { + for (y2 = y2sz-1; y2 > 0; --y2) { + *data = COLOR(y2); + data += w; + NEXT(y2); + } + *data = COLOR(y2); + data += w; + } + for (y3 = y3sz-1; y3 > 0; --y3) { + *data = COLOR(y3); + data += w; + NEXT(y3); + } + *data = COLOR(y3); + + /* copy the first pixels into the whole rows */ + data = sf->pixel_data; + for (y1 = h; y1 > 0; --y1) { + repeat_pixel(data, w); + data += w; + } +} + +static void gradient_horizontal(RrSurface *sf, gint w, gint h) +{ + register gint x, y, cpbytes; + RrPixel32 *data = sf->pixel_data, *datav; + gchar *datac; + + VARS(x); + SETUP(x, sf->primary, sf->secondary, w); + + /* set the color values for the first row */ + datav = data; + for (x = w - 1; x > 0; --x) { /* 0 -> w - 1 */ + *datav = COLOR(x); + ++datav; + NEXT(x); + } + *datav = COLOR(x); + ++datav; + + /* copy the first row to the rest in O(logn) copies */ + datac = (gchar*)datav; + cpbytes = 1 * w * sizeof(RrPixel32); + for (y = (h - 1) * w * sizeof(RrPixel32); y > 0;) { + memcpy(datac, data, cpbytes); + y -= cpbytes; + datac += cpbytes; + cpbytes <<= 1; + if (cpbytes > y) + cpbytes = y; + } +} + +static void gradient_mirrorhorizontal(RrSurface *sf, gint w, gint h) +{ + register gint x, y, half1, half2, cpbytes; + RrPixel32 *data = sf->pixel_data, *datav; + gchar *datac; + + VARS(x); + + half1 = (w + 1) / 2; + half2 = w / 2; + + /* set the color values for the first row */ + + SETUP(x, sf->primary, sf->secondary, half1); + datav = data; + for (x = half1 - 1; x > 0; --x) { /* 0 -> half1 - 1 */ + *datav = COLOR(x); + ++datav; + NEXT(x); + } + *datav = COLOR(x); + ++datav; + + if (half2 > 0) { + SETUP(x, sf->secondary, sf->primary, half2); + for (x = half2 - 1; x > 0; --x) { /* 0 -> half2 - 1 */ + *datav = COLOR(x); + ++datav; + NEXT(x); + } + *datav = COLOR(x); + ++datav; + } + + /* copy the first row to the rest in O(logn) copies */ + datac = (gchar*)datav; + cpbytes = 1 * w * sizeof(RrPixel32); + for (y = (h - 1) * w * sizeof(RrPixel32); y > 0;) { + memcpy(datac, data, cpbytes); + y -= cpbytes; + datac += cpbytes; + cpbytes <<= 1; + if (cpbytes > y) + cpbytes = y; + } +} + +static void gradient_vertical(RrSurface *sf, gint w, gint h) +{ + register gint y; + RrPixel32 *data; + + VARS(y); + SETUP(y, sf->primary, sf->secondary, h); + + /* find the color for the first pixel of each row first */ + data = sf->pixel_data; + + for (y = h - 1; y > 0; --y) { /* 0 -> h-1 */ + *data = COLOR(y); + data += w; + NEXT(y); + } + *data = COLOR(y); + + /* copy the first pixels into the whole rows */ + data = sf->pixel_data; + for (y = h; y > 0; --y) { + repeat_pixel(data, w); + data += w; + } +} + +static void gradient_diagonal(RrSurface *sf, gint w, gint h) +{ + register gint x, y; + RrPixel32 *data = sf->pixel_data; + RrColor left, right; + RrColor extracorner; + + VARS(lefty); + VARS(righty); + VARS(x); + + extracorner.r = (sf->primary->r + sf->secondary->r) / 2; + extracorner.g = (sf->primary->g + sf->secondary->g) / 2; + extracorner.b = (sf->primary->b + sf->secondary->b) / 2; + + SETUP(lefty, sf->primary, (&extracorner), h); + SETUP(righty, (&extracorner), sf->secondary, h); + + for (y = h - 1; y > 0; --y) { /* 0 -> h-1 */ + COLOR_RR(lefty, (&left)); + COLOR_RR(righty, (&right)); + + SETUP(x, (&left), (&right), w); + + for (x = w - 1; x > 0; --x) { /* 0 -> w-1 */ + *(data++) = COLOR(x); + + NEXT(x); + } + *(data++) = COLOR(x); + + NEXT(lefty); + NEXT(righty); + } + COLOR_RR(lefty, (&left)); + COLOR_RR(righty, (&right)); + + SETUP(x, (&left), (&right), w); + + for (x = w - 1; x > 0; --x) { /* 0 -> w-1 */ + *(data++) = COLOR(x); + + NEXT(x); + } + *data = COLOR(x); +} + +static void gradient_crossdiagonal(RrSurface *sf, gint w, gint h) +{ + register gint x, y; + RrPixel32 *data = sf->pixel_data; + RrColor left, right; + RrColor extracorner; + + VARS(lefty); + VARS(righty); + VARS(x); + + extracorner.r = (sf->primary->r + sf->secondary->r) / 2; + extracorner.g = (sf->primary->g + sf->secondary->g) / 2; + extracorner.b = (sf->primary->b + sf->secondary->b) / 2; + + SETUP(lefty, (&extracorner), sf->secondary, h); + SETUP(righty, sf->primary, (&extracorner), h); + + for (y = h - 1; y > 0; --y) { /* 0 -> h-1 */ + COLOR_RR(lefty, (&left)); + COLOR_RR(righty, (&right)); + + SETUP(x, (&left), (&right), w); + + for (x = w - 1; x > 0; --x) { /* 0 -> w-1 */ + *(data++) = COLOR(x); + + NEXT(x); + } + *(data++) = COLOR(x); + + NEXT(lefty); + NEXT(righty); + } + COLOR_RR(lefty, (&left)); + COLOR_RR(righty, (&right)); + + SETUP(x, (&left), (&right), w); + + for (x = w - 1; x > 0; --x) { /* 0 -> w-1 */ + *(data++) = COLOR(x); + + NEXT(x); + } + *data = COLOR(x); +} + +static void gradient_pyramid(RrSurface *sf, gint w, gint h) +{ + RrPixel32 *ldata, *rdata; + RrPixel32 *cp; + RrColor left, right; + RrColor extracorner; + register gint x, y, halfw, halfh, midx, midy; + + VARS(lefty); + VARS(righty); + VARS(x); + + extracorner.r = (sf->primary->r + sf->secondary->r) / 2; + extracorner.g = (sf->primary->g + sf->secondary->g) / 2; + extracorner.b = (sf->primary->b + sf->secondary->b) / 2; + + halfw = w >> 1; + halfh = h >> 1; + midx = w - halfw - halfw; /* 0 or 1, depending if w is even or odd */ + midy = h - halfh - halfh; /* 0 or 1, depending if h is even or odd */ + + SETUP(lefty, sf->primary, (&extracorner), halfh + midy); + SETUP(righty, (&extracorner), sf->secondary, halfh + midy); + + /* draw the top half + + it is faster to draw both top quarters together than to draw one and + then copy it over to the other side. + */ + + ldata = sf->pixel_data; + rdata = ldata + w - 1; + for (y = halfh + midy; y > 0; --y) { /* 0 -> (h+1)/2 */ + RrPixel32 c; + + COLOR_RR(lefty, (&left)); + COLOR_RR(righty, (&right)); + + SETUP(x, (&left), (&right), halfw + midx); + + for (x = halfw + midx - 1; x > 0; --x) { /* 0 -> (w+1)/2 */ + c = COLOR(x); + *(ldata++) = *(rdata--) = c; + + NEXT(x); + } + c = COLOR(x); + *ldata = *rdata = c; + ldata += halfw + 1; + rdata += halfw - 1 + midx + w; + + NEXT(lefty); + NEXT(righty); + } + + /* copy the top half into the bottom half, mirroring it, so we can only + copy one row at a time + + it is faster, to move the writing pointer forward, and the reading + pointer backward + + this is the current code, moving the write pointer forward and read + pointer backward + 41.78 4.26 1.78 504 3.53 3.53 gradient_pyramid2 + this is the opposite, moving the read pointer forward and the write + pointer backward + 42.27 4.40 1.86 504 3.69 3.69 gradient_pyramid2 + + */ + ldata = sf->pixel_data + (halfh - 1) * w; + cp = ldata + (midy + 1) * w; + for (y = halfh; y > 0; --y) { + memcpy(cp, ldata, w * sizeof(RrPixel32)); + ldata -= w; + cp += w; + } +} diff --git a/obrender/gradient.h b/obrender/gradient.h new file mode 100644 index 00000000..8613f0ce --- /dev/null +++ b/obrender/gradient.h @@ -0,0 +1,27 @@ +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + gradient.h for the Openbox window manager + Copyright (c) 2003-2007 Dana Jansens + Copyright (c) 2003 Derek Foreman + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + See the COPYING file for a copy of the GNU General Public License. +*/ + +#ifndef __gradient_h +#define __gradient_h + +#include "render.h" + +void RrRender(RrAppearance *a, gint w, gint h); + +#endif /* __gradient_h */ diff --git a/obrender/icon.h b/obrender/icon.h new file mode 100644 index 00000000..f0b2d267 --- /dev/null +++ b/obrender/icon.h @@ -0,0 +1,422 @@ +/* GIMP RGBA C-Source image dump (icon.h) */ + +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + icon.h for the Openbox window manager + Copyright (c) 2003-2007 Dana Jansens + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + See the COPYING file for a copy of the GNU General Public License. +*/ + +#define OB_DEFAULT_ICON_WIDTH (48) +#define OB_DEFAULT_ICON_HEIGHT (48) +#define OB_DEFAULT_ICON_BYTES_PER_PIXEL (4) /* 3:RGB, 4:RGBA */ +#define OB_DEFAULT_ICON_COMMENT \ + "To recreate this file, save an image as \"C-Source\" in The Gimp. Use \"ob_default_icon\" as the Prefixed Name. Enable Glib Types. Enable Save Alpha Channel. Enable Use Macros instead of Struct." +#define OB_DEFAULT_ICON_PIXEL_DATA ((guint8*) OB_DEFAULT_ICON_pixel_data) +static const guint8 OB_DEFAULT_ICON_pixel_data[48 * 48 * 4 + 1] = +("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\40J\207\15\40J\207\23\40J\207" + "\23\40J\207\23\40J\207\23\40J\207\23\40J\207\23\40J\207\23\40J\207\23\40J" + "\207\23\40J\207\23\40J\207\23\40J\207\23\40J\207\23\40J\207\23\40J\207\23" + "\40J\207\23\40J\207\23\40J\207\23\40J\207\23\40J\207\23\40J\207\23\40J\207" + "\23\40J\207\23\40J\207\23\40J\207\23\40J\207\23\40J\207\23\40J\207\23\40J" + "\207\23\40J\207\23\40J\207\23\40J\207\23\40J\207\23\40J\207\23\40J\207\23" + "\40J\207\23\40J\207\23\40J\207\23\40J\207\23\40J\207\23\40J\207\23\40J\207" + "\23\40J\207\15\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0'P\213\267'Q\214\275'Q\214\275" + "'Q\214\275'Q\214\275'Q\214\275'Q\214\275'Q\214\275'Q\214\275'Q\214\275'Q\214" + "\275'Q\214\275'Q\214\275'Q\214\275'Q\214\275'Q\214\275'Q\214\275'Q\214\275" + "'Q\214\275'Q\214\275'Q\214\275'Q\214\275'Q\214\275(R\215\275'Q\214\275'Q\214" + "\275'Q\214\275'Q\214\275'Q\214\275'Q\214\275'Q\214\275'Q\214\275'Q\214\275" + "'Q\214\275'Q\214\275'Q\214\275'Q\214\275'Q\214\275'Q\214\275'Q\214\275(R\215" + "\275(R\215\275(R\215\275&P\213\267\40J\207\20\0\0\0\0\0\0\0\0\40J\207+Y{\252" + "\377\216\253\320\377\204\243\314\377\204\243\314\377\204\243\314\377\204\243" + "\314\377\204\243\314\377\204\243\314\377\204\243\314\377\204\243\314\377\204" + "\243\314\377\204\243\314\377\204\243\314\377\204\243\314\377\204\243\314\377" + "\204\243\314\377\204\243\314\377\204\243\314\377\204\243\314\377\204\243\314" + "\377\204\243\314\377\204\243\314\377\204\243\314\377\204\243\314\377\204\243" + "\314\377\204\243\314\377\203\243\314\377\203\243\313\377\203\243\313\377\203" + "\243\313\377\203\242\313\377\202\242\313\377\202\242\313\377\202\241\313\377" + "\201\241\312\377\201\241\312\377\201\240\312\377\201\240\312\377\200\240\312" + "\377\200\240\312\377\200\240\312\377\200\240\312\377\211\247\316\377Jn\241" + "\377\40J\207+\0\0\0\0\0\0\0\0\40J\207+Wy\251\377]\207\275\377>o\260\377>o" + "\260\377>o\260\377>o\260\377>o\260\377>o\260\377>o\260\377>o\260\377>o\260" + "\377>o\260\377>o\260\377>o\260\377>o\260\377>o\260\377>o\260\377>o\260\377" + ">o\260\377>o\260\377>o\260\377>o\260\377>o\260\377>o\260\377>o\260\377>o\260" + "\377>o\260\377>o\260\377>o\260\377>o\260\377=o\260\377=o\260\377=o\260\377" + "=o\260\377=o\260\377=o\260\377=o\260\377=o\260\377=o\260\377=o\260\377=o\260" + "\377=o\260\377_\210\275\377Hm\241\377\40J\207+\0\0\0\0\0\0\0\0\40J\207+Tw" + "\251\377]\207\276\377?r\263\377?r\263\377?r\263\377?r\263\377?r\263\377?r" + "\263\377?r\263\377?r\263\377?r\263\377?r\263\377?r\263\377?r\263\377?r\263" + "\377?r\263\377?r\263\377?r\263\377?r\263\377?r\263\377?r\263\377?r\263\377" + "?r\263\377?r\263\377?r\263\377?r\263\377?r\263\377?r\263\377?r\263\377?r\263" + "\377?r\263\377?r\263\377?r\263\377?r\263\377?r\263\377?r\263\377?r\263\377" + "?r\263\377?r\263\377?r\263\377?r\263\377?r\263\377]\210\277\377Fl\241\377" + "\40J\207+\0\0\0\0\0\0\0\0\40J\207+Rv\250\377\\\210\300\377At\265\377At\265" + "\377At\265\377At\265\377At\265\377At\265\377At\265\377At\265\377At\265\377" + "At\265\377At\265\377At\265\377At\265\377At\265\377At\265\377At\265\377At\265" + "\377At\265\377At\265\377At\265\377At\265\377At\265\377At\265\377At\265\377" + "At\265\377At\265\377At\265\377At\265\377At\265\377At\265\377At\265\377At\265" + "\377At\265\377At\265\377At\265\377At\265\377At\265\377At\265\377At\265\377" + "At\265\377\\\210\300\377Dj\240\377\40J\207+\0\0\0\0\0\0\0\0\40J\207+Ot\247" + "\377\\\211\302\377Dw\271\377Dw\271\377Dw\271\377Dw\271\377Dw\271\377Dw\271" + "\377Dw\271\377Dw\271\377Dw\271\377Dw\271\377Dw\271\377Dw\271\377Dw\271\377" + "Dw\271\377Dw\271\377Dw\271\377Dw\271\377Dw\271\377Dw\271\377Dw\271\377Dw\271" + "\377Dw\271\377Dw\271\377Dw\271\377Dw\271\377Dw\271\377Dw\271\377Dw\271\377" + "Dw\271\377Dw\271\377Dw\271\377Dw\271\377Dw\271\377Dw\271\377Dw\271\377Dw\271" + "\377Dw\271\377Dw\271\377Dw\271\377Dw\271\377[\211\302\377Bi\240\377\40J\207" + "+\0\0\0\0\0\0\0\0\40J\207+Ls\247\377\\\211\303\377Fy\273\377Fy\273\377Fy\273" + "\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377" + "Fy\273\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377Fy\273" + "\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377" + "Fy\273\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377Fy\273" + "\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377" + "\\\211\303\377Ah\240\377\40J\207+\0\0\0\0\0\0\0\0\40J\207+Jq\246\377\\\212" + "\305\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277" + "\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377" + "I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277" + "\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377" + "I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277" + "\377I}\277\377I}\277\377I}\277\377[\212\305\377?g\237\377\40J\207+\0\0\0\0" + "\0\0\0\0\40J\207+Jq\246\377\\\212\305\377I}\277\377I}\277\377I}\277\377I}" + "\277\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277" + "\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377" + "I}\277\377I}\277\377I}\277\377J~\300\377K\177\301\377K\177\301\377K\177\301" + "\377K\177\301\377K\177\301\377K\177\301\377K\177\301\377K\177\301\377K\177" + "\301\377K\177\301\377K\177\301\377K\177\301\377K\177\301\377K\177\301\377" + "K\177\301\377K\177\301\377K\177\301\377K\177\301\377Z\212\307\377=f\237\377" + "\40J\207+\0\0\0\0\0\0\0\0\40J\207+Ip\247\377\\\213\307\377J\177\301\377J\177" + "\301\377J\177\301\377J\177\301\377J\177\301\377J\177\301\377J\177\301\377" + "J\177\301\377J\177\301\377J\177\301\377J\177\301\377J\177\301\377J\177\301" + "\377J\177\301\377J\177\301\377J\177\301\377J\177\301\377J\177\301\377J\177" + "\301\377J\177\301\377J\177\301\377K\200\302\377K\200\302\377K\200\302\377" + "K\200\302\377K\200\302\377K\200\302\377K\200\302\377K\200\302\377K\200\302" + "\377K\200\302\377K\200\302\377K\200\302\377K\200\302\377K\200\302\377K\200" + "\302\377K\200\302\377K\200\302\377K\200\302\377K\200\302\377Z\212\307\377" + "=f\237\377\40J\207+\0\0\0\0\0\0\0\0\40J\207+Ho\247\377e\223\314\377Z\213\310" + "\377Z\213\310\377Z\213\310\377Z\213\310\377Z\213\307\377Z\213\307\377Z\213" + "\307\377Z\213\307\377Z\213\307\377Y\212\307\377Y\212\307\377Y\212\307\377" + "Y\212\307\377Y\212\307\377X\212\307\377X\212\307\377X\212\307\377X\211\307" + "\377X\212\307\377X\212\307\377X\211\307\377X\211\307\377X\211\307\377X\211" + "\307\377X\211\307\377X\211\307\377X\211\307\377X\211\307\377X\211\307\377" + "X\211\307\377W\211\307\377W\211\307\377W\211\307\377W\211\307\377W\211\307" + "\377W\211\307\377V\211\307\377V\211\307\377V\210\307\377V\210\307\377`\217" + "\312\377 + +#define FRACTION 12 +#define FLOOR(i) ((i) & (~0UL << FRACTION)) +#define AVERAGE(a, b) (((((a) ^ (b)) & 0xfefefefeL) >> 1) + ((a) & (b))) + +void RrImagePicInit(RrImagePic *pic, gint w, gint h, RrPixel32 *data) +{ + gint i; + + pic->width = w; + pic->height = h; + pic->data = data; + pic->sum = 0; + for (i = w*h; i > 0; --i) + pic->sum += *(data++); +} + +static void RrImagePicFree(RrImagePic *pic) +{ + if (pic) { + g_free(pic->data); + g_free(pic); + } +} + +/*! Add a picture to an Image, that is, add another copy of the image at + another size. This may add it to the "originals" list or to the + "resized" list. */ +static void AddPicture(RrImage *self, RrImagePic ***list, gint *len, + RrImagePic *pic) +{ + gint i; + + g_assert(pic->width > 0 && pic->height > 0); + + g_assert(g_hash_table_lookup(self->cache->table, pic) == NULL); + + /* grow the list */ + *list = g_renew(RrImagePic*, *list, ++*len); + + /* move everything else down one */ + for (i = *len-1; i > 0; --i) + (*list)[i] = (*list)[i-1]; + + /* set the new picture up at the front of the list */ + (*list)[0] = pic; + + /* add the picture as a key to point to this image in the cache */ + g_hash_table_insert(self->cache->table, (*list)[0], self); + +/* +#ifdef DEBUG + g_debug("Adding %s picture to the cache:\n " + "Image 0x%lx, w %d h %d Hash %u", + (*list == self->original ? "ORIGINAL" : "RESIZED"), + (gulong)self, pic->width, pic->height, RrImagePicHash(pic)); +#endif +*/ +} + +/*! Remove a picture from an Image. This may remove it from the "originals" + list or the "resized" list. */ +static void RemovePicture(RrImage *self, RrImagePic ***list, + gint i, gint *len) +{ + gint j; + +/* +#ifdef DEBUG + g_debug("Removing %s picture from the cache:\n " + "Image 0x%lx, w %d h %d Hash %u", + (*list == self->original ? "ORIGINAL" : "RESIZED"), + (gulong)self, (*list)[i]->width, (*list)[i]->height, + RrImagePicHash((*list)[i])); +#endif +*/ + + /* remove the picture as a key in the cache */ + g_hash_table_remove(self->cache->table, (*list)[i]); + + /* free the picture */ + RrImagePicFree((*list)[i]); + /* shift everything down one */ + for (j = i; j < *len-1; ++j) + (*list)[j] = (*list)[j+1]; + /* shrink the list */ + *list = g_renew(RrImagePic*, *list, --*len); +} + +/*! Given a picture in RGBA format, of a specified size, resize it to the new + requested size (but keep its aspect ratio). If the image does not need to + be resized (it is already the right size) then this returns NULL. Otherwise + it returns a newly allocated RrImagePic with the resized picture inside it +*/ +static RrImagePic* ResizeImage(RrPixel32 *src, + gulong srcW, gulong srcH, + gulong dstW, gulong dstH) +{ + RrPixel32 *dst, *dststart; + RrImagePic *pic; + gulong dstX, dstY, srcX, srcY; + gulong srcX1, srcX2, srcY1, srcY2; + gulong ratioX, ratioY; + gulong aspectW, aspectH; + + /* XXX should these variables be ensured to not be zero in the callers? */ + srcW = srcW ? srcW : 1; + srcH = srcH ? srcH : 1; + dstW = dstW ? dstW : 1; + dstH = dstH ? dstH : 1; + + /* keep the aspect ratio */ + aspectW = dstW; + aspectH = (gint)(dstW * ((gdouble)srcH / srcW)); + if (aspectH > dstH) { + aspectH = dstH; + aspectW = (gint)(dstH * ((gdouble)srcW / srcH)); + } + dstW = aspectW ? aspectW : 1; + dstH = aspectH ? aspectH : 1; + + if (srcW == dstW && srcH == dstH) + return NULL; /* no scaling needed! */ + + dststart = dst = g_new(RrPixel32, dstW * dstH); + + ratioX = (srcW << FRACTION) / dstW; + ratioY = (srcH << FRACTION) / dstH; + + srcY2 = 0; + for (dstY = 0; dstY < dstH; dstY++) { + srcY1 = srcY2; + srcY2 += ratioY; + + srcX2 = 0; + for (dstX = 0; dstX < dstW; dstX++) { + gulong red = 0, green = 0, blue = 0, alpha = 0; + gulong portionX, portionY, portionXY, sumXY = 0; + RrPixel32 pixel; + + srcX1 = srcX2; + srcX2 += ratioX; + + for (srcY = srcY1; srcY < srcY2; srcY += (1UL << FRACTION)) { + if (srcY == srcY1) { + srcY = FLOOR(srcY); + portionY = (1UL << FRACTION) - (srcY1 - srcY); + if (portionY > srcY2 - srcY1) + portionY = srcY2 - srcY1; + } + else if (srcY == FLOOR(srcY2)) + portionY = srcY2 - srcY; + else + portionY = (1UL << FRACTION); + + for (srcX = srcX1; srcX < srcX2; srcX += (1UL << FRACTION)) { + if (srcX == srcX1) { + srcX = FLOOR(srcX); + portionX = (1UL << FRACTION) - (srcX1 - srcX); + if (portionX > srcX2 - srcX1) + portionX = srcX2 - srcX1; + } + else if (srcX == FLOOR(srcX2)) + portionX = srcX2 - srcX; + else + portionX = (1UL << FRACTION); + + portionXY = (portionX * portionY) >> FRACTION; + sumXY += portionXY; + + pixel = *(src + (srcY >> FRACTION) * srcW + + (srcX >> FRACTION)); + red += ((pixel >> RrDefaultRedOffset) & 0xFF) + * portionXY; + green += ((pixel >> RrDefaultGreenOffset) & 0xFF) + * portionXY; + blue += ((pixel >> RrDefaultBlueOffset) & 0xFF) + * portionXY; + alpha += ((pixel >> RrDefaultAlphaOffset) & 0xFF) + * portionXY; + } + } + + g_assert(sumXY != 0); + red /= sumXY; + green /= sumXY; + blue /= sumXY; + alpha /= sumXY; + + *dst++ = (red << RrDefaultRedOffset) | + (green << RrDefaultGreenOffset) | + (blue << RrDefaultBlueOffset) | + (alpha << RrDefaultAlphaOffset); + } + } + + pic = g_new(RrImagePic, 1); + RrImagePicInit(pic, dstW, dstH, dststart); + + return pic; +} + +/*! This draws an RGBA picture into the target, within the rectangle specified + by the area parameter. If the area's size differs from the source's then it + will be centered within the rectangle */ +void DrawRGBA(RrPixel32 *target, gint target_w, gint target_h, + RrPixel32 *source, gint source_w, gint source_h, + gint alpha, RrRect *area) +{ + RrPixel32 *dest; + gint col, num_pixels; + gint dw, dh; + + g_assert(source_w <= area->width && source_h <= area->height); + g_assert(area->x + area->width <= target_w); + g_assert(area->y + area->height <= target_h); + + /* keep the aspect ratio */ + dw = area->width; + dh = (gint)(dw * ((gdouble)source_h / source_w)); + if (dh > area->height) { + dh = area->height; + dw = (gint)(dh * ((gdouble)source_w / source_h)); + } + + /* copy source -> dest, and apply the alpha channel. + center the image if it is smaller than the area */ + col = 0; + num_pixels = dw * dh; + dest = target + area->x + (area->width - dw) / 2 + + (target_w * (area->y + (area->height - dh) / 2)); + while (num_pixels-- > 0) { + guchar a, r, g, b, bgr, bgg, bgb; + + /* apply the rgba's opacity as well */ + a = ((*source >> RrDefaultAlphaOffset) * alpha) >> 8; + r = *source >> RrDefaultRedOffset; + g = *source >> RrDefaultGreenOffset; + b = *source >> RrDefaultBlueOffset; + + /* background color */ + bgr = *dest >> RrDefaultRedOffset; + bgg = *dest >> RrDefaultGreenOffset; + bgb = *dest >> RrDefaultBlueOffset; + + r = bgr + (((r - bgr) * a) >> 8); + g = bgg + (((g - bgg) * a) >> 8); + b = bgb + (((b - bgb) * a) >> 8); + + *dest = ((r << RrDefaultRedOffset) | + (g << RrDefaultGreenOffset) | + (b << RrDefaultBlueOffset)); + + dest++; + source++; + + if (++col >= dw) { + col = 0; + dest += target_w - dw; + } + } +} + +/*! Draw an RGBA texture into a target pixel buffer. */ +void RrImageDrawRGBA(RrPixel32 *target, RrTextureRGBA *rgba, + gint target_w, gint target_h, + RrRect *area) +{ + RrImagePic *scaled; + + scaled = ResizeImage(rgba->data, rgba->width, rgba->height, + area->width, area->height); + + if (scaled) { +#ifdef DEBUG + g_warning("Scaling an RGBA! You should avoid this and just make " + "it the right size yourself!"); +#endif + DrawRGBA(target, target_w, target_h, + scaled->data, scaled->width, scaled->height, + rgba->alpha, area); + RrImagePicFree(scaled); + } + else + DrawRGBA(target, target_w, target_h, + rgba->data, rgba->width, rgba->height, + rgba->alpha, area); +} + +/*! Create a new RrImage, which is linked to an image cache */ +RrImage* RrImageNew(RrImageCache *cache) +{ + RrImage *self; + + g_assert(cache != NULL); + + self = g_new0(RrImage, 1); + self->ref = 1; + self->cache = cache; + return self; +} + +void RrImageRef(RrImage *self) +{ + ++self->ref; +} + +void RrImageUnref(RrImage *self) +{ + if (self && --self->ref == 0) { +/* +#ifdef DEBUG + g_debug("Refcount to 0, removing ALL pictures from the cache:\n " + "Image 0x%lx", (gulong)self); +#endif +*/ + while (self->n_original > 0) + RemovePicture(self, &self->original, 0, &self->n_original); + while (self->n_resized > 0) + RemovePicture(self, &self->resized, 0, &self->n_resized); + g_free(self); + } +} + +/*! Add a new picture with the given RGBA pixel data and dimensions into the + RrImage. This adds an "original" picture to the image. +*/ +void RrImageAddPicture(RrImage *self, RrPixel32 *data, gint w, gint h) +{ + gint i; + RrImagePic *pic; + + /* make sure we don't already have this size.. */ + for (i = 0; i < self->n_original; ++i) + if (self->original[i]->width == w && self->original[i]->height == h) { +/* +#ifdef DEBUG + g_debug("Found duplicate ORIGINAL image:\n " + "Image 0x%lx, w %d h %d", (gulong)self, w, h); +#endif +*/ + return; + } + + /* remove any resized pictures of this same size */ + for (i = 0; i < self->n_resized; ++i) + if (self->resized[i]->width == w || self->resized[i]->height == h) { + RemovePicture(self, &self->resized, i, &self->n_resized); + break; + } + + /* add the new picture */ + pic = g_new(RrImagePic, 1); + RrImagePicInit(pic, w, h, g_memdup(data, w*h*sizeof(RrPixel32))); + AddPicture(self, &self->original, &self->n_original, pic); +} + +/*! Remove the picture from the RrImage which has the given dimensions. This + removes an "original" picture from the image. +*/ +void RrImageRemovePicture(RrImage *self, gint w, gint h) +{ + gint i; + + /* remove any resized pictures of this same size */ + for (i = 0; i < self->n_original; ++i) + if (self->original[i]->width == w && self->original[i]->height == h) { + RemovePicture(self, &self->original, i, &self->n_original); + break; + } +} + +/*! Draw an RrImage texture into a target pixel buffer. If the RrImage does + not contain a picture of the appropriate size, then one of its "original" + pictures will be resized and used (and stored in the RrImage as a "resized" + picture). + */ +void RrImageDrawImage(RrPixel32 *target, RrTextureImage *img, + gint target_w, gint target_h, + RrRect *area) +{ + gint i, min_diff, min_i, min_aspect_diff, min_aspect_i; + RrImage *self; + RrImagePic *pic; + gboolean free_pic; + + self = img->image; + pic = NULL; + free_pic = FALSE; + + /* is there an original of this size? (only the larger of + w or h has to be right cuz we maintain aspect ratios) */ + for (i = 0; i < self->n_original; ++i) + if ((self->original[i]->width >= self->original[i]->height && + self->original[i]->width == area->width) || + (self->original[i]->width <= self->original[i]->height && + self->original[i]->height == area->height)) + { + pic = self->original[i]; + break; + } + + /* is there a resize of this size? */ + for (i = 0; i < self->n_resized; ++i) + if ((self->resized[i]->width >= self->resized[i]->height && + self->resized[i]->width == area->width) || + (self->resized[i]->width <= self->resized[i]->height && + self->resized[i]->height == area->height)) + { + gint j; + RrImagePic *saved; + + /* save the selected one */ + saved = self->resized[i]; + + /* shift all the others down */ + for (j = i; j > 0; --j) + self->resized[j] = self->resized[j-1]; + + /* and move the selected one to the top of the list */ + self->resized[0] = saved; + + pic = self->resized[0]; + break; + } + + if (!pic) { + gdouble aspect; + + /* find an original with a close size */ + min_diff = min_aspect_diff = -1; + min_i = min_aspect_i = 0; + aspect = ((gdouble)area->width) / area->height; + for (i = 0; i < self->n_original; ++i) { + gint diff; + gint wdiff, hdiff; + gdouble myasp; + + /* our size difference metric.. */ + wdiff = self->original[i]->width - area->width; + hdiff = self->original[i]->height - area->height; + diff = (wdiff * wdiff) + (hdiff * hdiff); + + /* find the smallest difference */ + if (min_diff < 0 || diff < min_diff) { + min_diff = diff; + min_i = i; + } + /* and also find the smallest difference with the same aspect + ratio (and prefer this one) */ + myasp = ((gdouble)self->original[i]->width) / + self->original[i]->height; + if (ABS(aspect - myasp) < 0.0000001 && + (min_aspect_diff < 0 || diff < min_aspect_diff)) + { + min_aspect_diff = diff; + min_aspect_i = i; + } + } + + /* use the aspect ratio correct source if there is one */ + if (min_aspect_i >= 0) + min_i = min_aspect_i; + + /* resize the original to the given area */ + pic = ResizeImage(self->original[min_i]->data, + self->original[min_i]->width, + self->original[min_i]->height, + area->width, area->height); + + /* add the resized image to the image, as the first in the resized + list */ + if (self->n_resized >= self->cache->max_resized_saved) + /* remove the last one (last used one) */ + RemovePicture(self, &self->resized, self->n_resized - 1, + &self->n_resized); + if (self->cache->max_resized_saved) + /* add it to the top of the resized list */ + AddPicture(self, &self->resized, &self->n_resized, pic); + else + free_pic = TRUE; /* don't leak mem! */ + } + + g_assert(pic != NULL); + + DrawRGBA(target, target_w, target_h, + pic->data, pic->width, pic->height, + img->alpha, area); + if (free_pic) + RrImagePicFree(pic); +} diff --git a/obrender/image.h b/obrender/image.h new file mode 100644 index 00000000..b478daf9 --- /dev/null +++ b/obrender/image.h @@ -0,0 +1,35 @@ +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + image.h for the Openbox window manager + Copyright (c) 2003-2007 Dana Jansens + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + See the COPYING file for a copy of the GNU General Public License. +*/ + +#ifndef __image_h +#define __image_h + +#include "render.h" +#include "geom.h" + +/*! Initialize an RrImagePicture to the specified dimensions and pixel data */ +void RrImagePicInit(RrImagePic *pic, gint w, gint h, RrPixel32 *data); + +void RrImageDrawImage(RrPixel32 *target, RrTextureImage *img, + gint target_w, gint target_h, + RrRect *area); +void RrImageDrawRGBA(RrPixel32 *target, RrTextureRGBA *rgba, + gint target_w, gint target_h, + RrRect *area); + +#endif diff --git a/obrender/imagecache.c b/obrender/imagecache.c new file mode 100644 index 00000000..9c605f9d --- /dev/null +++ b/obrender/imagecache.c @@ -0,0 +1,144 @@ +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + imagecache.c for the Openbox window manager + Copyright (c) 2008 Dana Jansens + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + See the COPYING file for a copy of the GNU General Public License. +*/ + +#include "render.h" +#include "imagecache.h" +#include "image.h" + +static gboolean RrImagePicEqual(const RrImagePic *p1, + const RrImagePic *p2); + +RrImageCache* RrImageCacheNew(gint max_resized_saved) +{ + RrImageCache *self; + + g_assert(max_resized_saved >= 0); + + self = g_new(RrImageCache, 1); + self->ref = 1; + self->max_resized_saved = max_resized_saved; + self->table = g_hash_table_new((GHashFunc)RrImagePicHash, + (GEqualFunc)RrImagePicEqual); + return self; +} + +void RrImageCacheRef(RrImageCache *self) +{ + ++self->ref; +} + +void RrImageCacheUnref(RrImageCache *self) +{ + if (self && --self->ref == 0) { + g_assert(g_hash_table_size(self->table) == 0); + g_hash_table_unref(self->table); + + g_free(self); + } +} + +/*! Finds an image in the cache, if it is already in there */ +RrImage* RrImageCacheFind(RrImageCache *self, + RrPixel32 *data, gint w, gint h) +{ + RrImagePic pic; + + RrImagePicInit(&pic, w, h, data); + return g_hash_table_lookup(self->table, &pic); +} + +#define hashsize(n) ((RrPixel32)1<<(n)) +#define hashmask(n) (hashsize(n)-1) +#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) +/* mix -- mix 3 32-bit values reversibly. */ +#define mix(a,b,c) \ +{ \ + a -= c; a ^= rot(c, 4); c += b; \ + b -= a; b ^= rot(a, 6); a += c; \ + c -= b; c ^= rot(b, 8); b += a; \ + a -= c; a ^= rot(c,16); c += b; \ + b -= a; b ^= rot(a,19); a += c; \ + c -= b; c ^= rot(b, 4); b += a; \ +} +/* final -- final mixing of 3 32-bit values (a,b,c) into c */ +#define final(a,b,c) \ +{ \ + c ^= b; c -= rot(b,14); \ + a ^= c; a -= rot(c,11); \ + b ^= a; b -= rot(a,25); \ + c ^= b; c -= rot(b,16); \ + a ^= c; a -= rot(c,4); \ + b ^= a; b -= rot(a,14); \ + c ^= b; c -= rot(b,24); \ +} + +/* This is a fast, reversable hash function called "lookup3", found here: + http://burtleburtle.net/bob/c/lookup3.c, by Bob Jenkins + + This hashing algorithm is "reversible", that is, not cryptographically + secure at all. But we don't care about that, we just want something to + tell when images are the same or different relatively quickly. +*/ +guint32 hashword(const guint32 *key, gint length, guint32 initval) +{ + guint32 a,b,c; + + /* Set up the internal state */ + a = b = c = 0xdeadbeef + (((guint32)length)<<2) + initval; + + /* handle most of the key */ + while (length > 3) + { + a += key[0]; + b += key[1]; + c += key[2]; + mix(a,b,c); + length -= 3; + key += 3; + } + + /* handle the last 3 guint32's */ + switch(length) /* all the case statements fall through */ + { + case 3: c+=key[2]; + case 2: b+=key[1]; + case 1: a+=key[0]; + final(a,b,c); + case 0: /* case 0: nothing left to add */ + break; + } + /* report the result */ + return c; +} + +/*! This is some arbitrary initial value for the hashing function. It's + constant so that you get the same result from the same data each time. +*/ +#define HASH_INITVAL 0xf00d + +guint RrImagePicHash(const RrImagePic *p) +{ + return hashword(p->data, p->width * p->height, HASH_INITVAL); +} + +static gboolean RrImagePicEqual(const RrImagePic *p1, + const RrImagePic *p2) +{ + return p1->width == p2->width && p1->height == p2->height && + p1->sum == p2->sum; +} diff --git a/obrender/imagecache.h b/obrender/imagecache.h new file mode 100644 index 00000000..4ad2deae --- /dev/null +++ b/obrender/imagecache.h @@ -0,0 +1,51 @@ +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + imagecache.h for the Openbox window manager + Copyright (c) 2008 Dana Jansens + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + See the COPYING file for a copy of the GNU General Public License. +*/ + +#ifndef __imagecache_h +#define __imagecache_h + +#include + +struct _RrImagePic; + +guint RrImagePicHash(const struct _RrImagePic *p); + +/*! Create a new image cache. An image cache is basically a hash table to look + up RrImages. Each RrImage in the cache may contain one or more Pictures, + that is one or more actual copies of image data at various sizes. For eg, + for a window, all of its various icons are loaded into the same RrImage. + When an RrImage is drawn and a picture inside it needs to be resized, that + is also saved within the RrImage. + + For each picture that an RrImage has, the picture is hashed and that is used + as a key to find the RrImage. So, given any picture in any RrImage in the + cache, if you hash it, you will find the RrImage. +*/ +struct _RrImageCache { + gint ref; + /*! When an original picture is resized for an RrImage, the resized picture + is saved in the RrImage. This specifies how many pictures should be + saved at a time. When this is exceeded, the least recently used + "resized" picture is deleted. + */ + gint max_resized_saved; + + GHashTable *table; +}; + +#endif diff --git a/obrender/instance.c b/obrender/instance.c new file mode 100644 index 00000000..b867815c --- /dev/null +++ b/obrender/instance.c @@ -0,0 +1,309 @@ +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + instance.c for the Openbox window manager + Copyright (c) 2006 Mikael Magnusson + Copyright (c) 2003-2007 Dana Jansens + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + See the COPYING file for a copy of the GNU General Public License. +*/ + +#include "render.h" +#include "instance.h" + +static RrInstance *definst = NULL; + +static void RrTrueColorSetup (RrInstance *inst); +static void RrPseudoColorSetup (RrInstance *inst); + +#ifdef DEBUG +#include "color.h" +#endif +static void +dest(gpointer data) +{ +#ifdef DEBUG + RrColor *c = data; + if (c->refcount > 0) + g_error("color %d (%d,%d,%d) in hash table with %d " + "leftover references", + c->id, RrColorRed(c), RrColorGreen(c), RrColorBlue(c), + c->refcount); +#endif +} + +#if 0 +static void f(gpointer key, gpointer value, gpointer n) +{ + RrColor *c = value; + if (c->id == *(gint*)n) + g_message("color %d has %d references", c->id, c->refcount); +} + +void print_refs(gint id) +{ + g_hash_table_foreach(RrColorHash(definst), f, &id); +} +#endif + +RrInstance* RrInstanceNew (Display *display, gint screen) +{ + g_type_init(); /* supposedly needed for pango but seems to work without */ + + definst = g_new (RrInstance, 1); + definst->display = display; + definst->screen = screen; + + definst->depth = DefaultDepth(display, screen); + definst->visual = DefaultVisual(display, screen); + definst->colormap = DefaultColormap(display, screen); + definst->pango = pango_xft_get_context(display, screen); + + definst->pseudo_colors = NULL; + + definst->color_hash = g_hash_table_new_full(g_int_hash, g_int_equal, + NULL, dest); + + switch (definst->visual->class) { + case TrueColor: + RrTrueColorSetup(definst); + break; + case PseudoColor: + case StaticColor: + case GrayScale: + case StaticGray: + RrPseudoColorSetup(definst); + break; + default: + g_critical("Unsupported visual class"); + g_free (definst); + return definst = NULL; + } + return definst; +} + +static void RrTrueColorSetup (RrInstance *inst) +{ + gulong red_mask, green_mask, blue_mask; + XImage *timage = NULL; + + timage = XCreateImage(inst->display, inst->visual, inst->depth, + ZPixmap, 0, NULL, 1, 1, 32, 0); + g_assert(timage != NULL); + /* find the offsets for each color in the visual's masks */ + inst->red_mask = red_mask = timage->red_mask; + inst->green_mask = green_mask = timage->green_mask; + inst->blue_mask = blue_mask = timage->blue_mask; + + inst->red_offset = 0; + inst->green_offset = 0; + inst->blue_offset = 0; + + while (! (red_mask & 1)) { inst->red_offset++; red_mask >>= 1; } + while (! (green_mask & 1)) { inst->green_offset++; green_mask >>= 1; } + while (! (blue_mask & 1)) { inst->blue_offset++; blue_mask >>= 1; } + + inst->red_shift = inst->green_shift = inst->blue_shift = 8; + while (red_mask) { red_mask >>= 1; inst->red_shift--; } + while (green_mask) { green_mask >>= 1; inst->green_shift--; } + while (blue_mask) { blue_mask >>= 1; inst->blue_shift--; } + XFree(timage); +} + +#define RrPseudoNcolors(inst) (1 << (inst->pseudo_bpc * 3)) + +static void RrPseudoColorSetup (RrInstance *inst) +{ + XColor icolors[256]; + gint tr, tg, tb, n, r, g, b, i, incolors, ii; + gulong dev; + gint cpc, _ncolors; + + /* determine the number of colors and the bits-per-color */ + inst->pseudo_bpc = 2; /* XXX THIS SHOULD BE A USER OPTION */ + g_assert(inst->pseudo_bpc >= 1); + _ncolors = RrPseudoNcolors(inst); + + if (_ncolors > 1 << inst->depth) { + g_message("Invalid colormap size. Resizing."); + inst->pseudo_bpc = 1 << (inst->depth/3) >> 3; + _ncolors = 1 << (inst->pseudo_bpc * 3); + } + + /* build a color cube */ + inst->pseudo_colors = g_new(XColor, _ncolors); + cpc = 1 << inst->pseudo_bpc; /* colors per channel */ + + for (n = 0, r = 0; r < cpc; r++) + for (g = 0; g < cpc; g++) + for (b = 0; b < cpc; b++, n++) { + tr = (gint)(((gfloat)(r)/(gfloat)(cpc-1)) * 0xFF); + tg = (gint)(((gfloat)(g)/(gfloat)(cpc-1)) * 0xFF); + tb = (gint)(((gfloat)(b)/(gfloat)(cpc-1)) * 0xFF); + inst->pseudo_colors[n].red = tr | tr << 8; + inst->pseudo_colors[n].green = tg | tg << 8; + inst->pseudo_colors[n].blue = tb | tb << 8; + /* used to track allocation */ + inst->pseudo_colors[n].flags = DoRed|DoGreen|DoBlue; + } + + /* allocate the colors */ + for (i = 0; i < _ncolors; i++) + if (!XAllocColor(inst->display, inst->colormap, + &inst->pseudo_colors[i])) + inst->pseudo_colors[i].flags = 0; /* mark it as unallocated */ + + /* try allocate any colors that failed allocation above */ + + /* get the allocated values from the X server + (only the first 256 XXX why!?) + */ + incolors = (((1 << inst->depth) > 256) ? 256 : (1 << inst->depth)); + for (i = 0; i < incolors; i++) + icolors[i].pixel = i; + XQueryColors(inst->display, inst->colormap, icolors, incolors); + + /* try match unallocated ones */ + for (i = 0; i < _ncolors; i++) { + if (!inst->pseudo_colors[i].flags) { /* if it wasn't allocated... */ + gulong closest = 0xffffffff, close = 0; + for (ii = 0; ii < incolors; ii++) { + /* find deviations */ + r = (inst->pseudo_colors[i].red - icolors[ii].red) & 0xff; + g = (inst->pseudo_colors[i].green - icolors[ii].green) & 0xff; + b = (inst->pseudo_colors[i].blue - icolors[ii].blue) & 0xff; + /* find a weighted absolute deviation */ + dev = (r * r) + (g * g) + (b * b); + + if (dev < closest) { + closest = dev; + close = ii; + } + } + + inst->pseudo_colors[i].red = icolors[close].red; + inst->pseudo_colors[i].green = icolors[close].green; + inst->pseudo_colors[i].blue = icolors[close].blue; + inst->pseudo_colors[i].pixel = icolors[close].pixel; + + /* try alloc this closest color, it had better succeed! */ + if (XAllocColor(inst->display, inst->colormap, + &inst->pseudo_colors[i])) + /* mark as alloced */ + inst->pseudo_colors[i].flags = DoRed|DoGreen|DoBlue; + else + /* wtf has gone wrong, its already alloced for chissake! */ + g_assert_not_reached(); + } + } +} + +void RrInstanceFree (RrInstance *inst) +{ + if (inst) { + if (inst == definst) definst = NULL; + g_free(inst->pseudo_colors); + g_hash_table_destroy(inst->color_hash); + g_object_unref(inst->pango); + g_free(inst); + } +} + +Display* RrDisplay (const RrInstance *inst) +{ + return (inst ? inst : definst)->display; +} + +gint RrScreen (const RrInstance *inst) +{ + return (inst ? inst : definst)->screen; +} + +Window RrRootWindow (const RrInstance *inst) +{ + return RootWindow (RrDisplay (inst), RrScreen (inst)); +} + +Visual *RrVisual (const RrInstance *inst) +{ + return (inst ? inst : definst)->visual; +} + +gint RrDepth (const RrInstance *inst) +{ + return (inst ? inst : definst)->depth; +} + +Colormap RrColormap (const RrInstance *inst) +{ + return (inst ? inst : definst)->colormap; +} + +gint RrRedOffset (const RrInstance *inst) +{ + return (inst ? inst : definst)->red_offset; +} + +gint RrGreenOffset (const RrInstance *inst) +{ + return (inst ? inst : definst)->green_offset; +} + +gint RrBlueOffset (const RrInstance *inst) +{ + return (inst ? inst : definst)->blue_offset; +} + +gint RrRedShift (const RrInstance *inst) +{ + return (inst ? inst : definst)->red_shift; +} + +gint RrGreenShift (const RrInstance *inst) +{ + return (inst ? inst : definst)->green_shift; +} + +gint RrBlueShift (const RrInstance *inst) +{ + return (inst ? inst : definst)->blue_shift; +} + +gint RrRedMask (const RrInstance *inst) +{ + return (inst ? inst : definst)->red_mask; +} + +gint RrGreenMask (const RrInstance *inst) +{ + return (inst ? inst : definst)->green_mask; +} + +gint RrBlueMask (const RrInstance *inst) +{ + return (inst ? inst : definst)->blue_mask; +} + +guint RrPseudoBPC (const RrInstance *inst) +{ + return (inst ? inst : definst)->pseudo_bpc; +} + +XColor *RrPseudoColors (const RrInstance *inst) +{ + return (inst ? inst : definst)->pseudo_colors; +} + +GHashTable* RrColorHash (const RrInstance *inst) +{ + return (inst ? inst : definst)->color_hash; +} diff --git a/obrender/instance.h b/obrender/instance.h new file mode 100644 index 00000000..324f061a --- /dev/null +++ b/obrender/instance.h @@ -0,0 +1,57 @@ +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + instance.h for the Openbox window manager + Copyright (c) 2003-2007 Dana Jansens + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + See the COPYING file for a copy of the GNU General Public License. +*/ + +#ifndef __render_instance_h +#define __render_instance_h + +#include +#include +#include + +struct _RrInstance { + Display *display; + gint screen; + + Visual *visual; + gint depth; + Colormap colormap; + PangoContext *pango; + + gint red_offset; + gint green_offset; + gint blue_offset; + + gint red_shift; + gint green_shift; + gint blue_shift; + + gint red_mask; + gint green_mask; + gint blue_mask; + + gint pseudo_bpc; + XColor *pseudo_colors; + + GHashTable *color_hash; +}; + +guint RrPseudoBPC (const RrInstance *inst); +XColor* RrPseudoColors (const RrInstance *inst); +GHashTable* RrColorHash (const RrInstance *inst); + +#endif diff --git a/obrender/mask.c b/obrender/mask.c new file mode 100644 index 00000000..b6e3c443 --- /dev/null +++ b/obrender/mask.c @@ -0,0 +1,82 @@ +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + mask.c for the Openbox window manager + Copyright (c) 2003-2007 Dana Jansens + Copyright (c) 2003 Derek Foreman + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + See the COPYING file for a copy of the GNU General Public License. +*/ + +#include "render.h" +#include "color.h" +#include "mask.h" + +RrPixmapMask *RrPixmapMaskNew(const RrInstance *inst, + gint w, gint h, const gchar *data) +{ + RrPixmapMask *m = g_new(RrPixmapMask, 1); + m->inst = inst; + m->width = w; + m->height = h; + /* round up to nearest byte */ + m->data = g_memdup(data, (w + 7) / 8 * h); + m->mask = XCreateBitmapFromData(RrDisplay(inst), RrRootWindow(inst), + data, w, h); + return m; +} + +void RrPixmapMaskFree(RrPixmapMask *m) +{ + if (m) { + XFreePixmap(RrDisplay(m->inst), m->mask); + g_free(m->data); + g_free(m); + } +} + +void RrPixmapMaskDraw(Pixmap p, const RrTextureMask *m, const RrRect *area) +{ + gint x, y; + if (m->mask == NULL) return; /* no mask given */ + + /* set the clip region */ + x = area->x + (area->width - m->mask->width) / 2; + y = area->y + (area->height - m->mask->height) / 2; + + if (x < 0) x = 0; + if (y < 0) y = 0; + + XSetClipMask(RrDisplay(m->mask->inst), RrColorGC(m->color), m->mask->mask); + XSetClipOrigin(RrDisplay(m->mask->inst), RrColorGC(m->color), x, y); + + /* fill in the clipped region */ + XFillRectangle(RrDisplay(m->mask->inst), p, RrColorGC(m->color), x, y, + x + m->mask->width, y + m->mask->height); + + /* unset the clip region */ + XSetClipMask(RrDisplay(m->mask->inst), RrColorGC(m->color), None); + XSetClipOrigin(RrDisplay(m->mask->inst), RrColorGC(m->color), 0, 0); +} + +RrPixmapMask *RrPixmapMaskCopy(const RrPixmapMask *src) +{ + RrPixmapMask *m = g_new(RrPixmapMask, 1); + m->inst = src->inst; + m->width = src->width; + m->height = src->height; + /* round up to nearest byte */ + m->data = g_memdup(src->data, (src->width + 7) / 8 * src->height); + m->mask = XCreateBitmapFromData(RrDisplay(m->inst), RrRootWindow(m->inst), + m->data, m->width, m->height); + return m; +} diff --git a/obrender/mask.h b/obrender/mask.h new file mode 100644 index 00000000..4dc85031 --- /dev/null +++ b/obrender/mask.h @@ -0,0 +1,32 @@ +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + mask.h for the Openbox window manager + Copyright (c) 2003-2007 Dana Jansens + Copyright (c) 2003 Derek Foreman + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + See the COPYING file for a copy of the GNU General Public License. +*/ + +#ifndef __mask_h +#define __mask_h + +#include "render.h" +#include "geom.h" + +RrPixmapMask *RrPixmapMaskNew(const RrInstance *inst, + gint w, gint h, const gchar *data); +void RrPixmapMaskFree(RrPixmapMask *m); +RrPixmapMask *RrPixmapMaskCopy(const RrPixmapMask *src); +void RrPixmapMaskDraw(Pixmap p, const RrTextureMask *m, const RrRect *area); + +#endif diff --git a/obrender/obrender-3.5.pc.in b/obrender/obrender-3.5.pc.in new file mode 100644 index 00000000..78646e32 --- /dev/null +++ b/obrender/obrender-3.5.pc.in @@ -0,0 +1,14 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +xcflags=@X_CFLAGS@ +xlibs=@X_LIBS@ + +Name: ObRender +Description: Openbox Render Library +Version: @RR_VERSION@ +Requires: obt-3.5 glib-2.0 xft pangoxft +Libs: -L${libdir} -lobrender ${xlibs} +Cflags: -I${includedir}/openbox/@RR_VERSION@ ${xcflags} diff --git a/obrender/render.c b/obrender/render.c new file mode 100644 index 00000000..20002e32 --- /dev/null +++ b/obrender/render.c @@ -0,0 +1,564 @@ +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + render.c for the Openbox window manager + Copyright (c) 2006 Mikael Magnusson + Copyright (c) 2003-2007 Dana Jansens + Copyright (c) 2003 Derek Foreman + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + See the COPYING file for a copy of the GNU General Public License. +*/ + +#include "render.h" +#include "gradient.h" +#include "font.h" +#include "mask.h" +#include "color.h" +#include "image.h" +#include "theme.h" + +#include +#include +#include +#include + +#ifdef HAVE_STDLIB_H +# include +#endif + +static void pixel_data_to_pixmap(RrAppearance *l, + gint x, gint y, gint w, gint h); + +Pixmap RrPaintPixmap(RrAppearance *a, gint w, gint h) +{ + gint i, transferred = 0, force_transfer = 0; + Pixmap oldp = None; + RrRect tarea; /* area in which to draw textures */ + gboolean resized; + + if (w <= 0 || h <= 0) return None; + + if (a->surface.parentx < 0 || a->surface.parenty < 0) { + /* ob_debug("Invalid parent co-ordinates\n"); */ + return None; + } + + if (a->surface.grad == RR_SURFACE_PARENTREL && + (a->surface.parentx >= a->surface.parent->w || + a->surface.parenty >= a->surface.parent->h)) + { + return None; + } + + resized = (a->w != w || a->h != h); + + oldp = a->pixmap; /* save to free after changing the visible pixmap */ + a->pixmap = XCreatePixmap(RrDisplay(a->inst), + RrRootWindow(a->inst), + w, h, RrDepth(a->inst)); + + g_assert(a->pixmap != None); + a->w = w; + a->h = h; + + if (a->xftdraw != NULL) + XftDrawDestroy(a->xftdraw); + a->xftdraw = XftDrawCreate(RrDisplay(a->inst), a->pixmap, + RrVisual(a->inst), RrColormap(a->inst)); + g_assert(a->xftdraw != NULL); + + if (resized) { + g_free(a->surface.pixel_data); + a->surface.pixel_data = g_new(RrPixel32, w * h); + } + + RrRender(a, w, h); + + { + gint l, t, r, b; + RrMargins(a, &l, &t, &r, &b); + RECT_SET(tarea, l, t, w - l - r, h - t - b); + } + + for (i = 0; i < a->textures; i++) { + switch (a->texture[i].type) { + case RR_TEXTURE_NONE: + break; + case RR_TEXTURE_TEXT: + if (!transferred) { + transferred = 1; + if ((a->surface.grad != RR_SURFACE_SOLID) + || (a->surface.interlaced)) + pixel_data_to_pixmap(a, 0, 0, w, h); + } + if (a->xftdraw == NULL) { + a->xftdraw = XftDrawCreate(RrDisplay(a->inst), a->pixmap, + RrVisual(a->inst), + RrColormap(a->inst)); + } + RrFontDraw(a->xftdraw, &a->texture[i].data.text, &tarea); + break; + case RR_TEXTURE_LINE_ART: + if (!transferred) { + transferred = 1; + if ((a->surface.grad != RR_SURFACE_SOLID) + || (a->surface.interlaced)) + pixel_data_to_pixmap(a, 0, 0, w, h); + } + XDrawLine(RrDisplay(a->inst), a->pixmap, + RrColorGC(a->texture[i].data.lineart.color), + a->texture[i].data.lineart.x1, + a->texture[i].data.lineart.y1, + a->texture[i].data.lineart.x2, + a->texture[i].data.lineart.y2); + break; + case RR_TEXTURE_MASK: + if (!transferred) { + transferred = 1; + if ((a->surface.grad != RR_SURFACE_SOLID) + || (a->surface.interlaced)) + pixel_data_to_pixmap(a, 0, 0, w, h); + } + RrPixmapMaskDraw(a->pixmap, &a->texture[i].data.mask, &tarea); + break; + case RR_TEXTURE_IMAGE: + g_assert(!transferred); + { + RrRect narea = tarea; + RrTextureImage *img = &a->texture[i].data.image; + narea.x += img->tx; + narea.width -= img->tx; + narea.y += img->ty; + narea.height -= img->ty; + if (img->twidth) + narea.width = MIN(narea.width, img->twidth); + if (img->theight) + narea.height = MIN(narea.height, img->theight); + RrImageDrawImage(a->surface.pixel_data, + &a->texture[i].data.image, + a->w, a->h, + &narea); + } + force_transfer = 1; + break; + case RR_TEXTURE_RGBA: + g_assert(!transferred); + { + RrRect narea = tarea; + RrTextureRGBA *rgb = &a->texture[i].data.rgba; + narea.x += rgb->tx; + narea.width -= rgb->tx; + narea.y += rgb->ty; + narea.height -= rgb->ty; + if (rgb->twidth) + narea.width = MIN(narea.width, rgb->twidth); + if (rgb->theight) + narea.height = MIN(narea.height, rgb->theight); + RrImageDrawRGBA(a->surface.pixel_data, + &a->texture[i].data.rgba, + a->w, a->h, + &narea); + } + force_transfer = 1; + break; + } + } + + if (!transferred) { + transferred = 1; + if ((a->surface.grad != RR_SURFACE_SOLID) || (a->surface.interlaced) || + force_transfer) + { + pixel_data_to_pixmap(a, 0, 0, w, h); + } + } + + return oldp; +} + +void RrPaint(RrAppearance *a, Window win, gint w, gint h) +{ + Pixmap oldp; + + oldp = RrPaintPixmap(a, w, h); + XSetWindowBackgroundPixmap(RrDisplay(a->inst), win, a->pixmap); + XClearWindow(RrDisplay(a->inst), win); + /* free this after changing the visible pixmap */ + if (oldp) XFreePixmap(RrDisplay(a->inst), oldp); +} + +RrAppearance *RrAppearanceNew(const RrInstance *inst, gint numtex) +{ + RrAppearance *out; + + out = g_new0(RrAppearance, 1); + out->inst = inst; + out->textures = numtex; + out->surface.bevel_light_adjust = 128; + out->surface.bevel_dark_adjust = 64; + if (numtex) out->texture = g_new0(RrTexture, numtex); + + return out; +} + +void RrAppearanceRemoveTextures(RrAppearance *a) +{ + g_free(a->texture); + a->textures = 0; +} + +void RrAppearanceAddTextures(RrAppearance *a, gint numtex) +{ + g_assert(a->textures == 0); + + a->textures = numtex; + if (numtex) a->texture = g_new0(RrTexture, numtex); +} + +void RrAppearanceClearTextures(RrAppearance *a) +{ + memset(a->texture, 0, a->textures * sizeof(RrTexture)); +} + +RrAppearance *RrAppearanceCopy(RrAppearance *orig) +{ + RrSurface *spo, *spc; + RrAppearance *copy = g_new(RrAppearance, 1); + + copy->inst = orig->inst; + + spo = &(orig->surface); + spc = &(copy->surface); + spc->grad = spo->grad; + spc->relief = spo->relief; + spc->bevel = spo->bevel; + if (spo->primary != NULL) + spc->primary = RrColorNew(copy->inst, + spo->primary->r, + spo->primary->g, + spo->primary->b); + else spc->primary = NULL; + + if (spo->secondary != NULL) + spc->secondary = RrColorNew(copy->inst, + spo->secondary->r, + spo->secondary->g, + spo->secondary->b); + else spc->secondary = NULL; + + if (spo->border_color != NULL) + spc->border_color = RrColorNew(copy->inst, + spo->border_color->r, + spo->border_color->g, + spo->border_color->b); + else spc->border_color = NULL; + + if (spo->interlace_color != NULL) + spc->interlace_color = RrColorNew(copy->inst, + spo->interlace_color->r, + spo->interlace_color->g, + spo->interlace_color->b); + else spc->interlace_color = NULL; + + if (spo->bevel_dark != NULL) + spc->bevel_dark = RrColorNew(copy->inst, + spo->bevel_dark->r, + spo->bevel_dark->g, + spo->bevel_dark->b); + else spc->bevel_dark = NULL; + + if (spo->bevel_light != NULL) + spc->bevel_light = RrColorNew(copy->inst, + spo->bevel_light->r, + spo->bevel_light->g, + spo->bevel_light->b); + else spc->bevel_light = NULL; + + if (spo->split_primary != NULL) + spc->split_primary = RrColorNew(copy->inst, + spo->split_primary->r, + spo->split_primary->g, + spo->split_primary->b); + else spc->split_primary = NULL; + + if (spo->split_secondary != NULL) + spc->split_secondary = RrColorNew(copy->inst, + spo->split_secondary->r, + spo->split_secondary->g, + spo->split_secondary->b); + else spc->split_secondary = NULL; + + spc->interlaced = spo->interlaced; + spc->bevel_light_adjust = spo->bevel_light_adjust; + spc->bevel_dark_adjust = spo->bevel_dark_adjust; + spc->border = spo->border; + spc->parent = NULL; + spc->parentx = spc->parenty = 0; + spc->pixel_data = NULL; + + copy->textures = orig->textures; + copy->texture = g_memdup(orig->texture, + orig->textures * sizeof(RrTexture)); + copy->pixmap = None; + copy->xftdraw = NULL; + copy->w = copy->h = 0; + return copy; +} + +void RrAppearanceFree(RrAppearance *a) +{ + if (a) { + RrSurface *p; + if (a->pixmap != None) XFreePixmap(RrDisplay(a->inst), a->pixmap); + if (a->xftdraw != NULL) XftDrawDestroy(a->xftdraw); + if (a->textures) + g_free(a->texture); + p = &a->surface; + RrColorFree(p->primary); + RrColorFree(p->secondary); + RrColorFree(p->border_color); + RrColorFree(p->interlace_color); + RrColorFree(p->bevel_dark); + RrColorFree(p->bevel_light); + RrColorFree(p->split_primary); + RrColorFree(p->split_secondary); + g_free(p->pixel_data); + p->pixel_data = NULL; + g_free(a); + } +} + +static void pixel_data_to_pixmap(RrAppearance *l, + gint x, gint y, gint w, gint h) +{ + RrPixel32 *in, *scratch; + Pixmap out; + XImage *im = NULL; + im = XCreateImage(RrDisplay(l->inst), RrVisual(l->inst), RrDepth(l->inst), + ZPixmap, 0, NULL, w, h, 32, 0); + g_assert(im != NULL); + + in = l->surface.pixel_data; + out = l->pixmap; + +/* this malloc is a complete waste of time on normal 32bpp + as reduce_depth just sets im->data = data and returns +*/ + scratch = g_new(RrPixel32, im->width * im->height); + im->data = (gchar*) scratch; + RrReduceDepth(l->inst, in, im); + XPutImage(RrDisplay(l->inst), out, + DefaultGC(RrDisplay(l->inst), RrScreen(l->inst)), + im, 0, 0, x, y, w, h); + im->data = NULL; + XDestroyImage(im); + g_free(scratch); +} + +void RrMargins (RrAppearance *a, gint *l, gint *t, gint *r, gint *b) +{ + *l = *t = *r = *b = 0; + + if (a->surface.grad != RR_SURFACE_PARENTREL) { + if (a->surface.relief != RR_RELIEF_FLAT) { + switch (a->surface.bevel) { + case RR_BEVEL_1: + *l = *t = *r = *b = 1; + break; + case RR_BEVEL_2: + *l = *t = *r = *b = 2; + break; + } + } else if (a->surface.border) { + *l = *t = *r = *b = 1; + } + } +} + +void RrMinSize(RrAppearance *a, gint *w, gint *h) +{ + *w = RrMinWidth(a); + *h = RrMinHeight(a); +} + +gint RrMinWidth(RrAppearance *a) +{ + gint i; + RrSize *m; + gint l, t, r, b; + gint w = 0; + + RrMargins(a, &l, &t, &r, &b); + + for (i = 0; i < a->textures; ++i) { + switch (a->texture[i].type) { + case RR_TEXTURE_NONE: + break; + case RR_TEXTURE_MASK: + w = MAX(w, a->texture[i].data.mask.mask->width); + break; + case RR_TEXTURE_TEXT: + m = RrFontMeasureString(a->texture[i].data.text.font, + a->texture[i].data.text.string, + a->texture[i].data.text.shadow_offset_x, + a->texture[i].data.text.shadow_offset_y, + a->texture[i].data.text.flow, + a->texture[i].data.text.maxwidth); + w = MAX(w, m->width); + g_free(m); + break; + case RR_TEXTURE_RGBA: + w += MAX(w, a->texture[i].data.rgba.width); + break; + case RR_TEXTURE_IMAGE: + /* images resize so they don't contribute anything to the min */ + break; + case RR_TEXTURE_LINE_ART: + w = MAX(w, MAX(a->texture[i].data.lineart.x1 - l - r, + a->texture[i].data.lineart.x2 - l - r)); + break; + } + } + + w += l + r; + + if (w < 1) w = 1; + return w; +} + +gint RrMinHeight(RrAppearance *a) +{ + gint i; + gint l, t, r, b; + RrSize *m; + gint h = 0; + + RrMargins(a, &l, &t, &r, &b); + + for (i = 0; i < a->textures; ++i) { + switch (a->texture[i].type) { + case RR_TEXTURE_NONE: + break; + case RR_TEXTURE_MASK: + h = MAX(h, a->texture[i].data.mask.mask->height); + break; + case RR_TEXTURE_TEXT: + if (a->texture[i].data.text.flow) { + g_assert(a->texture[i].data.text.string != NULL); + + m = RrFontMeasureString + (a->texture[i].data.text.font, + a->texture[i].data.text.string, + a->texture[i].data.text.shadow_offset_x, + a->texture[i].data.text.shadow_offset_y, + a->texture[i].data.text.flow, + a->texture[i].data.text.maxwidth); + h += MAX(h, m->height); + g_free(m); + } + else + h += MAX(h, + RrFontHeight + (a->texture[i].data.text.font, + a->texture[i].data.text.shadow_offset_y)); + break; + case RR_TEXTURE_RGBA: + h += MAX(h, a->texture[i].data.rgba.height); + break; + case RR_TEXTURE_IMAGE: + /* images resize so they don't contribute anything to the min */ + break; + case RR_TEXTURE_LINE_ART: + h = MAX(h, MAX(a->texture[i].data.lineart.y1 - t - b, + a->texture[i].data.lineart.y2 - t - b)); + break; + } + } + + h += t + b; + + if (h < 1) h = 1; + return h; +} + +static void reverse_bits(gchar *c, gint n) +{ + gint i; + for (i = 0; i < n; i++, c++) + *c = (((*c * 0x0802UL & 0x22110UL) | + (*c * 0x8020UL & 0x88440UL)) * 0x10101UL) >> 16; +} + +gboolean RrPixmapToRGBA(const RrInstance *inst, + Pixmap pmap, Pixmap mask, + gint *w, gint *h, RrPixel32 **data) +{ + Window xr; + gint xx, xy; + guint pw, ph, mw, mh, xb, xd, i, x, y, di; + XImage *xi, *xm = NULL; + + if (!XGetGeometry(RrDisplay(inst), pmap, + &xr, &xx, &xy, &pw, &ph, &xb, &xd)) + return FALSE; + + if (mask) { + if (!XGetGeometry(RrDisplay(inst), mask, + &xr, &xx, &xy, &mw, &mh, &xb, &xd)) + return FALSE; + if (pw != mw || ph != mh || xd != 1) + return FALSE; + } + + xi = XGetImage(RrDisplay(inst), pmap, + 0, 0, pw, ph, 0xffffffff, ZPixmap); + if (!xi) + return FALSE; + + if (mask) { + xm = XGetImage(RrDisplay(inst), mask, + 0, 0, mw, mh, 0xffffffff, ZPixmap); + if (!xm) { + XDestroyImage(xi); + return FALSE; + } + if ((xm->bits_per_pixel == 1) && (xm->bitmap_bit_order != LSBFirst)) + reverse_bits(xm->data, xm->bytes_per_line * xm->height); + } + + if ((xi->bits_per_pixel == 1) && (xi->bitmap_bit_order != LSBFirst)) + reverse_bits(xi->data, xi->bytes_per_line * xi->height); + + *data = g_new(RrPixel32, pw * ph); + RrIncreaseDepth(inst, *data, xi); + + if (mask) { + /* apply transparency from the mask */ + di = 0; + for (i = 0, y = 0; y < ph; ++y) { + for (x = 0; x < pw; ++x, ++i) { + if (!((((unsigned)xm->data[di + x / 8]) >> (x % 8)) & 0x1)) + (*data)[i] &= ~(0xff << RrDefaultAlphaOffset); + } + di += xm->bytes_per_line; + } + } + + *w = pw; + *h = ph; + + XDestroyImage(xi); + if (mask) + XDestroyImage(xm); + + return TRUE; +} diff --git a/obrender/render.h b/obrender/render.h new file mode 100644 index 00000000..7bea1b54 --- /dev/null +++ b/obrender/render.h @@ -0,0 +1,350 @@ +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + render.h for the Openbox window manager + Copyright (c) 2006 Mikael Magnusson + Copyright (c) 2003-2007 Dana Jansens + Copyright (c) 2003 Derek Foreman + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + See the COPYING file for a copy of the GNU General Public License. +*/ + +#ifndef __render_h +#define __render_h + +#include /* some platforms dont include this as needed for Xft */ +#include +#include + +G_BEGIN_DECLS + +#include "obrender/geom.h" +#include "obrender/version.h" + +typedef union _RrTextureData RrTextureData; +typedef struct _RrAppearance RrAppearance; +typedef struct _RrSurface RrSurface; +typedef struct _RrFont RrFont; +typedef struct _RrTexture RrTexture; +typedef struct _RrTextureMask RrTextureMask; +typedef struct _RrTextureRGBA RrTextureRGBA; +typedef struct _RrTextureImage RrTextureImage; +typedef struct _RrTextureText RrTextureText; +typedef struct _RrTextureLineArt RrTextureLineArt; +typedef struct _RrPixmapMask RrPixmapMask; +typedef struct _RrInstance RrInstance; +typedef struct _RrColor RrColor; +typedef struct _RrImage RrImage; +typedef struct _RrImagePic RrImagePic; +typedef struct _RrImageCache RrImageCache; + +typedef guint32 RrPixel32; +typedef guint16 RrPixel16; +typedef guchar RrPixel8; + +typedef enum { + RR_RELIEF_FLAT, + RR_RELIEF_RAISED, + RR_RELIEF_SUNKEN +} RrReliefType; + +typedef enum { + RR_BEVEL_1, + RR_BEVEL_2 +} RrBevelType; + +typedef enum { + RR_SURFACE_NONE, + RR_SURFACE_PARENTREL, + RR_SURFACE_SOLID, + RR_SURFACE_SPLIT_VERTICAL, + RR_SURFACE_HORIZONTAL, + RR_SURFACE_VERTICAL, + RR_SURFACE_DIAGONAL, + RR_SURFACE_CROSS_DIAGONAL, + RR_SURFACE_PYRAMID, + RR_SURFACE_MIRROR_HORIZONTAL +} RrSurfaceColorType; + +typedef enum { + RR_TEXTURE_NONE, + RR_TEXTURE_MASK, + RR_TEXTURE_TEXT, + RR_TEXTURE_LINE_ART, + RR_TEXTURE_RGBA, + RR_TEXTURE_IMAGE +} RrTextureType; + +typedef enum { + RR_JUSTIFY_LEFT, + RR_JUSTIFY_CENTER, + RR_JUSTIFY_RIGHT +} RrJustify; + +/* Put middle first so it's the default */ +typedef enum { + RR_ELLIPSIZE_MIDDLE, + RR_ELLIPSIZE_NONE, + RR_ELLIPSIZE_START, + RR_ELLIPSIZE_END +} RrEllipsizeMode; + +typedef enum { + RR_FONTWEIGHT_LIGHT, + RR_FONTWEIGHT_NORMAL, + RR_FONTWEIGHT_SEMIBOLD, + RR_FONTWEIGHT_BOLD, + RR_FONTWEIGHT_ULTRABOLD +} RrFontWeight; + +typedef enum { + RR_FONTSLANT_NORMAL, + RR_FONTSLANT_ITALIC, + RR_FONTSLANT_OBLIQUE +} RrFontSlant; + +struct _RrSurface { + RrSurfaceColorType grad; + RrReliefType relief; + RrBevelType bevel; + RrColor *primary; + RrColor *secondary; + RrColor *border_color; + RrColor *bevel_dark; + RrColor *bevel_light; + RrColor *interlace_color; + gboolean interlaced; + gboolean border; + RrAppearance *parent; + gint parentx; + gint parenty; + RrPixel32 *pixel_data; + gint bevel_dark_adjust; /* 0-255, default is 64 */ + gint bevel_light_adjust; /* 0-255, default is 128 */ + RrColor *split_primary; + RrColor *split_secondary; +}; + +struct _RrTextureText { + RrFont *font; + RrJustify justify; + RrColor *color; + const gchar *string; + gint shadow_offset_x; + gint shadow_offset_y; + RrColor *shadow_color; + gboolean shortcut; /*!< Underline a character */ + guint shortcut_pos; /*!< Position in bytes of the character to underline */ + RrEllipsizeMode ellipsize; + gboolean flow; /* allow multiple lines. must set maxwidth below */ + gint maxwidth; + guchar shadow_alpha; /* at the bottom to improve alignment */ +}; + +struct _RrPixmapMask { + const RrInstance *inst; + Pixmap mask; + gint width; + gint height; + gchar *data; +}; + +struct _RrTextureMask { + RrColor *color; + RrPixmapMask *mask; +}; + +struct _RrTextureRGBA { + gint width; + gint height; + gint alpha; + RrPixel32 *data; + /* size and position to draw at (if these are zero, then it will be + drawn to fill the entire texture */ + gint tx; + gint ty; + gint twidth; + gint theight; +}; + +struct _RrTextureImage { + RrImage *image; + gint alpha; + /* size and position to draw at (if these are zero, then it will be + drawn to fill the entire texture */ + gint tx; + gint ty; + gint twidth; + gint theight; +}; + +struct _RrTextureLineArt { + RrColor *color; + gint x1; + gint y1; + gint x2; + gint y2; +}; + +union _RrTextureData { + RrTextureRGBA rgba; + RrTextureImage image; + RrTextureText text; + RrTextureMask mask; + RrTextureLineArt lineart; +}; + +struct _RrTexture { + /* If changing the type of a texture, you should DEFINITELY call + RrAppearanceClearTextures() first! */ + RrTextureType type; + RrTextureData data; +}; + +struct _RrAppearance { + const RrInstance *inst; + + RrSurface surface; + gint textures; + RrTexture *texture; + Pixmap pixmap; + XftDraw *xftdraw; + + /* cached for internal use */ + gint w, h; +}; + +/*! Holds a RGBA image picture */ +struct _RrImagePic { + gint width, height; + RrPixel32 *data; + /* The sum of all the pixels. This is used to compare pictures if their + hashes match. */ + gint sum; +}; + +/*! An RrImage is a sort of meta-image. It can contain multiple versions of + an image at different sizes, which may or may not be completely different + pictures */ +struct _RrImage { + gint ref; + RrImageCache *cache; + + /*! An array of "originals", that is of RrPictures that have been added + to the image in various sizes, and that have not been resized. These + are explicitly added to the RrImage. */ + RrImagePic **original; + gint n_original; + /*! An array of "resized" pictures. When an "original" RrPicture + needs to be resized for drawing, it is saved in here so that it doesn't + need to be resized again. These are automatically added to the + RrImage. */ + RrImagePic **resized; + gint n_resized; +}; + +/* these are the same on all endian machines because it seems to be dependant + on the endianness of the gfx card, not the cpu. */ +#define RrDefaultAlphaOffset 24 +#define RrDefaultRedOffset 16 +#define RrDefaultGreenOffset 8 +#define RrDefaultBlueOffset 0 + +#define RrDefaultFontFamily "arial,sans" +#define RrDefaultFontSize 8 +#define RrDefaultFontWeight RR_FONTWEIGHT_NORMAL +#define RrDefaultFontSlant RR_FONTSLANT_NORMAL + +RrInstance* RrInstanceNew (Display *display, gint screen); +void RrInstanceFree (RrInstance *inst); + +Display* RrDisplay (const RrInstance *inst); +gint RrScreen (const RrInstance *inst); +Window RrRootWindow (const RrInstance *inst); +Visual* RrVisual (const RrInstance *inst); +gint RrDepth (const RrInstance *inst); +Colormap RrColormap (const RrInstance *inst); +gint RrRedOffset (const RrInstance *inst); +gint RrGreenOffset (const RrInstance *inst); +gint RrBlueOffset (const RrInstance *inst); +gint RrRedShift (const RrInstance *inst); +gint RrGreenShift (const RrInstance *inst); +gint RrBlueShift (const RrInstance *inst); +gint RrRedMask (const RrInstance *inst); +gint RrGreenMask (const RrInstance *inst); +gint RrBlueMask (const RrInstance *inst); + +RrColor *RrColorNew (const RrInstance *inst, gint r, gint g, gint b); +RrColor *RrColorParse (const RrInstance *inst, gchar *colorname); +void RrColorFree (RrColor *in); + +gint RrColorRed (const RrColor *c); +gint RrColorGreen (const RrColor *c); +gint RrColorBlue (const RrColor *c); +gulong RrColorPixel (const RrColor *c); +GC RrColorGC (RrColor *c); + +RrAppearance *RrAppearanceNew (const RrInstance *inst, gint numtex); +RrAppearance *RrAppearanceCopy (RrAppearance *a); +void RrAppearanceFree (RrAppearance *a); +void RrAppearanceRemoveTextures(RrAppearance *a); +void RrAppearanceAddTextures(RrAppearance *a, gint numtex); +/*! Always call this when changing the type of a texture in an appearance */ +void RrAppearanceClearTextures(RrAppearance *a); + +RrFont *RrFontOpen (const RrInstance *inst, const gchar *name, + gint size, RrFontWeight weight, RrFontSlant slant); +RrFont *RrFontOpenDefault (const RrInstance *inst); +void RrFontClose (RrFont *f); +RrSize *RrFontMeasureString (const RrFont *f, const gchar *str, + gint shadow_offset_x, gint shadow_offset_y, + gboolean flow, gint maxwidth); +gint RrFontHeight (const RrFont *f, gint shadow_offset_y); +gint RrFontMaxCharWidth (const RrFont *f); + +/* Paint into the appearance. The old pixmap is returned (if there was one). It + is the responsibility of the caller to call XFreePixmap on the return when + it is non-null. */ +Pixmap RrPaintPixmap (RrAppearance *a, gint w, gint h); +void RrPaint (RrAppearance *a, Window win, gint w, gint h); +void RrMinSize (RrAppearance *a, gint *w, gint *h); +gint RrMinWidth (RrAppearance *a); +/* For text textures, if flow is TRUE, then the string must be set before + calling this, otherwise it doesn't need to be */ +gint RrMinHeight (RrAppearance *a); +void RrMargins (RrAppearance *a, gint *l, gint *t, gint *r, gint *b); + +gboolean RrPixmapToRGBA(const RrInstance *inst, + Pixmap pmap, Pixmap mask, + gint *w, gint *h, RrPixel32 **data); + +/*! Create a new image cache for RrImages. + @param max_resized_saved The number of resized copies of an image to save +*/ +RrImageCache* RrImageCacheNew(gint max_resized_saved); +void RrImageCacheRef(RrImageCache *self); +void RrImageCacheUnref(RrImageCache *self); + +/*! Finds an image in the cache, if it is already in there */ +RrImage* RrImageCacheFind(RrImageCache *self, + RrPixel32 *data, gint w, gint h); + +RrImage* RrImageNew(RrImageCache *cache); +void RrImageRef(RrImage *im); +void RrImageUnref(RrImage *im); + +void RrImageAddPicture(RrImage *im, RrPixel32 *data, gint w, gint h); +void RrImageRemovePicture(RrImage *im, gint w, gint h); + +G_END_DECLS + +#endif /*__render_h*/ diff --git a/obrender/test.c b/obrender/test.c new file mode 100644 index 00000000..55ab621e --- /dev/null +++ b/obrender/test.c @@ -0,0 +1,115 @@ +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + test.c for the Openbox window manager + Copyright (c) 2006 Mikael Magnusson + Copyright (c) 2003-2007 Dana Jansens + Copyright (c) 2003 Derek Foreman + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + See the COPYING file for a copy of the GNU General Public License. +*/ + +#include +#include +#include +#include +#include +#include +#include "render.h" +#include + +static gint x_error_handler(Display * disp, XErrorEvent * error) +{ + gchar buf[1024]; + XGetErrorText(disp, error->error_code, buf, 1024); + printf("%s\n", buf); + return 0; +} + +Display *ob_display; +gint ob_screen; +Window ob_root; + +gint main() +{ + Window win; + RrInstance *inst; + RrAppearance *look; + int done; + + Window root; + XEvent report; + gint h = 500, w = 500; + + ob_display = XOpenDisplay(NULL); + XSetErrorHandler(x_error_handler); + ob_screen = DefaultScreen(ob_display); + ob_root = RootWindow(ob_display, ob_screen); + win = + XCreateWindow(ob_display, RootWindow(ob_display, 0), + 10, 10, w, h, 10, + CopyFromParent, /* depth */ + CopyFromParent, /* class */ + CopyFromParent, /* visual */ + 0, /* valuemask */ + 0); /* attributes */ + XMapWindow(ob_display, win); + XSelectInput(ob_display, win, ExposureMask | StructureNotifyMask); + root = RootWindow (ob_display, DefaultScreen (ob_display)); + inst = RrInstanceNew(ob_display, ob_screen); + + look = RrAppearanceNew(inst, 0); + look->surface.grad = RR_SURFACE_MIRROR_HORIZONTAL; + look->surface.secondary = RrColorParse(inst, "Yellow"); + look->surface.split_secondary = RrColorParse(inst, "Red"); + look->surface.split_primary = RrColorParse(inst, "Green"); + look->surface.primary = RrColorParse(inst, "Blue"); + look->surface.interlaced = FALSE; + if (ob_display == NULL) { + fprintf(stderr, "couldn't connect to X server :0\n"); + return 0; + } + +#if BIGTEST + int i; + look->surface.pixel_data = g_new(RrPixel32, w*h); + for (i = 0; i < 10000; ++i) { + printf("\r%d", i); + fflush(stdout); + RrRender(look, w, h); + } + exit (0); +#endif + + RrPaint(look, win, w, h); + done = 0; + while (!done) { + XNextEvent(ob_display, &report); + switch (report.type) { + case Expose: + break; + case ConfigureNotify: + RrPaint(look, win, + report.xconfigure.width, + report.xconfigure.height); + break; + case UnmapNotify: + done = 1; + break; + } + } + + RrAppearanceFree (look); + RrInstanceFree (inst); + + return 1; +} diff --git a/obrender/theme.c b/obrender/theme.c new file mode 100644 index 00000000..6c136bf5 --- /dev/null +++ b/obrender/theme.c @@ -0,0 +1,2007 @@ +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + theme.c for the Openbox window manager + Copyright (c) 2006 Mikael Magnusson + Copyright (c) 2003-2007 Dana Jansens + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + See the COPYING file for a copy of the GNU General Public License. +*/ + +#include "render.h" +#include "color.h" +#include "font.h" +#include "mask.h" +#include "theme.h" +#include "icon.h" +#include "obt/paths.h" + +#include +#include +#include +#include +#include + +static XrmDatabase loaddb(const gchar *name, gchar **path); +static gboolean read_int(XrmDatabase db, const gchar *rname, gint *value); +static gboolean read_string(XrmDatabase db, const gchar *rname, gchar **value); +static gboolean read_color(XrmDatabase db, const RrInstance *inst, + const gchar *rname, RrColor **value); +static gboolean read_mask(const RrInstance *inst, const gchar *path, + RrTheme *theme, const gchar *maskname, + RrPixmapMask **value); +static gboolean read_appearance(XrmDatabase db, const RrInstance *inst, + const gchar *rname, RrAppearance *value, + gboolean allow_trans); +static int parse_inline_number(const char *p); +static RrPixel32* read_c_image(gint width, gint height, const guint8 *data); +static void set_default_appearance(RrAppearance *a); + +static RrFont *get_font(RrFont *target, RrFont **default_font, + const RrInstance *inst) +{ + if (target) { + RrFontRef(target); + return target; + } else { + /* Only load the default font once */ + if (*default_font) { + RrFontRef(*default_font); + } else { + *default_font = RrFontOpenDefault(inst); + } + return *default_font; + } +} + +RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name, + gboolean allow_fallback, + RrFont *active_window_font, RrFont *inactive_window_font, + RrFont *menu_title_font, RrFont *menu_item_font, + RrFont *active_osd_font, RrFont *inactive_osd_font) +{ + XrmDatabase db = NULL; + RrJustify winjust, mtitlejust; + gchar *str; + RrTheme *theme; + RrFont *default_font = NULL; + gchar *path; + gboolean userdef; + + if (name) { + db = loaddb(name, &path); + if (db == NULL) { + g_message("Unable to load the theme '%s'", name); + if (allow_fallback) + g_message("Falling back to the default theme '%s'", + DEFAULT_THEME); + /* fallback to the default theme */ + name = NULL; + } + } + if (name == NULL) { + if (allow_fallback) { + db = loaddb(DEFAULT_THEME, &path); + if (db == NULL) { + g_message("Unable to load the theme '%s'", DEFAULT_THEME); + return NULL; + } + } else + return NULL; + } + + theme = g_new0(RrTheme, 1); + + theme->inst = inst; + theme->name = g_strdup(name ? name : DEFAULT_THEME); + + theme->a_disabled_focused_max = RrAppearanceNew(inst, 1); + theme->a_disabled_unfocused_max = RrAppearanceNew(inst, 1); + theme->a_hover_focused_max = RrAppearanceNew(inst, 1); + theme->a_hover_unfocused_max = RrAppearanceNew(inst, 1); + theme->a_toggled_focused_unpressed_max = RrAppearanceNew(inst, 1); + theme->a_toggled_unfocused_unpressed_max = RrAppearanceNew(inst, 1); + theme->a_toggled_hover_focused_max = RrAppearanceNew(inst, 1); + theme->a_toggled_hover_unfocused_max = RrAppearanceNew(inst, 1); + theme->a_toggled_focused_pressed_max = RrAppearanceNew(inst, 1); + theme->a_toggled_unfocused_pressed_max = RrAppearanceNew(inst, 1); + theme->a_focused_unpressed_max = RrAppearanceNew(inst, 1); + theme->a_focused_pressed_max = RrAppearanceNew(inst, 1); + theme->a_unfocused_unpressed_max = RrAppearanceNew(inst, 1); + theme->a_unfocused_pressed_max = RrAppearanceNew(inst, 1); + theme->a_focused_grip = RrAppearanceNew(inst, 0); + theme->a_unfocused_grip = RrAppearanceNew(inst, 0); + theme->a_focused_title = RrAppearanceNew(inst, 0); + theme->a_unfocused_title = RrAppearanceNew(inst, 0); + theme->a_focused_label = RrAppearanceNew(inst, 1); + theme->a_unfocused_label = RrAppearanceNew(inst, 1); + theme->a_icon = RrAppearanceNew(inst, 1); + theme->a_focused_handle = RrAppearanceNew(inst, 0); + theme->a_unfocused_handle = RrAppearanceNew(inst, 0); + theme->a_menu = RrAppearanceNew(inst, 0); + theme->a_menu_title = RrAppearanceNew(inst, 0); + theme->a_menu_text_title = RrAppearanceNew(inst, 1); + theme->a_menu_normal = RrAppearanceNew(inst, 0); + theme->a_menu_selected = RrAppearanceNew(inst, 0); + theme->a_menu_disabled = RrAppearanceNew(inst, 0); + /* a_menu_disabled_selected is copied from a_menu_selected */ + theme->a_menu_text_normal = RrAppearanceNew(inst, 1); + theme->a_menu_text_selected = RrAppearanceNew(inst, 1); + theme->a_menu_text_disabled = RrAppearanceNew(inst, 1); + theme->a_menu_text_disabled_selected = RrAppearanceNew(inst, 1); + theme->a_menu_bullet_normal = RrAppearanceNew(inst, 1); + theme->a_menu_bullet_selected = RrAppearanceNew(inst, 1); + theme->a_clear = RrAppearanceNew(inst, 0); + theme->a_clear_tex = RrAppearanceNew(inst, 1); + theme->osd_bg = RrAppearanceNew(inst, 0); + theme->osd_hilite_label = RrAppearanceNew(inst, 1); + theme->osd_hilite_bg = RrAppearanceNew(inst, 0); + theme->osd_unhilite_label = RrAppearanceNew(inst, 1); + theme->osd_unhilite_bg = RrAppearanceNew(inst, 0); + + /* load the font stuff */ + theme->win_font_focused = get_font(active_window_font, + &default_font, inst); + theme->win_font_unfocused = get_font(inactive_window_font, + &default_font, inst); + + winjust = RR_JUSTIFY_LEFT; + if (read_string(db, "window.label.text.justify", &str)) { + if (!g_ascii_strcasecmp(str, "right")) + winjust = RR_JUSTIFY_RIGHT; + else if (!g_ascii_strcasecmp(str, "center")) + winjust = RR_JUSTIFY_CENTER; + } + + theme->menu_title_font = get_font(menu_title_font, &default_font, inst); + + mtitlejust = RR_JUSTIFY_LEFT; + if (read_string(db, "menu.title.text.justify", &str)) { + if (!g_ascii_strcasecmp(str, "right")) + mtitlejust = RR_JUSTIFY_RIGHT; + else if (!g_ascii_strcasecmp(str, "center")) + mtitlejust = RR_JUSTIFY_CENTER; + } + + theme->menu_font = get_font(menu_item_font, &default_font, inst); + + theme->osd_font_hilite = get_font(active_osd_font, &default_font, inst); + theme->osd_font_unhilite = get_font(inactive_osd_font, &default_font,inst); + + /* load direct dimensions */ + if ((!read_int(db, "menu.overlap.x", &theme->menu_overlap_x) && + !read_int(db, "menu.overlap", &theme->menu_overlap_x)) || + theme->menu_overlap_x < -100 || theme->menu_overlap_x > 100) + theme->menu_overlap_x = 0; + if ((!read_int(db, "menu.overlap.y", &theme->menu_overlap_y) && + !read_int(db, "menu.overlap", &theme->menu_overlap_y)) || + theme->menu_overlap_y < -100 || theme->menu_overlap_y > 100) + theme->menu_overlap_y = 0; + if (!read_int(db, "window.handle.width", &theme->handle_height) || + theme->handle_height < 0 || theme->handle_height > 100) + theme->handle_height = 6; + if (!read_int(db, "padding.width", &theme->paddingx) || + theme->paddingx < 0 || theme->paddingx > 100) + theme->paddingx = 3; + if (!read_int(db, "padding.height", &theme->paddingy) || + theme->paddingy < 0 || theme->paddingy > 100) + theme->paddingy = theme->paddingx; + if (!read_int(db, "border.width", &theme->fbwidth) || + theme->fbwidth < 0 || theme->fbwidth > 100) + theme->fbwidth = 1; + /* menu border width inherits from the frame border width */ + if (!read_int(db, "menu.border.width", &theme->mbwidth) || + theme->mbwidth < 0 || theme->mbwidth > 100) + theme->mbwidth = theme->fbwidth; + /* osd border width inherits from the frame border width */ + if (!read_int(db, "osd.border.width", &theme->obwidth) || + theme->obwidth < 0 || theme->obwidth > 100) + theme->obwidth = theme->fbwidth; + if (!read_int(db, "window.client.padding.width", &theme->cbwidthx) || + theme->cbwidthx < 0 || theme->cbwidthx > 100) + theme->cbwidthx = theme->paddingx; + if (!read_int(db, "window.client.padding.height", &theme->cbwidthy) || + theme->cbwidthy < 0 || theme->cbwidthy > 100) + theme->cbwidthy = theme->cbwidthx; + if (!read_int(db, "menu.separator.width", &theme->menu_sep_width) || + theme->menu_sep_width < 1 || theme->menu_sep_width > 100) + theme->menu_sep_width = 1; + if (!read_int(db, "menu.separator.padding.width", + &theme->menu_sep_paddingx) || + theme->menu_sep_paddingx < 0 || theme->menu_sep_paddingx > 100) + theme->menu_sep_paddingx = 6; + if (!read_int(db, "menu.separator.padding.height", + &theme->menu_sep_paddingy) || + theme->menu_sep_paddingy < 0 || theme->menu_sep_paddingy > 100) + theme->menu_sep_paddingy = 3; + + /* load colors */ + if (!read_color(db, inst, + "window.active.border.color", + &theme->frame_focused_border_color) && + !read_color(db, inst, + "border.color", + &theme->frame_focused_border_color)) + theme->frame_focused_border_color = RrColorNew(inst, 0, 0, 0); + /* title separator focused color inherits from focused border color */ + if (!read_color(db, inst, + "window.active.title.separator.color", + &theme->title_separator_focused_color)) + theme->title_separator_focused_color = + RrColorNew(inst, + theme->frame_focused_border_color->r, + theme->frame_focused_border_color->g, + theme->frame_focused_border_color->b); + /* unfocused border color inherits from frame focused border color */ + if (!read_color(db, inst, + "window.inactive.border.color", + &theme->frame_unfocused_border_color)) + theme->frame_unfocused_border_color = + RrColorNew(inst, theme->frame_focused_border_color->r, + theme->frame_focused_border_color->g, + theme->frame_focused_border_color->b); + /* title separator unfocused color inherits from unfocused border color */ + if (!read_color(db, inst, + "window.inactive.title.separator.color", + &theme->title_separator_unfocused_color)) + theme->title_separator_unfocused_color = + RrColorNew(inst, + theme->frame_unfocused_border_color->r, + theme->frame_unfocused_border_color->g, + theme->frame_unfocused_border_color->b); + + /* menu border color inherits from frame focused border color */ + if (!read_color(db, inst, "menu.border.color", &theme->menu_border_color)) + theme->menu_border_color = + RrColorNew(inst, + theme->frame_focused_border_color->r, + theme->frame_focused_border_color->g, + theme->frame_focused_border_color->b); + /* osd border color inherits from frame focused border color */ + if (!read_color(db, inst, "osd.border.color", &theme->osd_border_color)) + theme->osd_border_color = + RrColorNew(inst, + theme->frame_focused_border_color->r, + theme->frame_focused_border_color->g, + theme->frame_focused_border_color->b); + if (!read_color(db, inst, + "window.active.client.color", + &theme->cb_focused_color)) + theme->cb_focused_color = RrColorNew(inst, 0xff, 0xff, 0xff); + if (!read_color(db, inst, + "window.inactive.client.color", + &theme->cb_unfocused_color)) + theme->cb_unfocused_color = RrColorNew(inst, 0xff, 0xff, 0xff); + if (!read_color(db, inst, + "window.active.label.text.color", + &theme->title_focused_color)) + theme->title_focused_color = RrColorNew(inst, 0x0, 0x0, 0x0); + if (!read_color(db, inst, "osd.active.label.text.color", + &theme->osd_text_active_color) && + !read_color(db, inst, "osd.label.text.color", + &theme->osd_text_active_color)) + theme->osd_text_active_color = + RrColorNew(inst, + theme->title_focused_color->r, + theme->title_focused_color->g, + theme->title_focused_color->b); + if (!read_color(db, inst, + "window.inactive.label.text.color", + &theme->title_unfocused_color)) + theme->title_unfocused_color = RrColorNew(inst, 0xff, 0xff, 0xff); + if (!read_color(db, inst, "osd.inactive.label.text.color", + &theme->osd_text_inactive_color)) + theme->osd_text_inactive_color = + RrColorNew(inst, + theme->title_unfocused_color->r, + theme->title_unfocused_color->g, + theme->title_unfocused_color->b); + if (!read_color(db, inst, + "window.active.button.unpressed.image.color", + &theme->titlebut_focused_unpressed_color)) + theme->titlebut_focused_unpressed_color = RrColorNew(inst, 0, 0, 0); + if (!read_color(db, inst, + "window.inactive.button.unpressed.image.color", + &theme->titlebut_unfocused_unpressed_color)) + theme->titlebut_unfocused_unpressed_color = + RrColorNew(inst, 0xff, 0xff, 0xff); + if (!read_color(db, inst, + "window.active.button.pressed.image.color", + &theme->titlebut_focused_pressed_color)) + theme->titlebut_focused_pressed_color = + RrColorNew(inst, + theme->titlebut_focused_unpressed_color->r, + theme->titlebut_focused_unpressed_color->g, + theme->titlebut_focused_unpressed_color->b); + if (!read_color(db, inst, + "window.inactive.button.pressed.image.color", + &theme->titlebut_unfocused_pressed_color)) + theme->titlebut_unfocused_pressed_color = + RrColorNew(inst, + theme->titlebut_unfocused_unpressed_color->r, + theme->titlebut_unfocused_unpressed_color->g, + theme->titlebut_unfocused_unpressed_color->b); + if (!read_color(db, inst, + "window.active.button.disabled.image.color", + &theme->titlebut_disabled_focused_color)) + theme->titlebut_disabled_focused_color = + RrColorNew(inst, 0xff, 0xff, 0xff); + if (!read_color(db, inst, + "window.inactive.button.disabled.image.color", + &theme->titlebut_disabled_unfocused_color)) + theme->titlebut_disabled_unfocused_color = RrColorNew(inst, 0, 0, 0); + if (!read_color(db, inst, + "window.active.button.hover.image.color", + &theme->titlebut_hover_focused_color)) + theme->titlebut_hover_focused_color = + RrColorNew(inst, + theme->titlebut_focused_unpressed_color->r, + theme->titlebut_focused_unpressed_color->g, + theme->titlebut_focused_unpressed_color->b); + if (!read_color(db, inst, + "window.inactive.button.hover.image.color", + &theme->titlebut_hover_unfocused_color)) + theme->titlebut_hover_unfocused_color = + RrColorNew(inst, + theme->titlebut_unfocused_unpressed_color->r, + theme->titlebut_unfocused_unpressed_color->g, + theme->titlebut_unfocused_unpressed_color->b); + if (!read_color(db, inst, + "window.active.button.toggled.unpressed.image.color", + &theme->titlebut_toggled_focused_unpressed_color) && + !read_color(db, inst, + "window.active.button.toggled.image.color", + &theme->titlebut_toggled_focused_unpressed_color)) + theme->titlebut_toggled_focused_unpressed_color = + RrColorNew(inst, + theme->titlebut_focused_pressed_color->r, + theme->titlebut_focused_pressed_color->g, + theme->titlebut_focused_pressed_color->b); + if (!read_color(db, inst, + "window.inactive.button.toggled.unpressed.image.color", + &theme->titlebut_toggled_unfocused_unpressed_color) && + !read_color(db, inst, + "window.inactive.button.toggled.image.color", + &theme->titlebut_toggled_unfocused_unpressed_color)) + theme->titlebut_toggled_unfocused_unpressed_color = + RrColorNew(inst, + theme->titlebut_unfocused_pressed_color->r, + theme->titlebut_unfocused_pressed_color->g, + theme->titlebut_unfocused_pressed_color->b); + if (!read_color(db, inst, + "window.active.button.toggled.hover.image.color", + &theme->titlebut_toggled_hover_focused_color)) + theme->titlebut_toggled_hover_focused_color = + RrColorNew(inst, + theme->titlebut_toggled_focused_unpressed_color->r, + theme->titlebut_toggled_focused_unpressed_color->g, + theme->titlebut_toggled_focused_unpressed_color->b); + if (!read_color(db, inst, + "window.inactive.button.toggled.hover.image.color", + &theme->titlebut_toggled_hover_unfocused_color)) + theme->titlebut_toggled_hover_unfocused_color = + RrColorNew(inst, + theme->titlebut_toggled_unfocused_unpressed_color->r, + theme->titlebut_toggled_unfocused_unpressed_color->g, + theme->titlebut_toggled_unfocused_unpressed_color->b); + if (!read_color(db, inst, + "window.active.button.toggled.pressed.image.color", + &theme->titlebut_toggled_focused_pressed_color)) + theme->titlebut_toggled_focused_pressed_color = + RrColorNew(inst, + theme->titlebut_focused_pressed_color->r, + theme->titlebut_focused_pressed_color->g, + theme->titlebut_focused_pressed_color->b); + if (!read_color(db, inst, + "window.inactive.button.toggled.pressed.image.color", + &theme->titlebut_toggled_unfocused_pressed_color)) + theme->titlebut_toggled_unfocused_pressed_color = + RrColorNew(inst, + theme->titlebut_unfocused_pressed_color->r, + theme->titlebut_unfocused_pressed_color->g, + theme->titlebut_unfocused_pressed_color->b); + if (!read_color(db, inst, + "menu.title.text.color", &theme->menu_title_color)) + theme->menu_title_color = RrColorNew(inst, 0, 0, 0); + if (!read_color(db, inst, + "menu.items.text.color", &theme->menu_color)) + theme->menu_color = RrColorNew(inst, 0xff, 0xff, 0xff); + if (!read_color(db, inst, + "menu.items.disabled.text.color", + &theme->menu_disabled_color)) + theme->menu_disabled_color = RrColorNew(inst, 0, 0, 0); + if (!read_color(db, inst, + "menu.items.active.disabled.text.color", + &theme->menu_disabled_selected_color)) + theme->menu_disabled_selected_color = + RrColorNew(inst, + theme->menu_disabled_color->r, + theme->menu_disabled_color->g, + theme->menu_disabled_color->b); + if (!read_color(db, inst, + "menu.items.active.text.color", + &theme->menu_selected_color)) + theme->menu_selected_color = RrColorNew(inst, 0, 0, 0); + if (!read_color(db, inst, + "menu.separator.color", &theme->menu_sep_color)) + theme->menu_sep_color = RrColorNew(inst, + theme->menu_color->r, + theme->menu_color->g, + theme->menu_color->b); + + /* load the image masks */ + + /* maximize button masks */ + userdef = TRUE; + if (!read_mask(inst, path, theme, "max.xbm", &theme->max_mask)) { + guchar data[] = { 0x3f, 0x3f, 0x21, 0x21, 0x21, 0x3f }; + theme->max_mask = RrPixmapMaskNew(inst, 6, 6, (gchar*)data); + userdef = FALSE; + } + if (!read_mask(inst, path, theme, "max_toggled.xbm", + &theme->max_toggled_mask)) + { + if (userdef) + theme->max_toggled_mask = RrPixmapMaskCopy(theme->max_mask); + else { + guchar data[] = { 0x3e, 0x22, 0x2f, 0x29, 0x39, 0x0f }; + theme->max_toggled_mask = RrPixmapMaskNew(inst, 6, 6,(gchar*)data); + } + } + if (!read_mask(inst, path, theme, "max_pressed.xbm", + &theme->max_pressed_mask)) + theme->max_pressed_mask = RrPixmapMaskCopy(theme->max_mask); + if (!read_mask(inst,path,theme,"max_disabled.xbm", + &theme->max_disabled_mask)) + theme->max_disabled_mask = RrPixmapMaskCopy(theme->max_mask); + if (!read_mask(inst, path, theme, "max_hover.xbm", &theme->max_hover_mask)) + theme->max_hover_mask = RrPixmapMaskCopy(theme->max_mask); + if (!read_mask(inst, path, theme, "max_toggled_pressed.xbm", + &theme->max_toggled_pressed_mask)) + theme->max_toggled_pressed_mask = + RrPixmapMaskCopy(theme->max_toggled_mask); + if (!read_mask(inst, path, theme, "max_toggled_hover.xbm", + &theme->max_toggled_hover_mask)) + theme->max_toggled_hover_mask = + RrPixmapMaskCopy(theme->max_toggled_mask); + + /* iconify button masks */ + if (!read_mask(inst, path, theme, "iconify.xbm", &theme->iconify_mask)) { + guchar data[] = { 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f }; + theme->iconify_mask = RrPixmapMaskNew(inst, 6, 6, (gchar*)data); + } + if (!read_mask(inst, path, theme, "iconify_pressed.xbm", + &theme->iconify_pressed_mask)) + theme->iconify_pressed_mask = RrPixmapMaskCopy(theme->iconify_mask); + if (!read_mask(inst, path, theme, "iconify_disabled.xbm", + &theme->iconify_disabled_mask)) + theme->iconify_disabled_mask = RrPixmapMaskCopy(theme->iconify_mask); + if (!read_mask(inst, path, theme, "iconify_hover.xbm", + &theme->iconify_hover_mask)) + theme->iconify_hover_mask = RrPixmapMaskCopy(theme->iconify_mask); + + /* all desktops button masks */ + userdef = TRUE; + if (!read_mask(inst, path, theme, "desk.xbm", &theme->desk_mask)) { + guchar data[] = { 0x33, 0x33, 0x00, 0x00, 0x33, 0x33 }; + theme->desk_mask = RrPixmapMaskNew(inst, 6, 6, (gchar*)data); + userdef = FALSE; + } + if (!read_mask(inst, path, theme, "desk_toggled.xbm", + &theme->desk_toggled_mask)) { + if (userdef) + theme->desk_toggled_mask = RrPixmapMaskCopy(theme->desk_mask); + else { + guchar data[] = { 0x00, 0x1e, 0x1a, 0x16, 0x1e, 0x00 }; + theme->desk_toggled_mask = + RrPixmapMaskNew(inst, 6, 6, (gchar*)data); + } + } + if (!read_mask(inst, path, theme, "desk_pressed.xbm", + &theme->desk_pressed_mask)) + theme->desk_pressed_mask = RrPixmapMaskCopy(theme->desk_mask); + if (!read_mask(inst, path, theme, "desk_disabled.xbm", + &theme->desk_disabled_mask)) + theme->desk_disabled_mask = RrPixmapMaskCopy(theme->desk_mask); + if (!read_mask(inst, path, theme, "desk_hover.xbm", + &theme->desk_hover_mask)) + theme->desk_hover_mask = RrPixmapMaskCopy(theme->desk_mask); + if (!read_mask(inst, path, theme, "desk_toggled_pressed.xbm", + &theme->desk_toggled_pressed_mask)) + theme->desk_toggled_pressed_mask = + RrPixmapMaskCopy(theme->desk_toggled_mask); + if (!read_mask(inst, path, theme, "desk_toggled_hover.xbm", + &theme->desk_toggled_hover_mask)) + theme->desk_toggled_hover_mask = + RrPixmapMaskCopy(theme->desk_toggled_mask); + + /* shade button masks */ + if (!read_mask(inst, path, theme, "shade.xbm", &theme->shade_mask)) { + guchar data[] = { 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00 }; + theme->shade_mask = RrPixmapMaskNew(inst, 6, 6, (gchar*)data); + } + if (!read_mask(inst, path, theme, "shade_toggled.xbm", + &theme->shade_toggled_mask)) + theme->shade_toggled_mask = RrPixmapMaskCopy(theme->shade_mask); + if (!read_mask(inst, path, theme, "shade_pressed.xbm", + &theme->shade_pressed_mask)) + theme->shade_pressed_mask = RrPixmapMaskCopy(theme->shade_mask); + if (!read_mask(inst, path, theme, "shade_disabled.xbm", + &theme->shade_disabled_mask)) + theme->shade_disabled_mask = RrPixmapMaskCopy(theme->shade_mask); + if (!read_mask(inst, path, theme, "shade_hover.xbm", + &theme->shade_hover_mask)) + theme->shade_hover_mask = RrPixmapMaskCopy(theme->shade_mask); + if (!read_mask(inst, path, theme, "shade_toggled_pressed.xbm", + &theme->shade_toggled_pressed_mask)) + theme->shade_toggled_pressed_mask = + RrPixmapMaskCopy(theme->shade_toggled_mask); + if (!read_mask(inst, path, theme, "shade_toggled_hover.xbm", + &theme->shade_toggled_hover_mask)) + theme->shade_toggled_hover_mask = + RrPixmapMaskCopy(theme->shade_toggled_mask); + + /* close button masks */ + if (!read_mask(inst, path, theme, "close.xbm", &theme->close_mask)) { + guchar data[] = { 0x33, 0x3f, 0x1e, 0x1e, 0x3f, 0x33 }; + theme->close_mask = RrPixmapMaskNew(inst, 6, 6, (gchar*)data); + } + if (!read_mask(inst, path, theme, "close_pressed.xbm", + &theme->close_pressed_mask)) + theme->close_pressed_mask = RrPixmapMaskCopy(theme->close_mask); + if (!read_mask(inst, path, theme, "close_disabled.xbm", + &theme->close_disabled_mask)) + theme->close_disabled_mask = RrPixmapMaskCopy(theme->close_mask); + if (!read_mask(inst, path, theme, "close_hover.xbm", + &theme->close_hover_mask)) + theme->close_hover_mask = RrPixmapMaskCopy(theme->close_mask); + + /* submenu bullet mask */ + if (!read_mask(inst, path, theme, "bullet.xbm", &theme->menu_bullet_mask)) + { + guchar data[] = { 0x01, 0x03, 0x07, 0x0f, 0x07, 0x03, 0x01 }; + theme->menu_bullet_mask = RrPixmapMaskNew(inst, 4, 7, (gchar*)data); + } + + /* up and down arrows */ + { + guchar data[] = { 0xfe, 0x00, 0x7c, 0x00, 0x38, 0x00, 0x10, 0x00 }; + theme->down_arrow_mask = RrPixmapMaskNew(inst, 9, 4, (gchar*)data); + } + { + guchar data[] = { 0x10, 0x00, 0x38, 0x00, 0x7c, 0x00, 0xfe, 0x00 }; + theme->up_arrow_mask = RrPixmapMaskNew(inst, 9, 4, (gchar*)data); + } + + /* setup the default window icon */ + theme->def_win_icon = read_c_image(OB_DEFAULT_ICON_WIDTH, + OB_DEFAULT_ICON_HEIGHT, + OB_DEFAULT_ICON_pixel_data); + theme->def_win_icon_w = OB_DEFAULT_ICON_WIDTH; + theme->def_win_icon_h = OB_DEFAULT_ICON_HEIGHT; + + /* read the decoration textures */ + if (!read_appearance(db, inst, + "window.active.title.bg", theme->a_focused_title, + FALSE)) + set_default_appearance(theme->a_focused_title); + if (!read_appearance(db, inst, + "window.inactive.title.bg", theme->a_unfocused_title, + FALSE)) + set_default_appearance(theme->a_unfocused_title); + if (!read_appearance(db, inst, + "window.active.label.bg", theme->a_focused_label, + TRUE)) + set_default_appearance(theme->a_focused_label); + if (!read_appearance(db, inst, + "window.inactive.label.bg", theme->a_unfocused_label, + TRUE)) + set_default_appearance(theme->a_unfocused_label); + if (!read_appearance(db, inst, + "window.active.handle.bg", theme->a_focused_handle, + FALSE)) + set_default_appearance(theme->a_focused_handle); + if (!read_appearance(db, inst, + "window.inactive.handle.bg",theme->a_unfocused_handle, + FALSE)) + set_default_appearance(theme->a_unfocused_handle); + if (!read_appearance(db, inst, + "window.active.grip.bg", theme->a_focused_grip, + TRUE)) + set_default_appearance(theme->a_focused_grip); + if (!read_appearance(db, inst, + "window.inactive.grip.bg", theme->a_unfocused_grip, + TRUE)) + set_default_appearance(theme->a_unfocused_grip); + if (!read_appearance(db, inst, + "menu.items.bg", theme->a_menu, + FALSE)) + set_default_appearance(theme->a_menu); + if (!read_appearance(db, inst, + "menu.title.bg", theme->a_menu_title, + TRUE)) + set_default_appearance(theme->a_menu_title); + if (!read_appearance(db, inst, + "menu.items.active.bg", theme->a_menu_selected, + TRUE)) + set_default_appearance(theme->a_menu_selected); + theme->a_menu_disabled_selected = + RrAppearanceCopy(theme->a_menu_selected); + + /* read appearances for non-decorations (on-screen-display) */ + if (!read_appearance(db, inst, "osd.bg", theme->osd_bg, FALSE)) { + RrAppearanceFree(theme->osd_bg); + theme->osd_bg = RrAppearanceCopy(theme->a_focused_title); + } + if (!read_appearance(db, inst, "osd.active.label.bg", + theme->osd_hilite_label, TRUE) && + !read_appearance(db, inst, "osd.label.bg", + theme->osd_hilite_label, TRUE)) { + RrAppearanceFree(theme->osd_hilite_label); + theme->osd_hilite_label = RrAppearanceCopy(theme->a_focused_label); + } + if (!read_appearance(db, inst, "osd.inactive.label.bg", + theme->osd_unhilite_label, TRUE)) { + RrAppearanceFree(theme->osd_unhilite_label); + theme->osd_unhilite_label = RrAppearanceCopy(theme->a_unfocused_label); + } + /* osd_hilite_fg can't be parentrel */ + if (!read_appearance(db, inst, "osd.hilight.bg", + theme->osd_hilite_bg, FALSE)) { + RrAppearanceFree(theme->osd_hilite_bg); + if (theme->a_focused_label->surface.grad != RR_SURFACE_PARENTREL) + theme->osd_hilite_bg = RrAppearanceCopy(theme->a_focused_label); + else + theme->osd_hilite_bg = RrAppearanceCopy(theme->a_focused_title); + } + /* osd_unhilite_fg can't be parentrel either */ + if (!read_appearance(db, inst, "osd.unhilight.bg", + theme->osd_unhilite_bg, FALSE)) { + RrAppearanceFree(theme->osd_unhilite_bg); + if (theme->a_unfocused_label->surface.grad != RR_SURFACE_PARENTREL) + theme->osd_unhilite_bg=RrAppearanceCopy(theme->a_unfocused_label); + else + theme->osd_unhilite_bg=RrAppearanceCopy(theme->a_unfocused_title); + } + + /* read buttons textures */ + if (!read_appearance(db, inst, + "window.active.button.disabled.bg", + theme->a_disabled_focused_max, + TRUE)) + set_default_appearance(theme->a_disabled_focused_max); + if (!read_appearance(db, inst, + "window.inactive.button.disabled.bg", + theme->a_disabled_unfocused_max, + TRUE)) + set_default_appearance(theme->a_disabled_unfocused_max); + if (!read_appearance(db, inst, + "window.active.button.pressed.bg", + theme->a_focused_pressed_max, + TRUE)) + set_default_appearance(theme->a_focused_pressed_max); + if (!read_appearance(db, inst, + "window.inactive.button.pressed.bg", + theme->a_unfocused_pressed_max, + TRUE)) + set_default_appearance(theme->a_unfocused_pressed_max); + if (!read_appearance(db, inst, + "window.active.button.toggled.unpressed.bg", + theme->a_toggled_focused_unpressed_max, + TRUE) && + !read_appearance(db, inst, + "window.active.button.toggled.bg", + theme->a_toggled_focused_unpressed_max, + TRUE)) + { + RrAppearanceFree(theme->a_toggled_focused_unpressed_max); + theme->a_toggled_focused_unpressed_max = + RrAppearanceCopy(theme->a_focused_pressed_max); + } + if (!read_appearance(db, inst, + "window.inactive.button.toggled.unpressed.bg", + theme->a_toggled_unfocused_unpressed_max, + TRUE) && + !read_appearance(db, inst, + "window.inactive.button.toggled.bg", + theme->a_toggled_unfocused_unpressed_max, + TRUE)) + { + RrAppearanceFree(theme->a_toggled_unfocused_unpressed_max); + theme->a_toggled_unfocused_unpressed_max = + RrAppearanceCopy(theme->a_unfocused_pressed_max); + } + if (!read_appearance(db, inst, + "window.active.button.toggled.hover.bg", + theme->a_toggled_hover_focused_max, + TRUE)) + { + RrAppearanceFree(theme->a_toggled_hover_focused_max); + theme->a_toggled_hover_focused_max = + RrAppearanceCopy(theme->a_toggled_focused_unpressed_max); + } + if (!read_appearance(db, inst, + "window.inactive.button.toggled.hover.bg", + theme->a_toggled_hover_unfocused_max, + TRUE)) + { + RrAppearanceFree(theme->a_toggled_hover_unfocused_max); + theme->a_toggled_hover_unfocused_max = + RrAppearanceCopy(theme->a_toggled_unfocused_unpressed_max); + } + if (!read_appearance(db, inst, + "window.active.button.toggled.pressed.bg", + theme->a_toggled_focused_pressed_max, + TRUE)) + { + RrAppearanceFree(theme->a_toggled_focused_pressed_max); + theme->a_toggled_focused_pressed_max = + RrAppearanceCopy(theme->a_focused_pressed_max); + } + if (!read_appearance(db, inst, + "window.inactive.button.toggled.pressed.bg", + theme->a_toggled_unfocused_pressed_max, + TRUE)) + { + RrAppearanceFree(theme->a_toggled_unfocused_pressed_max); + theme->a_toggled_unfocused_pressed_max = + RrAppearanceCopy(theme->a_unfocused_pressed_max); + } + if (!read_appearance(db, inst, + "window.active.button.unpressed.bg", + theme->a_focused_unpressed_max, + TRUE)) + set_default_appearance(theme->a_focused_unpressed_max); + if (!read_appearance(db, inst, + "window.inactive.button.unpressed.bg", + theme->a_unfocused_unpressed_max, + TRUE)) + set_default_appearance(theme->a_unfocused_unpressed_max); + if (!read_appearance(db, inst, + "window.active.button.hover.bg", + theme->a_hover_focused_max, + TRUE)) + { + RrAppearanceFree(theme->a_hover_focused_max); + theme->a_hover_focused_max = + RrAppearanceCopy(theme->a_focused_unpressed_max); + } + if (!read_appearance(db, inst, + "window.inactive.button.hover.bg", + theme->a_hover_unfocused_max, + TRUE)) + { + RrAppearanceFree(theme->a_hover_unfocused_max); + theme->a_hover_unfocused_max = + RrAppearanceCopy(theme->a_unfocused_unpressed_max); + } + + theme->a_disabled_focused_close = + RrAppearanceCopy(theme->a_disabled_focused_max); + theme->a_disabled_unfocused_close = + RrAppearanceCopy(theme->a_disabled_unfocused_max); + theme->a_hover_focused_close = + RrAppearanceCopy(theme->a_hover_focused_max); + theme->a_hover_unfocused_close = + RrAppearanceCopy(theme->a_hover_unfocused_max); + theme->a_unfocused_unpressed_close = + RrAppearanceCopy(theme->a_unfocused_unpressed_max); + theme->a_unfocused_pressed_close = + RrAppearanceCopy(theme->a_unfocused_pressed_max); + theme->a_focused_unpressed_close = + RrAppearanceCopy(theme->a_focused_unpressed_max); + theme->a_focused_pressed_close = + RrAppearanceCopy(theme->a_focused_pressed_max); + theme->a_disabled_focused_desk = + RrAppearanceCopy(theme->a_disabled_focused_max); + theme->a_disabled_unfocused_desk = + RrAppearanceCopy(theme->a_disabled_unfocused_max); + theme->a_hover_focused_desk = + RrAppearanceCopy(theme->a_hover_focused_max); + theme->a_hover_unfocused_desk = + RrAppearanceCopy(theme->a_hover_unfocused_max); + theme->a_toggled_hover_focused_desk = + RrAppearanceCopy(theme->a_toggled_hover_focused_max); + theme->a_toggled_hover_unfocused_desk = + RrAppearanceCopy(theme->a_toggled_hover_unfocused_max); + theme->a_toggled_focused_unpressed_desk = + RrAppearanceCopy(theme->a_toggled_focused_unpressed_max); + theme->a_toggled_unfocused_unpressed_desk = + RrAppearanceCopy(theme->a_toggled_unfocused_unpressed_max); + theme->a_toggled_focused_pressed_desk = + RrAppearanceCopy(theme->a_toggled_focused_pressed_max); + theme->a_toggled_unfocused_pressed_desk = + RrAppearanceCopy(theme->a_toggled_unfocused_pressed_max); + theme->a_unfocused_unpressed_desk = + RrAppearanceCopy(theme->a_unfocused_unpressed_max); + theme->a_unfocused_pressed_desk = + RrAppearanceCopy(theme->a_unfocused_pressed_max); + theme->a_focused_unpressed_desk = + RrAppearanceCopy(theme->a_focused_unpressed_max); + theme->a_focused_pressed_desk = + RrAppearanceCopy(theme->a_focused_pressed_max); + theme->a_disabled_focused_shade = + RrAppearanceCopy(theme->a_disabled_focused_max); + theme->a_disabled_unfocused_shade = + RrAppearanceCopy(theme->a_disabled_unfocused_max); + theme->a_hover_focused_shade = + RrAppearanceCopy(theme->a_hover_focused_max); + theme->a_hover_unfocused_shade = + RrAppearanceCopy(theme->a_hover_unfocused_max); + theme->a_toggled_hover_focused_shade = + RrAppearanceCopy(theme->a_toggled_hover_focused_max); + theme->a_toggled_hover_unfocused_shade = + RrAppearanceCopy(theme->a_toggled_hover_unfocused_max); + theme->a_toggled_focused_unpressed_shade = + RrAppearanceCopy(theme->a_toggled_focused_unpressed_max); + theme->a_toggled_unfocused_unpressed_shade = + RrAppearanceCopy(theme->a_toggled_unfocused_unpressed_max); + theme->a_toggled_focused_pressed_shade = + RrAppearanceCopy(theme->a_toggled_focused_pressed_max); + theme->a_toggled_unfocused_pressed_shade = + RrAppearanceCopy(theme->a_toggled_unfocused_pressed_max); + theme->a_unfocused_unpressed_shade = + RrAppearanceCopy(theme->a_unfocused_unpressed_max); + theme->a_unfocused_pressed_shade = + RrAppearanceCopy(theme->a_unfocused_pressed_max); + theme->a_focused_unpressed_shade = + RrAppearanceCopy(theme->a_focused_unpressed_max); + theme->a_focused_pressed_shade = + RrAppearanceCopy(theme->a_focused_pressed_max); + theme->a_disabled_focused_iconify = + RrAppearanceCopy(theme->a_disabled_focused_max); + theme->a_disabled_unfocused_iconify = + RrAppearanceCopy(theme->a_disabled_focused_max); + theme->a_hover_focused_iconify = + RrAppearanceCopy(theme->a_hover_focused_max); + theme->a_hover_unfocused_iconify = + RrAppearanceCopy(theme->a_hover_unfocused_max); + theme->a_unfocused_unpressed_iconify = + RrAppearanceCopy(theme->a_unfocused_unpressed_max); + theme->a_unfocused_pressed_iconify = + RrAppearanceCopy(theme->a_unfocused_pressed_max); + theme->a_focused_unpressed_iconify = + RrAppearanceCopy(theme->a_focused_unpressed_max); + theme->a_focused_pressed_iconify = + RrAppearanceCopy(theme->a_focused_pressed_max); + + theme->a_icon->surface.grad = + theme->a_clear->surface.grad = + theme->a_clear_tex->surface.grad = + theme->a_menu_text_title->surface.grad = + theme->a_menu_normal->surface.grad = + theme->a_menu_disabled->surface.grad = + theme->a_menu_text_normal->surface.grad = + theme->a_menu_text_selected->surface.grad = + theme->a_menu_text_disabled->surface.grad = + theme->a_menu_text_disabled_selected->surface.grad = + theme->a_menu_bullet_normal->surface.grad = + theme->a_menu_bullet_selected->surface.grad = RR_SURFACE_PARENTREL; + + /* set up the textures */ + theme->a_focused_label->texture[0].type = RR_TEXTURE_TEXT; + theme->a_focused_label->texture[0].data.text.justify = winjust; + theme->a_focused_label->texture[0].data.text.font=theme->win_font_focused; + theme->a_focused_label->texture[0].data.text.color = + theme->title_focused_color; + + if (read_string(db, "window.active.label.text.font", &str)) { + char *p; + gint i = 0; + gint j; + if (strstr(str, "shadow=y")) { + if ((p = strstr(str, "shadowoffset="))) + i = parse_inline_number(p + strlen("shadowoffset=")); + else + i = 1; + theme->a_focused_label->texture[0].data.text.shadow_offset_x = i; + theme->a_focused_label->texture[0].data.text.shadow_offset_y = i; + } + if ((p = strstr(str, "shadowtint="))) + { + i = parse_inline_number(p + strlen("shadowtint=")); + j = (i > 0 ? 0 : 255); + i = ABS(i*255/100); + + theme->title_focused_shadow_color = RrColorNew(inst, j, j, j); + theme->title_focused_shadow_alpha = i; + } else { + theme->title_focused_shadow_color = RrColorNew(inst, 0, 0, 0); + theme->title_focused_shadow_alpha = 50; + } + } + + theme->a_focused_label->texture[0].data.text.shadow_color = + theme->title_focused_shadow_color; + theme->a_focused_label->texture[0].data.text.shadow_alpha = + theme->title_focused_shadow_alpha; + + theme->osd_hilite_label->texture[0].type = RR_TEXTURE_TEXT; + theme->osd_hilite_label->texture[0].data.text.justify = RR_JUSTIFY_LEFT; + theme->osd_hilite_label->texture[0].data.text.font = + theme->osd_font_hilite; + theme->osd_hilite_label->texture[0].data.text.color = + theme->osd_text_active_color; + + theme->osd_unhilite_label->texture[0].type = RR_TEXTURE_TEXT; + theme->osd_unhilite_label->texture[0].data.text.justify = RR_JUSTIFY_LEFT; + theme->osd_unhilite_label->texture[0].data.text.font = + theme->osd_font_unhilite; + theme->osd_unhilite_label->texture[0].data.text.color = + theme->osd_text_inactive_color; + + if (read_string(db, "osd.active.label.text.font", &str) || + read_string(db, "osd.label.text.font", &str)) + { + char *p; + gint i = 0; + gint j; + if (strstr(str, "shadow=y")) { + if ((p = strstr(str, "shadowoffset="))) + i = parse_inline_number(p + strlen("shadowoffset=")); + else + i = 1; + theme->osd_hilite_label->texture[0].data.text.shadow_offset_x = i; + theme->osd_hilite_label->texture[0].data.text.shadow_offset_y = i; + } + if ((p = strstr(str, "shadowtint="))) + { + i = parse_inline_number(p + strlen("shadowtint=")); + j = (i > 0 ? 0 : 255); + i = ABS(i*255/100); + + theme->osd_text_active_shadow_color = RrColorNew(inst, j, j, j); + theme->osd_text_active_shadow_alpha = i; + } else { + theme->osd_text_active_shadow_color = RrColorNew(inst, 0, 0, 0); + theme->osd_text_active_shadow_alpha = 50; + } + } else { + /* inherit the font settings from the focused label */ + theme->osd_hilite_label->texture[0].data.text.shadow_offset_x = + theme->a_focused_label->texture[0].data.text.shadow_offset_x; + theme->osd_hilite_label->texture[0].data.text.shadow_offset_y = + theme->a_focused_label->texture[0].data.text.shadow_offset_y; + if (theme->title_focused_shadow_color) + theme->osd_text_active_shadow_color = + RrColorNew(inst, + theme->title_focused_shadow_color->r, + theme->title_focused_shadow_color->g, + theme->title_focused_shadow_color->b); + else + theme->osd_text_active_shadow_color = RrColorNew(inst, 0, 0, 0); + theme->osd_text_active_shadow_alpha = + theme->title_focused_shadow_alpha; + } + + theme->osd_hilite_label->texture[0].data.text.shadow_color = + theme->osd_text_active_shadow_color; + theme->osd_hilite_label->texture[0].data.text.shadow_alpha = + theme->osd_text_active_shadow_alpha; + + if (read_string(db, "osd.inactive.label.text.font", &str)) + { + char *p; + gint i = 0; + gint j; + if (strstr(str, "shadow=y")) { + if ((p = strstr(str, "shadowoffset="))) + i = parse_inline_number(p + strlen("shadowoffset=")); + else + i = 1; + theme->osd_unhilite_label->texture[0].data.text.shadow_offset_x=i; + theme->osd_unhilite_label->texture[0].data.text.shadow_offset_y=i; + } + if ((p = strstr(str, "shadowtint="))) + { + i = parse_inline_number(p + strlen("shadowtint=")); + j = (i > 0 ? 0 : 255); + i = ABS(i*255/100); + + theme->osd_text_inactive_shadow_color = RrColorNew(inst, j, j, j); + theme->osd_text_inactive_shadow_alpha = i; + } else { + theme->osd_text_inactive_shadow_color = RrColorNew(inst, 0, 0, 0); + theme->osd_text_inactive_shadow_alpha = 50; + } + } else { + /* inherit the font settings from the focused label */ + theme->osd_unhilite_label->texture[0].data.text.shadow_offset_x = + theme->a_unfocused_label->texture[0].data.text.shadow_offset_x; + theme->osd_unhilite_label->texture[0].data.text.shadow_offset_y = + theme->a_unfocused_label->texture[0].data.text.shadow_offset_y; + if (theme->title_unfocused_shadow_color) + theme->osd_text_inactive_shadow_color = + RrColorNew(inst, + theme->title_unfocused_shadow_color->r, + theme->title_unfocused_shadow_color->g, + theme->title_unfocused_shadow_color->b); + else + theme->osd_text_inactive_shadow_color = RrColorNew(inst, 0, 0, 0); + theme->osd_text_inactive_shadow_alpha = + theme->title_unfocused_shadow_alpha; + } + + theme->osd_unhilite_label->texture[0].data.text.shadow_color = + theme->osd_text_inactive_shadow_color; + theme->osd_unhilite_label->texture[0].data.text.shadow_alpha = + theme->osd_text_inactive_shadow_alpha; + + theme->a_unfocused_label->texture[0].type = RR_TEXTURE_TEXT; + theme->a_unfocused_label->texture[0].data.text.justify = winjust; + theme->a_unfocused_label->texture[0].data.text.font = + theme->win_font_unfocused; + theme->a_unfocused_label->texture[0].data.text.color = + theme->title_unfocused_color; + + if (read_string(db, "window.inactive.label.text.font", &str)) { + char *p; + gint i = 0; + gint j; + if (strstr(str, "shadow=y")) { + if ((p = strstr(str, "shadowoffset="))) + i = parse_inline_number(p + strlen("shadowoffset=")); + else + i = 1; + theme->a_unfocused_label->texture[0].data.text.shadow_offset_x = i; + theme->a_unfocused_label->texture[0].data.text.shadow_offset_y = i; + } + if ((p = strstr(str, "shadowtint="))) + { + i = parse_inline_number(p + strlen("shadowtint=")); + j = (i > 0 ? 0 : 255); + i = ABS(i*255/100); + + theme->title_unfocused_shadow_color = RrColorNew(inst, j, j, j); + theme->title_unfocused_shadow_alpha = i; + } else { + theme->title_unfocused_shadow_color = RrColorNew(inst, 0, 0, 0); + theme->title_unfocused_shadow_alpha = 50; + } + } + + theme->a_unfocused_label->texture[0].data.text.shadow_color = + theme->title_unfocused_shadow_color; + theme->a_unfocused_label->texture[0].data.text.shadow_alpha = + theme->title_unfocused_shadow_alpha; + + theme->a_menu_text_title->texture[0].type = RR_TEXTURE_TEXT; + theme->a_menu_text_title->texture[0].data.text.justify = mtitlejust; + theme->a_menu_text_title->texture[0].data.text.font = + theme->menu_title_font; + theme->a_menu_text_title->texture[0].data.text.color = + theme->menu_title_color; + + if (read_string(db, "menu.title.text.font", &str)) { + char *p; + gint i = 0; + gint j; + if (strstr(str, "shadow=y")) { + if ((p = strstr(str, "shadowoffset="))) + i = parse_inline_number(p + strlen("shadowoffset=")); + else + i = 1; + theme->a_menu_text_title->texture[0].data.text.shadow_offset_x = i; + theme->a_menu_text_title->texture[0].data.text.shadow_offset_y = i; + } + if ((p = strstr(str, "shadowtint="))) + { + i = parse_inline_number(p + strlen("shadowtint=")); + j = (i > 0 ? 0 : 255); + i = ABS(i*255/100); + + theme->menu_title_shadow_color = RrColorNew(inst, j, j, j); + theme->menu_title_shadow_alpha = i; + } else { + theme->menu_title_shadow_color = RrColorNew(inst, 0, 0, 0); + theme->menu_title_shadow_alpha = 50; + } + } + + theme->a_menu_text_title->texture[0].data.text.shadow_color = + theme->menu_title_shadow_color; + theme->a_menu_text_title->texture[0].data.text.shadow_alpha = + theme->menu_title_shadow_alpha; + + theme->a_menu_text_normal->texture[0].type = + theme->a_menu_text_selected->texture[0].type = + theme->a_menu_text_disabled->texture[0].type = + theme->a_menu_text_disabled_selected->texture[0].type = + RR_TEXTURE_TEXT; + theme->a_menu_text_normal->texture[0].data.text.justify = + theme->a_menu_text_selected->texture[0].data.text.justify = + theme->a_menu_text_disabled->texture[0].data.text.justify = + theme->a_menu_text_disabled_selected->texture[0].data.text.justify = + RR_JUSTIFY_LEFT; + theme->a_menu_text_normal->texture[0].data.text.font = + theme->a_menu_text_selected->texture[0].data.text.font = + theme->a_menu_text_disabled->texture[0].data.text.font = + theme->a_menu_text_disabled_selected->texture[0].data.text.font = + theme->menu_font; + theme->a_menu_text_normal->texture[0].data.text.color = theme->menu_color; + theme->a_menu_text_selected->texture[0].data.text.color = + theme->menu_selected_color; + theme->a_menu_text_disabled->texture[0].data.text.color = + theme->menu_disabled_color; + theme->a_menu_text_disabled_selected->texture[0].data.text.color = + theme->menu_disabled_selected_color; + + if (read_string(db, "menu.items.font", &str)) { + char *p; + gint i = 0; + gint j; + if (strstr(str, "shadow=y")) { + if ((p = strstr(str, "shadowoffset="))) + i = parse_inline_number(p + strlen("shadowoffset=")); + else + i = 1; + theme->a_menu_text_normal-> + texture[0].data.text.shadow_offset_x = i; + theme->a_menu_text_normal-> + texture[0].data.text.shadow_offset_y = i; + theme->a_menu_text_selected-> + texture[0].data.text.shadow_offset_x = i; + theme->a_menu_text_selected-> + texture[0].data.text.shadow_offset_y = i; + theme->a_menu_text_disabled-> + texture[0].data.text.shadow_offset_x = i; + theme->a_menu_text_disabled-> + texture[0].data.text.shadow_offset_y = i; + theme->a_menu_text_disabled_selected-> + texture[0].data.text.shadow_offset_x = i; + theme->a_menu_text_disabled_selected-> + texture[0].data.text.shadow_offset_y = i; + } + if ((p = strstr(str, "shadowtint="))) + { + i = parse_inline_number(p + strlen("shadowtint=")); + j = (i > 0 ? 0 : 255); + i = ABS(i*255/100); + + theme->menu_text_normal_shadow_color = RrColorNew(inst, j, j, j); + theme->menu_text_selected_shadow_color = RrColorNew(inst, j, j, j); + theme->menu_text_disabled_shadow_color = RrColorNew(inst, j, j, j); + theme->menu_text_normal_shadow_alpha = i; + theme->menu_text_selected_shadow_alpha = i; + theme->menu_text_disabled_shadow_alpha = i; + theme->menu_text_disabled_selected_shadow_alpha = i; + } else { + theme->menu_text_normal_shadow_color = RrColorNew(inst, 0, 0, 0); + theme->menu_text_selected_shadow_color = RrColorNew(inst, 0, 0, 0); + theme->menu_text_disabled_shadow_color = RrColorNew(inst, 0, 0, 0); + theme->menu_text_normal_shadow_alpha = 50; + theme->menu_text_selected_shadow_alpha = 50; + theme->menu_text_disabled_selected_shadow_alpha = 50; + } + } + + theme->a_menu_text_normal->texture[0].data.text.shadow_color = + theme->menu_text_normal_shadow_color; + theme->a_menu_text_normal->texture[0].data.text.shadow_alpha = + theme->menu_text_normal_shadow_alpha; + theme->a_menu_text_selected->texture[0].data.text.shadow_color = + theme->menu_text_selected_shadow_color; + theme->a_menu_text_selected->texture[0].data.text.shadow_alpha = + theme->menu_text_selected_shadow_alpha; + theme->a_menu_text_disabled->texture[0].data.text.shadow_color = + theme->menu_text_disabled_shadow_color; + theme->a_menu_text_disabled->texture[0].data.text.shadow_alpha = + theme->menu_text_disabled_shadow_alpha; + theme->a_menu_text_disabled_selected->texture[0].data.text.shadow_color = + theme->menu_text_disabled_shadow_color; + theme->a_menu_text_disabled_selected->texture[0].data.text.shadow_alpha = + theme->menu_text_disabled_shadow_alpha; + + theme->a_disabled_focused_max->texture[0].type = + theme->a_disabled_unfocused_max->texture[0].type = + theme->a_hover_focused_max->texture[0].type = + theme->a_hover_unfocused_max->texture[0].type = + theme->a_toggled_hover_focused_max->texture[0].type = + theme->a_toggled_hover_unfocused_max->texture[0].type = + theme->a_toggled_focused_unpressed_max->texture[0].type = + theme->a_toggled_unfocused_unpressed_max->texture[0].type = + theme->a_toggled_focused_pressed_max->texture[0].type = + theme->a_toggled_unfocused_pressed_max->texture[0].type = + theme->a_focused_unpressed_max->texture[0].type = + theme->a_focused_pressed_max->texture[0].type = + theme->a_unfocused_unpressed_max->texture[0].type = + theme->a_unfocused_pressed_max->texture[0].type = + theme->a_disabled_focused_close->texture[0].type = + theme->a_disabled_unfocused_close->texture[0].type = + theme->a_hover_focused_close->texture[0].type = + theme->a_hover_unfocused_close->texture[0].type = + theme->a_focused_unpressed_close->texture[0].type = + theme->a_focused_pressed_close->texture[0].type = + theme->a_unfocused_unpressed_close->texture[0].type = + theme->a_unfocused_pressed_close->texture[0].type = + theme->a_disabled_focused_desk->texture[0].type = + theme->a_disabled_unfocused_desk->texture[0].type = + theme->a_hover_focused_desk->texture[0].type = + theme->a_hover_unfocused_desk->texture[0].type = + theme->a_toggled_hover_focused_desk->texture[0].type = + theme->a_toggled_hover_unfocused_desk->texture[0].type = + theme->a_toggled_focused_unpressed_desk->texture[0].type = + theme->a_toggled_unfocused_unpressed_desk->texture[0].type = + theme->a_toggled_focused_pressed_desk->texture[0].type = + theme->a_toggled_unfocused_pressed_desk->texture[0].type = + theme->a_focused_unpressed_desk->texture[0].type = + theme->a_focused_pressed_desk->texture[0].type = + theme->a_unfocused_unpressed_desk->texture[0].type = + theme->a_unfocused_pressed_desk->texture[0].type = + theme->a_disabled_focused_shade->texture[0].type = + theme->a_disabled_unfocused_shade->texture[0].type = + theme->a_hover_focused_shade->texture[0].type = + theme->a_hover_unfocused_shade->texture[0].type = + theme->a_toggled_hover_focused_shade->texture[0].type = + theme->a_toggled_hover_unfocused_shade->texture[0].type = + theme->a_toggled_focused_unpressed_shade->texture[0].type = + theme->a_toggled_unfocused_unpressed_shade->texture[0].type = + theme->a_toggled_focused_pressed_shade->texture[0].type = + theme->a_toggled_unfocused_pressed_shade->texture[0].type = + theme->a_focused_unpressed_shade->texture[0].type = + theme->a_focused_pressed_shade->texture[0].type = + theme->a_unfocused_unpressed_shade->texture[0].type = + theme->a_unfocused_pressed_shade->texture[0].type = + theme->a_disabled_focused_iconify->texture[0].type = + theme->a_disabled_unfocused_iconify->texture[0].type = + theme->a_hover_focused_iconify->texture[0].type = + theme->a_hover_unfocused_iconify->texture[0].type = + theme->a_focused_unpressed_iconify->texture[0].type = + theme->a_focused_pressed_iconify->texture[0].type = + theme->a_unfocused_unpressed_iconify->texture[0].type = + theme->a_unfocused_pressed_iconify->texture[0].type = + theme->a_menu_bullet_normal->texture[0].type = + theme->a_menu_bullet_selected->texture[0].type = RR_TEXTURE_MASK; + + theme->a_disabled_focused_max->texture[0].data.mask.mask = + theme->a_disabled_unfocused_max->texture[0].data.mask.mask = + theme->max_disabled_mask; + theme->a_hover_focused_max->texture[0].data.mask.mask = + theme->a_hover_unfocused_max->texture[0].data.mask.mask = + theme->max_hover_mask; + theme->a_focused_pressed_max->texture[0].data.mask.mask = + theme->a_unfocused_pressed_max->texture[0].data.mask.mask = + theme->max_pressed_mask; + theme->a_focused_unpressed_max->texture[0].data.mask.mask = + theme->a_unfocused_unpressed_max->texture[0].data.mask.mask = + theme->max_mask; + theme->a_toggled_hover_focused_max->texture[0].data.mask.mask = + theme->a_toggled_hover_unfocused_max->texture[0].data.mask.mask = + theme->max_toggled_hover_mask; + theme->a_toggled_focused_unpressed_max->texture[0].data.mask.mask = + theme->a_toggled_unfocused_unpressed_max->texture[0].data.mask.mask = + theme->max_toggled_mask; + theme->a_toggled_focused_pressed_max->texture[0].data.mask.mask = + theme->a_toggled_unfocused_pressed_max->texture[0].data.mask.mask = + theme->max_toggled_pressed_mask; + theme->a_disabled_focused_close->texture[0].data.mask.mask = + theme->a_disabled_unfocused_close->texture[0].data.mask.mask = + theme->close_disabled_mask; + theme->a_hover_focused_close->texture[0].data.mask.mask = + theme->a_hover_unfocused_close->texture[0].data.mask.mask = + theme->close_hover_mask; + theme->a_focused_pressed_close->texture[0].data.mask.mask = + theme->a_unfocused_pressed_close->texture[0].data.mask.mask = + theme->close_pressed_mask; + theme->a_focused_unpressed_close->texture[0].data.mask.mask = + theme->a_unfocused_unpressed_close->texture[0].data.mask.mask = + theme->close_mask; + theme->a_disabled_focused_desk->texture[0].data.mask.mask = + theme->a_disabled_unfocused_desk->texture[0].data.mask.mask = + theme->desk_disabled_mask; + theme->a_hover_focused_desk->texture[0].data.mask.mask = + theme->a_hover_unfocused_desk->texture[0].data.mask.mask = + theme->desk_hover_mask; + theme->a_focused_pressed_desk->texture[0].data.mask.mask = + theme->a_unfocused_pressed_desk->texture[0].data.mask.mask = + theme->desk_pressed_mask; + theme->a_focused_unpressed_desk->texture[0].data.mask.mask = + theme->a_unfocused_unpressed_desk->texture[0].data.mask.mask = + theme->desk_mask; + theme->a_toggled_hover_focused_desk->texture[0].data.mask.mask = + theme->a_toggled_hover_unfocused_desk->texture[0].data.mask.mask = + theme->desk_toggled_hover_mask; + theme->a_toggled_focused_unpressed_desk->texture[0].data.mask.mask = + theme->a_toggled_unfocused_unpressed_desk->texture[0].data.mask.mask = + theme->desk_toggled_mask; + theme->a_toggled_focused_pressed_desk->texture[0].data.mask.mask = + theme->a_toggled_unfocused_pressed_desk->texture[0].data.mask.mask = + theme->desk_toggled_pressed_mask; + theme->a_disabled_focused_shade->texture[0].data.mask.mask = + theme->a_disabled_unfocused_shade->texture[0].data.mask.mask = + theme->shade_disabled_mask; + theme->a_hover_focused_shade->texture[0].data.mask.mask = + theme->a_hover_unfocused_shade->texture[0].data.mask.mask = + theme->shade_hover_mask; + theme->a_focused_pressed_shade->texture[0].data.mask.mask = + theme->a_unfocused_pressed_shade->texture[0].data.mask.mask = + theme->shade_pressed_mask; + theme->a_focused_unpressed_shade->texture[0].data.mask.mask = + theme->a_unfocused_unpressed_shade->texture[0].data.mask.mask = + theme->shade_mask; + theme->a_toggled_hover_focused_shade->texture[0].data.mask.mask = + theme->a_toggled_hover_unfocused_shade->texture[0].data.mask.mask = + theme->shade_toggled_hover_mask; + theme->a_toggled_focused_unpressed_shade->texture[0].data.mask.mask = + theme->a_toggled_unfocused_unpressed_shade->texture[0].data.mask.mask = + theme->shade_toggled_mask; + theme->a_toggled_focused_pressed_shade->texture[0].data.mask.mask = + theme->a_toggled_unfocused_pressed_shade->texture[0].data.mask.mask = + theme->shade_toggled_pressed_mask; + theme->a_disabled_focused_iconify->texture[0].data.mask.mask = + theme->a_disabled_unfocused_iconify->texture[0].data.mask.mask = + theme->iconify_disabled_mask; + theme->a_hover_focused_iconify->texture[0].data.mask.mask = + theme->a_hover_unfocused_iconify->texture[0].data.mask.mask = + theme->iconify_hover_mask; + theme->a_focused_pressed_iconify->texture[0].data.mask.mask = + theme->a_unfocused_pressed_iconify->texture[0].data.mask.mask = + theme->iconify_pressed_mask; + theme->a_focused_unpressed_iconify->texture[0].data.mask.mask = + theme->a_unfocused_unpressed_iconify->texture[0].data.mask.mask = + theme->iconify_mask; + theme->a_menu_bullet_normal->texture[0].data.mask.mask = + theme->a_menu_bullet_selected->texture[0].data.mask.mask = + theme->menu_bullet_mask; + theme->a_disabled_focused_max->texture[0].data.mask.color = + theme->a_disabled_focused_close->texture[0].data.mask.color = + theme->a_disabled_focused_desk->texture[0].data.mask.color = + theme->a_disabled_focused_shade->texture[0].data.mask.color = + theme->a_disabled_focused_iconify->texture[0].data.mask.color = + theme->titlebut_disabled_focused_color; + theme->a_disabled_unfocused_max->texture[0].data.mask.color = + theme->a_disabled_unfocused_close->texture[0].data.mask.color = + theme->a_disabled_unfocused_desk->texture[0].data.mask.color = + theme->a_disabled_unfocused_shade->texture[0].data.mask.color = + theme->a_disabled_unfocused_iconify->texture[0].data.mask.color = + theme->titlebut_disabled_unfocused_color; + theme->a_hover_focused_max->texture[0].data.mask.color = + theme->a_hover_focused_close->texture[0].data.mask.color = + theme->a_hover_focused_desk->texture[0].data.mask.color = + theme->a_hover_focused_shade->texture[0].data.mask.color = + theme->a_hover_focused_iconify->texture[0].data.mask.color = + theme->titlebut_hover_focused_color; + theme->a_hover_unfocused_max->texture[0].data.mask.color = + theme->a_hover_unfocused_close->texture[0].data.mask.color = + theme->a_hover_unfocused_desk->texture[0].data.mask.color = + theme->a_hover_unfocused_shade->texture[0].data.mask.color = + theme->a_hover_unfocused_iconify->texture[0].data.mask.color = + theme->titlebut_hover_unfocused_color; + theme->a_toggled_hover_focused_max->texture[0].data.mask.color = + theme->a_toggled_hover_focused_desk->texture[0].data.mask.color = + theme->a_toggled_hover_focused_shade->texture[0].data.mask.color = + theme->titlebut_toggled_hover_focused_color; + theme->a_toggled_hover_unfocused_max->texture[0].data.mask.color = + theme->a_toggled_hover_unfocused_desk->texture[0].data.mask.color = + theme->a_toggled_hover_unfocused_shade->texture[0].data.mask.color = + theme->titlebut_toggled_hover_unfocused_color; + theme->a_toggled_focused_unpressed_max->texture[0].data.mask.color = + theme->a_toggled_focused_unpressed_desk->texture[0].data.mask.color = + theme->a_toggled_focused_unpressed_shade->texture[0].data.mask.color = + theme->titlebut_toggled_focused_unpressed_color; + theme->a_toggled_unfocused_unpressed_max->texture[0].data.mask.color = + theme->a_toggled_unfocused_unpressed_desk->texture[0].data.mask.color = + theme->a_toggled_unfocused_unpressed_shade->texture[0].data.mask.color= + theme->titlebut_toggled_unfocused_unpressed_color; + theme->a_toggled_focused_pressed_max->texture[0].data.mask.color = + theme->a_toggled_focused_pressed_desk->texture[0].data.mask.color = + theme->a_toggled_focused_pressed_shade->texture[0].data.mask.color = + theme->titlebut_toggled_focused_pressed_color; + theme->a_toggled_unfocused_pressed_max->texture[0].data.mask.color = + theme->a_toggled_unfocused_pressed_desk->texture[0].data.mask.color = + theme->a_toggled_unfocused_pressed_shade->texture[0].data.mask.color = + theme->titlebut_toggled_unfocused_pressed_color; + theme->a_focused_unpressed_max->texture[0].data.mask.color = + theme->a_focused_unpressed_close->texture[0].data.mask.color = + theme->a_focused_unpressed_desk->texture[0].data.mask.color = + theme->a_focused_unpressed_shade->texture[0].data.mask.color = + theme->a_focused_unpressed_iconify->texture[0].data.mask.color = + theme->titlebut_focused_unpressed_color; + theme->a_focused_pressed_max->texture[0].data.mask.color = + theme->a_focused_pressed_close->texture[0].data.mask.color = + theme->a_focused_pressed_desk->texture[0].data.mask.color = + theme->a_focused_pressed_shade->texture[0].data.mask.color = + theme->a_focused_pressed_iconify->texture[0].data.mask.color = + theme->titlebut_focused_pressed_color; + theme->a_unfocused_unpressed_max->texture[0].data.mask.color = + theme->a_unfocused_unpressed_close->texture[0].data.mask.color = + theme->a_unfocused_unpressed_desk->texture[0].data.mask.color = + theme->a_unfocused_unpressed_shade->texture[0].data.mask.color = + theme->a_unfocused_unpressed_iconify->texture[0].data.mask.color = + theme->titlebut_unfocused_unpressed_color; + theme->a_unfocused_pressed_max->texture[0].data.mask.color = + theme->a_unfocused_pressed_close->texture[0].data.mask.color = + theme->a_unfocused_pressed_desk->texture[0].data.mask.color = + theme->a_unfocused_pressed_shade->texture[0].data.mask.color = + theme->a_unfocused_pressed_iconify->texture[0].data.mask.color = + theme->titlebut_unfocused_pressed_color; + theme->a_menu_bullet_normal->texture[0].data.mask.color = + theme->menu_color; + theme->a_menu_bullet_selected->texture[0].data.mask.color = + theme->menu_selected_color; + + g_free(path); + XrmDestroyDatabase(db); + + /* set the font heights */ + theme->win_font_height = RrFontHeight + (theme->win_font_focused, + theme->a_focused_label->texture[0].data.text.shadow_offset_y); + theme->win_font_height = + MAX(theme->win_font_height, + RrFontHeight + (theme->win_font_focused, + theme->a_unfocused_label->texture[0].data.text.shadow_offset_y)); + theme->menu_title_font_height = RrFontHeight + (theme->menu_title_font, + theme->a_menu_text_title->texture[0].data.text.shadow_offset_y); + theme->menu_font_height = RrFontHeight + (theme->menu_font, + theme->a_menu_text_normal->texture[0].data.text.shadow_offset_y); + + /* calculate some last extents */ + { + gint ft, fb, fl, fr, ut, ub, ul, ur; + + RrMargins(theme->a_focused_label, &fl, &ft, &fr, &fb); + RrMargins(theme->a_unfocused_label, &ul, &ut, &ur, &ub); + theme->label_height = theme->win_font_height + MAX(ft + fb, ut + ub); + theme->label_height += theme->label_height % 2; + + /* this would be nice I think, since padding.width can now be 0, + but it breaks frame.c horribly and I don't feel like fixing that + right now, so if anyone complains, here is how to keep text from + going over the title's bevel/border with a padding.width of 0 and a + bevelless/borderless label + RrMargins(theme->a_focused_title, &fl, &ft, &fr, &fb); + RrMargins(theme->a_unfocused_title, &ul, &ut, &ur, &ub); + theme->title_height = theme->label_height + + MAX(MAX(theme->padding * 2, ft + fb), + MAX(theme->padding * 2, ut + ub)); + */ + theme->title_height = theme->label_height + theme->paddingy * 2; + + RrMargins(theme->a_menu_title, &ul, &ut, &ur, &ub); + theme->menu_title_label_height = theme->menu_title_font_height+ut+ub; + theme->menu_title_height = theme->menu_title_label_height + + theme->paddingy * 2; + } + theme->button_size = theme->label_height - 2; + theme->grip_width = 25; + + return theme; +} + +void RrThemeFree(RrTheme *theme) +{ + if (theme) { + g_free(theme->name); + + RrColorFree(theme->menu_border_color); + RrColorFree(theme->osd_border_color); + RrColorFree(theme->frame_focused_border_color); + RrColorFree(theme->frame_unfocused_border_color); + RrColorFree(theme->title_separator_focused_color); + RrColorFree(theme->title_separator_unfocused_color); + RrColorFree(theme->cb_unfocused_color); + RrColorFree(theme->cb_focused_color); + RrColorFree(theme->title_focused_color); + RrColorFree(theme->title_unfocused_color); + RrColorFree(theme->titlebut_disabled_focused_color); + RrColorFree(theme->titlebut_disabled_unfocused_color); + RrColorFree(theme->titlebut_hover_focused_color); + RrColorFree(theme->titlebut_hover_unfocused_color); + RrColorFree(theme->titlebut_toggled_hover_focused_color); + RrColorFree(theme->titlebut_toggled_hover_unfocused_color); + RrColorFree(theme->titlebut_toggled_focused_pressed_color); + RrColorFree(theme->titlebut_toggled_unfocused_pressed_color); + RrColorFree(theme->titlebut_toggled_focused_unpressed_color); + RrColorFree(theme->titlebut_toggled_unfocused_unpressed_color); + RrColorFree(theme->titlebut_focused_pressed_color); + RrColorFree(theme->titlebut_unfocused_pressed_color); + RrColorFree(theme->titlebut_focused_unpressed_color); + RrColorFree(theme->titlebut_unfocused_unpressed_color); + RrColorFree(theme->menu_title_color); + RrColorFree(theme->menu_sep_color); + RrColorFree(theme->menu_color); + RrColorFree(theme->menu_selected_color); + RrColorFree(theme->menu_disabled_color); + RrColorFree(theme->menu_disabled_selected_color); + RrColorFree(theme->title_focused_shadow_color); + RrColorFree(theme->title_unfocused_shadow_color); + RrColorFree(theme->osd_text_active_color); + RrColorFree(theme->osd_text_inactive_color); + RrColorFree(theme->osd_text_active_shadow_color); + RrColorFree(theme->osd_text_inactive_shadow_color); + RrColorFree(theme->menu_title_shadow_color); + RrColorFree(theme->menu_text_normal_shadow_color); + RrColorFree(theme->menu_text_selected_shadow_color); + RrColorFree(theme->menu_text_disabled_shadow_color); + RrColorFree(theme->menu_text_disabled_selected_shadow_color); + + g_free(theme->def_win_icon); + + RrPixmapMaskFree(theme->max_mask); + RrPixmapMaskFree(theme->max_toggled_mask); + RrPixmapMaskFree(theme->max_toggled_hover_mask); + RrPixmapMaskFree(theme->max_toggled_pressed_mask); + RrPixmapMaskFree(theme->max_disabled_mask); + RrPixmapMaskFree(theme->max_hover_mask); + RrPixmapMaskFree(theme->max_pressed_mask); + RrPixmapMaskFree(theme->desk_mask); + RrPixmapMaskFree(theme->desk_toggled_mask); + RrPixmapMaskFree(theme->desk_toggled_hover_mask); + RrPixmapMaskFree(theme->desk_toggled_pressed_mask); + RrPixmapMaskFree(theme->desk_disabled_mask); + RrPixmapMaskFree(theme->desk_hover_mask); + RrPixmapMaskFree(theme->desk_pressed_mask); + RrPixmapMaskFree(theme->shade_mask); + RrPixmapMaskFree(theme->shade_toggled_mask); + RrPixmapMaskFree(theme->shade_toggled_hover_mask); + RrPixmapMaskFree(theme->shade_toggled_pressed_mask); + RrPixmapMaskFree(theme->shade_disabled_mask); + RrPixmapMaskFree(theme->shade_hover_mask); + RrPixmapMaskFree(theme->shade_pressed_mask); + RrPixmapMaskFree(theme->iconify_mask); + RrPixmapMaskFree(theme->iconify_disabled_mask); + RrPixmapMaskFree(theme->iconify_hover_mask); + RrPixmapMaskFree(theme->iconify_pressed_mask); + RrPixmapMaskFree(theme->close_mask); + RrPixmapMaskFree(theme->close_disabled_mask); + RrPixmapMaskFree(theme->close_hover_mask); + RrPixmapMaskFree(theme->close_pressed_mask); + RrPixmapMaskFree(theme->menu_bullet_mask); + RrPixmapMaskFree(theme->down_arrow_mask); + RrPixmapMaskFree(theme->up_arrow_mask); + + RrFontClose(theme->win_font_focused); + RrFontClose(theme->win_font_unfocused); + RrFontClose(theme->menu_title_font); + RrFontClose(theme->menu_font); + RrFontClose(theme->osd_font_hilite); + RrFontClose(theme->osd_font_unhilite); + + RrAppearanceFree(theme->a_disabled_focused_max); + RrAppearanceFree(theme->a_disabled_unfocused_max); + RrAppearanceFree(theme->a_hover_focused_max); + RrAppearanceFree(theme->a_hover_unfocused_max); + RrAppearanceFree(theme->a_toggled_hover_focused_max); + RrAppearanceFree(theme->a_toggled_hover_unfocused_max); + RrAppearanceFree(theme->a_toggled_focused_unpressed_max); + RrAppearanceFree(theme->a_toggled_focused_pressed_max); + RrAppearanceFree(theme->a_toggled_unfocused_unpressed_max); + RrAppearanceFree(theme->a_toggled_unfocused_pressed_max); + RrAppearanceFree(theme->a_focused_unpressed_max); + RrAppearanceFree(theme->a_focused_pressed_max); + RrAppearanceFree(theme->a_unfocused_unpressed_max); + RrAppearanceFree(theme->a_unfocused_pressed_max); + RrAppearanceFree(theme->a_disabled_focused_close); + RrAppearanceFree(theme->a_disabled_unfocused_close); + RrAppearanceFree(theme->a_hover_focused_close); + RrAppearanceFree(theme->a_hover_unfocused_close); + RrAppearanceFree(theme->a_focused_unpressed_close); + RrAppearanceFree(theme->a_focused_pressed_close); + RrAppearanceFree(theme->a_unfocused_unpressed_close); + RrAppearanceFree(theme->a_unfocused_pressed_close); + RrAppearanceFree(theme->a_disabled_focused_desk); + RrAppearanceFree(theme->a_disabled_unfocused_desk); + RrAppearanceFree(theme->a_hover_focused_desk); + RrAppearanceFree(theme->a_hover_unfocused_desk); + RrAppearanceFree(theme->a_toggled_hover_focused_desk); + RrAppearanceFree(theme->a_toggled_hover_unfocused_desk); + RrAppearanceFree(theme->a_toggled_focused_unpressed_desk); + RrAppearanceFree(theme->a_toggled_focused_pressed_desk); + RrAppearanceFree(theme->a_toggled_unfocused_unpressed_desk); + RrAppearanceFree(theme->a_toggled_unfocused_pressed_desk); + RrAppearanceFree(theme->a_focused_unpressed_desk); + RrAppearanceFree(theme->a_focused_pressed_desk); + RrAppearanceFree(theme->a_unfocused_unpressed_desk); + RrAppearanceFree(theme->a_unfocused_pressed_desk); + RrAppearanceFree(theme->a_disabled_focused_shade); + RrAppearanceFree(theme->a_disabled_unfocused_shade); + RrAppearanceFree(theme->a_hover_focused_shade); + RrAppearanceFree(theme->a_hover_unfocused_shade); + RrAppearanceFree(theme->a_toggled_hover_focused_shade); + RrAppearanceFree(theme->a_toggled_hover_unfocused_shade); + RrAppearanceFree(theme->a_toggled_focused_unpressed_shade); + RrAppearanceFree(theme->a_toggled_focused_pressed_shade); + RrAppearanceFree(theme->a_toggled_unfocused_unpressed_shade); + RrAppearanceFree(theme->a_toggled_unfocused_pressed_shade); + RrAppearanceFree(theme->a_focused_unpressed_shade); + RrAppearanceFree(theme->a_focused_pressed_shade); + RrAppearanceFree(theme->a_unfocused_unpressed_shade); + RrAppearanceFree(theme->a_unfocused_pressed_shade); + RrAppearanceFree(theme->a_disabled_focused_iconify); + RrAppearanceFree(theme->a_disabled_unfocused_iconify); + RrAppearanceFree(theme->a_hover_focused_iconify); + RrAppearanceFree(theme->a_hover_unfocused_iconify); + RrAppearanceFree(theme->a_focused_unpressed_iconify); + RrAppearanceFree(theme->a_focused_pressed_iconify); + RrAppearanceFree(theme->a_unfocused_unpressed_iconify); + RrAppearanceFree(theme->a_unfocused_pressed_iconify); + RrAppearanceFree(theme->a_focused_grip); + RrAppearanceFree(theme->a_unfocused_grip); + RrAppearanceFree(theme->a_focused_title); + RrAppearanceFree(theme->a_unfocused_title); + RrAppearanceFree(theme->a_focused_label); + RrAppearanceFree(theme->a_unfocused_label); + RrAppearanceFree(theme->a_icon); + RrAppearanceFree(theme->a_focused_handle); + RrAppearanceFree(theme->a_unfocused_handle); + RrAppearanceFree(theme->a_menu); + RrAppearanceFree(theme->a_menu_title); + RrAppearanceFree(theme->a_menu_text_title); + RrAppearanceFree(theme->a_menu_normal); + RrAppearanceFree(theme->a_menu_selected); + RrAppearanceFree(theme->a_menu_disabled); + RrAppearanceFree(theme->a_menu_disabled_selected); + RrAppearanceFree(theme->a_menu_text_normal); + RrAppearanceFree(theme->a_menu_text_selected); + RrAppearanceFree(theme->a_menu_text_disabled); + RrAppearanceFree(theme->a_menu_text_disabled_selected); + RrAppearanceFree(theme->a_menu_bullet_normal); + RrAppearanceFree(theme->a_menu_bullet_selected); + RrAppearanceFree(theme->a_clear); + RrAppearanceFree(theme->a_clear_tex); + RrAppearanceFree(theme->osd_bg); + RrAppearanceFree(theme->osd_hilite_bg); + RrAppearanceFree(theme->osd_hilite_label); + RrAppearanceFree(theme->osd_unhilite_bg); + RrAppearanceFree(theme->osd_unhilite_label); + + g_free(theme); + } +} + +static XrmDatabase loaddb(const gchar *name, gchar **path) +{ + GSList *it; + XrmDatabase db = NULL; + gchar *s; + + if (name[0] == '/') { + s = g_build_filename(name, "openbox-3", "themerc", NULL); + if ((db = XrmGetFileDatabase(s))) + *path = g_path_get_dirname(s); + g_free(s); + } else { + ObtPaths *p; + + p = obt_paths_new(); + + /* XXX backwards compatibility, remove me sometime later */ + s = g_build_filename(g_get_home_dir(), ".themes", name, + "openbox-3", "themerc", NULL); + if ((db = XrmGetFileDatabase(s))) + *path = g_path_get_dirname(s); + g_free(s); + + for (it = obt_paths_data_dirs(p); !db && it; it = g_slist_next(it)) + { + s = g_build_filename(it->data, "themes", name, + "openbox-3", "themerc", NULL); + if ((db = XrmGetFileDatabase(s))) + *path = g_path_get_dirname(s); + g_free(s); + } + + obt_paths_unref(p); + } + + if (db == NULL) { + s = g_build_filename(name, "themerc", NULL); + if ((db = XrmGetFileDatabase(s))) + *path = g_path_get_dirname(s); + g_free(s); + } + + return db; +} + +static gchar *create_class_name(const gchar *rname) +{ + gchar *rclass = g_strdup(rname); + gchar *p = rclass; + + while (TRUE) { + *p = toupper(*p); + p = strchr(p+1, '.'); + if (p == NULL) break; + ++p; + if (*p == '\0') break; + } + return rclass; +} + +static gboolean read_int(XrmDatabase db, const gchar *rname, gint *value) +{ + gboolean ret = FALSE; + gchar *rclass = create_class_name(rname); + gchar *rettype, *end; + XrmValue retvalue; + + if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) && + retvalue.addr != NULL) { + *value = (gint)strtol(retvalue.addr, &end, 10); + if (end != retvalue.addr) + ret = TRUE; + } + + g_free(rclass); + return ret; +} + +static gboolean read_string(XrmDatabase db, const gchar *rname, gchar **value) +{ + gboolean ret = FALSE; + gchar *rclass = create_class_name(rname); + gchar *rettype; + XrmValue retvalue; + + if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) && + retvalue.addr != NULL) { + *value = retvalue.addr; + ret = TRUE; + } + + g_free(rclass); + return ret; +} + +static gboolean read_color(XrmDatabase db, const RrInstance *inst, + const gchar *rname, RrColor **value) +{ + gboolean ret = FALSE; + gchar *rclass = create_class_name(rname); + gchar *rettype; + XrmValue retvalue; + + if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) && + retvalue.addr != NULL) { + RrColor *c = RrColorParse(inst, retvalue.addr); + if (c != NULL) { + *value = c; + ret = TRUE; + } + } + + g_free(rclass); + return ret; +} + +static gboolean read_mask(const RrInstance *inst, const gchar *path, + RrTheme *theme, const gchar *maskname, + RrPixmapMask **value) +{ + gboolean ret = FALSE; + gchar *s; + gint hx, hy; /* ignored */ + guint w, h; + guchar *b; + + s = g_build_filename(path, maskname, NULL); + if (XReadBitmapFileData(s, &w, &h, &b, &hx, &hy) == BitmapSuccess) { + ret = TRUE; + *value = RrPixmapMaskNew(inst, w, h, (gchar*)b); + XFree(b); + } + g_free(s); + + return ret; +} + +static void parse_appearance(gchar *tex, RrSurfaceColorType *grad, + RrReliefType *relief, RrBevelType *bevel, + gboolean *interlaced, gboolean *border, + gboolean allow_trans) +{ + gchar *t; + + /* convert to all lowercase */ + for (t = tex; *t != '\0'; ++t) + *t = g_ascii_tolower(*t); + + if (allow_trans && strstr(tex, "parentrelative") != NULL) { + *grad = RR_SURFACE_PARENTREL; + } else { + if (strstr(tex, "gradient") != NULL) { + if (strstr(tex, "crossdiagonal") != NULL) + *grad = RR_SURFACE_CROSS_DIAGONAL; + else if (strstr(tex, "pyramid") != NULL) + *grad = RR_SURFACE_PYRAMID; + else if (strstr(tex, "mirrorhorizontal") != NULL) + *grad = RR_SURFACE_MIRROR_HORIZONTAL; + else if (strstr(tex, "horizontal") != NULL) + *grad = RR_SURFACE_HORIZONTAL; + else if (strstr(tex, "splitvertical") != NULL) + *grad = RR_SURFACE_SPLIT_VERTICAL; + else if (strstr(tex, "vertical") != NULL) + *grad = RR_SURFACE_VERTICAL; + else + *grad = RR_SURFACE_DIAGONAL; + } else { + *grad = RR_SURFACE_SOLID; + } + } + + if (strstr(tex, "sunken") != NULL) + *relief = RR_RELIEF_SUNKEN; + else if (strstr(tex, "flat") != NULL) + *relief = RR_RELIEF_FLAT; + else if (strstr(tex, "raised") != NULL) + *relief = RR_RELIEF_RAISED; + else + *relief = (*grad == RR_SURFACE_PARENTREL) ? + RR_RELIEF_FLAT : RR_RELIEF_RAISED; + + *border = FALSE; + if (*relief == RR_RELIEF_FLAT) { + if (strstr(tex, "border") != NULL) + *border = TRUE; + } else { + if (strstr(tex, "bevel2") != NULL) + *bevel = RR_BEVEL_2; + else + *bevel = RR_BEVEL_1; + } + + if (strstr(tex, "interlaced") != NULL) + *interlaced = TRUE; + else + *interlaced = FALSE; +} + +static gboolean read_appearance(XrmDatabase db, const RrInstance *inst, + const gchar *rname, RrAppearance *value, + gboolean allow_trans) +{ + gboolean ret = FALSE; + gchar *rclass = create_class_name(rname); + gchar *cname, *ctoname, *bcname, *icname, *hname, *sname; + gchar *csplitname, *ctosplitname; + gchar *rettype; + XrmValue retvalue; + gint i; + + cname = g_strconcat(rname, ".color", NULL); + ctoname = g_strconcat(rname, ".colorTo", NULL); + bcname = g_strconcat(rname, ".border.color", NULL); + icname = g_strconcat(rname, ".interlace.color", NULL); + hname = g_strconcat(rname, ".highlight", NULL); + sname = g_strconcat(rname, ".shadow", NULL); + csplitname = g_strconcat(rname, ".color.splitTo", NULL); + ctosplitname = g_strconcat(rname, ".colorTo.splitTo", NULL); + + if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) && + retvalue.addr != NULL) { + parse_appearance(retvalue.addr, + &value->surface.grad, + &value->surface.relief, + &value->surface.bevel, + &value->surface.interlaced, + &value->surface.border, + allow_trans); + if (!read_color(db, inst, cname, &value->surface.primary)) + value->surface.primary = RrColorNew(inst, 0, 0, 0); + if (!read_color(db, inst, ctoname, &value->surface.secondary)) + value->surface.secondary = RrColorNew(inst, 0, 0, 0); + if (value->surface.border) + if (!read_color(db, inst, bcname, + &value->surface.border_color)) + value->surface.border_color = RrColorNew(inst, 0, 0, 0); + if (value->surface.interlaced) + if (!read_color(db, inst, icname, + &value->surface.interlace_color)) + value->surface.interlace_color = RrColorNew(inst, 0, 0, 0); + if (read_int(db, hname, &i) && i >= 0) + value->surface.bevel_light_adjust = i; + if (read_int(db, sname, &i) && i >= 0 && i <= 256) + value->surface.bevel_dark_adjust = i; + + if (value->surface.grad == RR_SURFACE_SPLIT_VERTICAL) { + gint r, g, b; + + if (!read_color(db, inst, csplitname, + &value->surface.split_primary)) + { + r = value->surface.primary->r; + r += r >> 2; + g = value->surface.primary->g; + g += g >> 2; + b = value->surface.primary->b; + b += b >> 2; + if (r > 0xFF) r = 0xFF; + if (g > 0xFF) g = 0xFF; + if (b > 0xFF) b = 0xFF; + value->surface.split_primary = RrColorNew(inst, r, g, b); + } + + if (!read_color(db, inst, ctosplitname, + &value->surface.split_secondary)) + { + r = value->surface.secondary->r; + r += r >> 4; + g = value->surface.secondary->g; + g += g >> 4; + b = value->surface.secondary->b; + b += b >> 4; + if (r > 0xFF) r = 0xFF; + if (g > 0xFF) g = 0xFF; + if (b > 0xFF) b = 0xFF; + value->surface.split_secondary = RrColorNew(inst, r, g, b); + } + } + + ret = TRUE; + } + + g_free(ctosplitname); + g_free(csplitname); + g_free(sname); + g_free(hname); + g_free(icname); + g_free(bcname); + g_free(ctoname); + g_free(cname); + g_free(rclass); + return ret; +} + +static int parse_inline_number(const char *p) +{ + int neg = 1; + int res = 0; + if (*p == '-') { + neg = -1; + ++p; + } + for (; isdigit(*p); ++p) + res = res * 10 + *p - '0'; + res *= neg; + return res; +} + +static void set_default_appearance(RrAppearance *a) +{ + a->surface.grad = RR_SURFACE_SOLID; + a->surface.relief = RR_RELIEF_FLAT; + a->surface.bevel = RR_BEVEL_1; + a->surface.interlaced = FALSE; + a->surface.border = FALSE; + a->surface.primary = RrColorNew(a->inst, 0, 0, 0); + a->surface.secondary = RrColorNew(a->inst, 0, 0, 0); +} + +/* Reads the output from gimp's C-Source file format into valid RGBA data for + an RrTextureRGBA. */ +static RrPixel32* read_c_image(gint width, gint height, const guint8 *data) +{ + RrPixel32 *im, *p; + gint i; + + p = im = g_memdup(data, width * height * sizeof(RrPixel32)); + + for (i = 0; i < width * height; ++i) { + guchar a = ((*p >> 24) & 0xff); + guchar b = ((*p >> 16) & 0xff); + guchar g = ((*p >> 8) & 0xff); + guchar r = ((*p >> 0) & 0xff); + + *p = ((r << RrDefaultRedOffset) + + (g << RrDefaultGreenOffset) + + (b << RrDefaultBlueOffset) + + (a << RrDefaultAlphaOffset)); + p++; + } + + return im; +} diff --git a/obrender/theme.h b/obrender/theme.h new file mode 100644 index 00000000..3f9063e6 --- /dev/null +++ b/obrender/theme.h @@ -0,0 +1,266 @@ +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + theme.h for the Openbox window manager + Copyright (c) 2006 Mikael Magnusson + Copyright (c) 2003-2007 Dana Jansens + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + See the COPYING file for a copy of the GNU General Public License. +*/ + +#ifndef __theme_h +#define __theme_h + +#include "render.h" + +G_BEGIN_DECLS + +typedef struct _RrTheme RrTheme; + +struct _RrTheme { + const RrInstance *inst; + + /* style settings - fonts */ + RrFont *win_font_focused; + RrFont *win_font_unfocused; + RrFont *menu_title_font; + RrFont *menu_font; + RrFont *osd_font_hilite; + RrFont *osd_font_unhilite; + + /* style settings - geometry */ + gint paddingx; + gint paddingy; + gint handle_height; + gint fbwidth; /*!< frame border width */ + gint mbwidth; /*!< menu border width */ + gint obwidth; /*!< osd border width */ + gint cbwidthx; + gint cbwidthy; + gint menu_overlap_x; + gint menu_overlap_y; + gint menu_sep_width; + gint menu_sep_paddingx; + gint menu_sep_paddingy; + /* these ones are calculated, not set directly by the theme file */ + gint win_font_height; + gint menu_title_font_height; + gint menu_font_height; + gint label_height; + gint title_height; + gint button_size; + gint grip_width; + gint menu_title_label_height; + gint menu_title_height; + + /* style settings - colors */ + RrColor *menu_border_color; + RrColor *osd_border_color; + RrColor *frame_focused_border_color; + RrColor *frame_unfocused_border_color; + RrColor *title_separator_focused_color; + RrColor *title_separator_unfocused_color; + RrColor *cb_focused_color; + RrColor *cb_unfocused_color; + RrColor *title_focused_color; + RrColor *title_unfocused_color; + RrColor *titlebut_disabled_focused_color; + RrColor *titlebut_disabled_unfocused_color; + RrColor *titlebut_hover_focused_color; + RrColor *titlebut_hover_unfocused_color; + RrColor *titlebut_toggled_hover_focused_color; + RrColor *titlebut_toggled_hover_unfocused_color; + RrColor *titlebut_toggled_focused_pressed_color; + RrColor *titlebut_toggled_unfocused_pressed_color; + RrColor *titlebut_toggled_focused_unpressed_color; + RrColor *titlebut_toggled_unfocused_unpressed_color; + RrColor *titlebut_focused_pressed_color; + RrColor *titlebut_unfocused_pressed_color; + RrColor *titlebut_focused_unpressed_color; + RrColor *titlebut_unfocused_unpressed_color; + RrColor *menu_title_color; + RrColor *menu_sep_color; + RrColor *menu_color; + RrColor *menu_selected_color; + RrColor *menu_disabled_color; + RrColor *menu_disabled_selected_color; + RrColor *title_focused_shadow_color; + gchar title_focused_shadow_alpha; + RrColor *title_unfocused_shadow_color; + gchar title_unfocused_shadow_alpha; + RrColor *osd_text_active_color; + RrColor *osd_text_inactive_color; + RrColor *osd_text_active_shadow_color; + RrColor *osd_text_inactive_shadow_color; + gchar osd_text_active_shadow_alpha; + gchar osd_text_inactive_shadow_alpha; + RrColor *menu_title_shadow_color; + gchar menu_title_shadow_alpha; + RrColor *menu_text_normal_shadow_color; + gchar menu_text_normal_shadow_alpha; + RrColor *menu_text_selected_shadow_color; + gchar menu_text_selected_shadow_alpha; + RrColor *menu_text_disabled_shadow_color; + gchar menu_text_disabled_shadow_alpha; + RrColor *menu_text_disabled_selected_shadow_color; + gchar menu_text_disabled_selected_shadow_alpha; + + /* style settings - pics */ + RrPixel32 *def_win_icon; /* RGBA */ + gint def_win_icon_w; + gint def_win_icon_h; + + /* style settings - masks */ + RrPixmapMask *max_mask; + RrPixmapMask *max_hover_mask; + RrPixmapMask *max_pressed_mask; + RrPixmapMask *max_toggled_mask; + RrPixmapMask *max_toggled_hover_mask; + RrPixmapMask *max_toggled_pressed_mask; + RrPixmapMask *max_disabled_mask; + RrPixmapMask *iconify_mask; + RrPixmapMask *iconify_hover_mask; + RrPixmapMask *iconify_pressed_mask; + RrPixmapMask *iconify_disabled_mask; + RrPixmapMask *desk_mask; + RrPixmapMask *desk_hover_mask; + RrPixmapMask *desk_pressed_mask; + RrPixmapMask *desk_toggled_mask; + RrPixmapMask *desk_toggled_hover_mask; + RrPixmapMask *desk_toggled_pressed_mask; + RrPixmapMask *desk_disabled_mask; + RrPixmapMask *shade_mask; + RrPixmapMask *shade_hover_mask; + RrPixmapMask *shade_pressed_mask; + RrPixmapMask *shade_toggled_mask; + RrPixmapMask *shade_toggled_hover_mask; + RrPixmapMask *shade_toggled_pressed_mask; + RrPixmapMask *shade_disabled_mask; + RrPixmapMask *close_mask; + RrPixmapMask *close_hover_mask; + RrPixmapMask *close_disabled_mask; + RrPixmapMask *close_pressed_mask; + + RrPixmapMask *menu_bullet_mask; /* submenu pointer */ +#if 0 + RrPixmapMask *menu_toggle_mask; /* menu boolean */ +#endif + + RrPixmapMask *down_arrow_mask; + RrPixmapMask *up_arrow_mask; + + /* global appearances */ + RrAppearance *a_disabled_focused_max; + RrAppearance *a_disabled_unfocused_max; + RrAppearance *a_hover_focused_max; + RrAppearance *a_hover_unfocused_max; + RrAppearance *a_focused_unpressed_max; + RrAppearance *a_focused_pressed_max; + RrAppearance *a_unfocused_unpressed_max; + RrAppearance *a_unfocused_pressed_max; + RrAppearance *a_toggled_hover_focused_max; + RrAppearance *a_toggled_hover_unfocused_max; + RrAppearance *a_toggled_focused_unpressed_max; + RrAppearance *a_toggled_focused_pressed_max; + RrAppearance *a_toggled_unfocused_unpressed_max; + RrAppearance *a_toggled_unfocused_pressed_max; + RrAppearance *a_disabled_focused_close; + RrAppearance *a_disabled_unfocused_close; + RrAppearance *a_hover_focused_close; + RrAppearance *a_hover_unfocused_close; + RrAppearance *a_focused_unpressed_close; + RrAppearance *a_focused_pressed_close; + RrAppearance *a_unfocused_unpressed_close; + RrAppearance *a_unfocused_pressed_close; + RrAppearance *a_disabled_focused_desk; + RrAppearance *a_disabled_unfocused_desk; + RrAppearance *a_hover_focused_desk; + RrAppearance *a_hover_unfocused_desk; + RrAppearance *a_focused_unpressed_desk; + RrAppearance *a_focused_pressed_desk; + RrAppearance *a_unfocused_unpressed_desk; + RrAppearance *a_unfocused_pressed_desk; + RrAppearance *a_toggled_hover_focused_desk; + RrAppearance *a_toggled_hover_unfocused_desk; + RrAppearance *a_toggled_focused_unpressed_desk; + RrAppearance *a_toggled_focused_pressed_desk; + RrAppearance *a_toggled_unfocused_unpressed_desk; + RrAppearance *a_toggled_unfocused_pressed_desk; + RrAppearance *a_disabled_focused_shade; + RrAppearance *a_disabled_unfocused_shade; + RrAppearance *a_hover_focused_shade; + RrAppearance *a_hover_unfocused_shade; + RrAppearance *a_focused_unpressed_shade; + RrAppearance *a_focused_pressed_shade; + RrAppearance *a_unfocused_unpressed_shade; + RrAppearance *a_unfocused_pressed_shade; + RrAppearance *a_toggled_hover_focused_shade; + RrAppearance *a_toggled_hover_unfocused_shade; + RrAppearance *a_toggled_focused_unpressed_shade; + RrAppearance *a_toggled_focused_pressed_shade; + RrAppearance *a_toggled_unfocused_unpressed_shade; + RrAppearance *a_toggled_unfocused_pressed_shade; + RrAppearance *a_disabled_focused_iconify; + RrAppearance *a_disabled_unfocused_iconify; + RrAppearance *a_hover_focused_iconify; + RrAppearance *a_hover_unfocused_iconify; + RrAppearance *a_focused_unpressed_iconify; + RrAppearance *a_focused_pressed_iconify; + RrAppearance *a_unfocused_unpressed_iconify; + RrAppearance *a_unfocused_pressed_iconify; + RrAppearance *a_focused_grip; + RrAppearance *a_unfocused_grip; + RrAppearance *a_focused_title; + RrAppearance *a_unfocused_title; + RrAppearance *a_focused_label; + RrAppearance *a_unfocused_label; + /* always parentrelative, so no focused/unfocused */ + RrAppearance *a_icon; + RrAppearance *a_focused_handle; + RrAppearance *a_unfocused_handle; + RrAppearance *a_menu_text_title; + RrAppearance *a_menu_title; + RrAppearance *a_menu; + RrAppearance *a_menu_normal; + RrAppearance *a_menu_selected; + RrAppearance *a_menu_disabled; + RrAppearance *a_menu_disabled_selected; + RrAppearance *a_menu_text_normal; + RrAppearance *a_menu_text_disabled; + RrAppearance *a_menu_text_disabled_selected; + RrAppearance *a_menu_text_selected; + RrAppearance *a_menu_bullet_normal; + RrAppearance *a_menu_bullet_selected; + RrAppearance *a_clear; /* clear with no texture */ + RrAppearance *a_clear_tex; /* clear with a texture */ + + RrAppearance *osd_bg; /* can never be parent relative */ + RrAppearance *osd_hilite_bg; /* can never be parent relative */ + RrAppearance *osd_hilite_label; /* can be parent relative */ + RrAppearance *osd_unhilite_bg; /* can never be parent relative */ + RrAppearance *osd_unhilite_label; /* can be parent relative */ + + gchar *name; +}; + +/*! The font values are all optional. If a NULL is used for any of them, then + the default font will be used. */ +RrTheme* RrThemeNew(const RrInstance *inst, const gchar *theme, + gboolean allow_fallback, + RrFont *active_window_font, RrFont *inactive_window_font, + RrFont *menu_title_font, RrFont *menu_item_font, + RrFont *active_osd_font, RrFont *inactive_osd_font); +void RrThemeFree(RrTheme *theme); + +G_END_DECLS + +#endif diff --git a/obrender/version.h.in b/obrender/version.h.in new file mode 100644 index 00000000..0ff30b57 --- /dev/null +++ b/obrender/version.h.in @@ -0,0 +1,15 @@ +#ifndef rr__version_h +#define rr__version_h + +#define RR_MAJOR_VERSION @RR_MAJOR_VERSION@ +#define RR_MINOR_VERSION @RR_MINOR_VERSION@ +#define RR_MICRO_VERSION @RR_MICRO_VERSION@ +#define RR_VERSION RR_MAJOR_VERSION.RR_MINOR_VERSION.RR_MICRO_VERSION + +#define RR_CHECK_VERSION(major,minor,micro) \ + (RR_MAJOR_VERSION > (major) || \ + (RR_MAJOR_VERSION == (major) && RR_MINOR_VERSION > (minor)) || \ + (RR_MAJOR_VERSION == (major) && RR_MINOR_VERSION == (minor) && \ + RR_MICRO_VERSION >= (micro))) + +#endif diff --git a/obt/obt-3.5.pc.in b/obt/obt-3.5.pc.in new file mode 100644 index 00000000..840de161 --- /dev/null +++ b/obt/obt-3.5.pc.in @@ -0,0 +1,14 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +xcflags=@X_CFLAGS@ +xlibs=@X_LIBS@ + +Name: Obt +Description: Openbox Toolkit Library +Version: @OBT_VERSION@ +Requires: glib-2.0 +Libs: -L${libdir} -lobrender ${xlibs} +Cflags: -I${includedir}/openbox/@OBT_VERSION@ ${xcflags} diff --git a/obt/obt-4.0.pc.in b/obt/obt-4.0.pc.in deleted file mode 100644 index 840de161..00000000 --- a/obt/obt-4.0.pc.in +++ /dev/null @@ -1,14 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -xcflags=@X_CFLAGS@ -xlibs=@X_LIBS@ - -Name: Obt -Description: Openbox Toolkit Library -Version: @OBT_VERSION@ -Requires: glib-2.0 -Libs: -L${libdir} -lobrender ${xlibs} -Cflags: -I${includedir}/openbox/@OBT_VERSION@ ${xcflags} diff --git a/openbox/client.c b/openbox/client.c index 184ae171..4d8f4e77 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -38,7 +38,7 @@ #include "menuframe.h" #include "keyboard.h" #include "mouse.h" -#include "render/render.h" +#include "obrender/render.h" #include "gettext.h" #include "obt/display.h" #include "obt/prop.h" diff --git a/openbox/client.h b/openbox/client.h index 8126abe2..a361e367 100644 --- a/openbox/client.h +++ b/openbox/client.h @@ -25,7 +25,7 @@ #include "geom.h" #include "stacking.h" #include "window.h" -#include "render/color.h" +#include "obrender/color.h" #include #include diff --git a/openbox/config.h b/openbox/config.h index 11796dcb..5c18ad3a 100644 --- a/openbox/config.h +++ b/openbox/config.h @@ -26,7 +26,7 @@ #include "client.h" #include "geom.h" #include "moveresize.h" -#include "render/render.h" +#include "obrender/render.h" #include "obt/parse.h" #include diff --git a/openbox/dock.c b/openbox/dock.c index ce2dafb8..d1f6b294 100644 --- a/openbox/dock.c +++ b/openbox/dock.c @@ -23,7 +23,7 @@ #include "config.h" #include "grab.h" #include "openbox.h" -#include "render/theme.h" +#include "obrender/theme.h" #include "obt/prop.h" #define DOCK_EVENT_MASK (ButtonPressMask | ButtonReleaseMask | \ diff --git a/openbox/dock.h b/openbox/dock.h index 3463f27b..8bc735ee 100644 --- a/openbox/dock.h +++ b/openbox/dock.h @@ -22,7 +22,7 @@ #include "window.h" #include "stacking.h" #include "geom.h" -#include "render/render.h" +#include "obrender/render.h" #include #include diff --git a/openbox/focus_cycle_indicator.c b/openbox/focus_cycle_indicator.c index 5d7ecb3d..89527903 100644 --- a/openbox/focus_cycle_indicator.c +++ b/openbox/focus_cycle_indicator.c @@ -23,7 +23,7 @@ #include "openbox.h" #include "frame.h" #include "event.h" -#include "render/render.h" +#include "obrender/render.h" #include #include diff --git a/openbox/focus_cycle_popup.c b/openbox/focus_cycle_popup.c index 0f9bd752..4f697fdd 100644 --- a/openbox/focus_cycle_popup.c +++ b/openbox/focus_cycle_popup.c @@ -26,7 +26,7 @@ #include "config.h" #include "window.h" #include "event.h" -#include "render/render.h" +#include "obrender/render.h" #include #include diff --git a/openbox/frame.c b/openbox/frame.c index 6387d7ef..084f3f6a 100644 --- a/openbox/frame.c +++ b/openbox/frame.c @@ -28,7 +28,7 @@ #include "focus_cycle_indicator.h" #include "moveresize.h" #include "screen.h" -#include "render/theme.h" +#include "obrender/theme.h" #include "obt/display.h" #include "obt/prop.h" diff --git a/openbox/frame.h b/openbox/frame.h index 8687381d..1130709b 100644 --- a/openbox/frame.h +++ b/openbox/frame.h @@ -21,7 +21,7 @@ #define __frame_h #include "geom.h" -#include "render/render.h" +#include "obrender/render.h" typedef struct _ObFrame ObFrame; diff --git a/openbox/framerender.c b/openbox/framerender.c index bf71d2c3..28c12ae2 100644 --- a/openbox/framerender.c +++ b/openbox/framerender.c @@ -22,7 +22,7 @@ #include "screen.h" #include "client.h" #include "framerender.h" -#include "render/theme.h" +#include "obrender/theme.h" static void framerender_label(ObFrame *self, RrAppearance *a); static void framerender_icon(ObFrame *self, RrAppearance *a); diff --git a/openbox/menu.h b/openbox/menu.h index 43efd413..16cf4291 100644 --- a/openbox/menu.h +++ b/openbox/menu.h @@ -21,7 +21,7 @@ #include "window.h" #include "geom.h" -#include "render/render.h" +#include "obrender/render.h" #include diff --git a/openbox/menuframe.c b/openbox/menuframe.c index 999dddf1..ee374de5 100644 --- a/openbox/menuframe.c +++ b/openbox/menuframe.c @@ -27,7 +27,7 @@ #include "openbox.h" #include "config.h" #include "obt/prop.h" -#include "render/theme.h" +#include "obrender/theme.h" #define PADDING 2 #define MAX_MENU_WIDTH 400 diff --git a/openbox/menuframe.h b/openbox/menuframe.h index f6a7b30e..87a718e7 100644 --- a/openbox/menuframe.h +++ b/openbox/menuframe.h @@ -22,7 +22,7 @@ #include "geom.h" #include "window.h" -#include "render/render.h" +#include "obrender/render.h" #include diff --git a/openbox/moveresize.c b/openbox/moveresize.c index 5db79f9f..99222577 100644 --- a/openbox/moveresize.c +++ b/openbox/moveresize.c @@ -29,8 +29,8 @@ #include "config.h" #include "event.h" #include "debug.h" -#include "render/render.h" -#include "render/theme.h" +#include "obrender/render.h" +#include "obrender/theme.h" #include "obt/display.h" #include "obt/prop.h" #include "obt/keyboard.h" diff --git a/openbox/openbox.c b/openbox/openbox.c index 5f926bb6..c597d23f 100644 --- a/openbox/openbox.c +++ b/openbox/openbox.c @@ -43,8 +43,8 @@ #include "ping.h" #include "prompt.h" #include "gettext.h" -#include "render/render.h" -#include "render/theme.h" +#include "obrender/render.h" +#include "obrender/theme.h" #include "obt/display.h" #include "obt/prop.h" #include "obt/keyboard.h" diff --git a/openbox/openbox.h b/openbox/openbox.h index b0529219..c43f0a61 100644 --- a/openbox/openbox.h +++ b/openbox/openbox.h @@ -21,8 +21,8 @@ #include "misc.h" -#include "render/render.h" -#include "render/theme.h" +#include "obrender/render.h" +#include "obrender/theme.h" #include "obt/mainloop.h" #include "obt/display.h" diff --git a/openbox/popup.c b/openbox/popup.c index a4192819..90ec32de 100644 --- a/openbox/popup.c +++ b/openbox/popup.c @@ -25,8 +25,8 @@ #include "stacking.h" #include "event.h" #include "screen.h" -#include "render/render.h" -#include "render/theme.h" +#include "obrender/render.h" +#include "obrender/theme.h" ObPopup *popup_new(void) { diff --git a/openbox/popup.h b/openbox/popup.h index 503e2773..f876e3ce 100644 --- a/openbox/popup.h +++ b/openbox/popup.h @@ -20,7 +20,7 @@ #define __popup_h #include "window.h" -#include "render/render.h" +#include "obrender/render.h" #include struct _ObClientIcon; diff --git a/openbox/prompt.h b/openbox/prompt.h index d07793a9..0d7cfef8 100644 --- a/openbox/prompt.h +++ b/openbox/prompt.h @@ -21,7 +21,7 @@ #include "window.h" #include "geom.h" -#include "render/render.h" +#include "obrender/render.h" #include #include diff --git a/openbox/screen.c b/openbox/screen.c index bb98e084..bce2faaf 100644 --- a/openbox/screen.c +++ b/openbox/screen.c @@ -32,7 +32,7 @@ #include "focus.h" #include "focus_cycle.h" #include "popup.h" -#include "render/render.h" +#include "obrender/render.h" #include "gettext.h" #include "obt/display.h" #include "obt/prop.h" diff --git a/render/Makefile b/render/Makefile deleted file mode 100644 index b90edacf..00000000 --- a/render/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -all clean install: - $(MAKE) -C .. -$(MAKEFLAGS) $@ - -.PHONY: all clean install diff --git a/render/color.c b/render/color.c deleted file mode 100644 index 5e3f2169..00000000 --- a/render/color.c +++ /dev/null @@ -1,361 +0,0 @@ -/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- - - color.c for the Openbox window manager - Copyright (c) 2006 Mikael Magnusson - Copyright (c) 2003-2007 Dana Jansens - Copyright (c) 2003 Derek Foreman - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - See the COPYING file for a copy of the GNU General Public License. -*/ - -#include "render.h" -#include "color.h" -#include "instance.h" - -#include -#include -#include - -void RrColorAllocateGC(RrColor *in) -{ - XGCValues gcv; - - gcv.foreground = in->pixel; - gcv.cap_style = CapProjecting; - in->gc = XCreateGC(RrDisplay(in->inst), - RrRootWindow(in->inst), - GCForeground | GCCapStyle, &gcv); -} - -RrColor *RrColorParse(const RrInstance *inst, gchar *colorname) -{ - XColor xcol; - - g_assert(colorname != NULL); - /* get rgb values from colorname */ - - xcol.red = 0; - xcol.green = 0; - xcol.blue = 0; - xcol.pixel = 0; - if (!XParseColor(RrDisplay(inst), RrColormap(inst), colorname, &xcol)) { - g_message("Unable to parse color '%s'", colorname); - return NULL; - } - return RrColorNew(inst, xcol.red >> 8, xcol.green >> 8, xcol.blue >> 8); -} - -/*#define NO_COLOR_CACHE*/ -#ifdef DEBUG -gint id; -#endif - -RrColor *RrColorNew(const RrInstance *inst, gint r, gint g, gint b) -{ - /* this should be replaced with something far cooler */ - RrColor *out = NULL; - XColor xcol; - gint key; - - g_assert(r >= 0 && r < 256); - g_assert(g >= 0 && g < 256); - g_assert(b >= 0 && b < 256); - - key = (r << 24) + (g << 16) + (b << 8); -#ifndef NO_COLOR_CACHE - if ((out = g_hash_table_lookup(RrColorHash(inst), &key))) { - out->refcount++; - } else { -#endif - xcol.red = (r << 8) | r; - xcol.green = (g << 8) | g; - xcol.blue = (b << 8) | b; - if (XAllocColor(RrDisplay(inst), RrColormap(inst), &xcol)) { - out = g_new(RrColor, 1); - out->inst = inst; - out->r = xcol.red >> 8; - out->g = xcol.green >> 8; - out->b = xcol.blue >> 8; - out->gc = None; - out->pixel = xcol.pixel; - out->key = key; - out->refcount = 1; -#ifdef DEBUG - out->id = id++; -#endif -#ifndef NO_COLOR_CACHE - g_hash_table_insert(RrColorHash(inst), &out->key, out); - } -#endif - } - return out; -} - -void RrColorFree(RrColor *c) -{ - if (c) { - if (--c->refcount < 1) { -#ifndef NO_COLOR_CACHE - g_assert(g_hash_table_lookup(RrColorHash(c->inst), &c->key)); - g_hash_table_remove(RrColorHash(c->inst), &c->key); -#endif - if (c->pixel) XFreeColors(RrDisplay(c->inst), RrColormap(c->inst), - &c->pixel, 1, 0); - if (c->gc) XFreeGC(RrDisplay(c->inst), c->gc); - g_free(c); - } - } -} - -void RrReduceDepth(const RrInstance *inst, RrPixel32 *data, XImage *im) -{ - gint r, g, b; - gint x,y; - RrPixel32 *p32 = (RrPixel32 *) im->data; - RrPixel16 *p16 = (RrPixel16 *) im->data; - RrPixel8 *p8 = (RrPixel8 *) im->data; - switch (im->bits_per_pixel) { - case 32: - if ((RrRedOffset(inst) != RrDefaultRedOffset) || - (RrBlueOffset(inst) != RrDefaultBlueOffset) || - (RrGreenOffset(inst) != RrDefaultGreenOffset)) { - for (y = 0; y < im->height; y++) { - for (x = 0; x < im->width; x++) { - r = (data[x] >> RrDefaultRedOffset) & 0xFF; - g = (data[x] >> RrDefaultGreenOffset) & 0xFF; - b = (data[x] >> RrDefaultBlueOffset) & 0xFF; - p32[x] = (r << RrRedOffset(inst)) - + (g << RrGreenOffset(inst)) - + (b << RrBlueOffset(inst)); - } - data += im->width; - p32 += im->width; - } - } else im->data = (gchar*) data; - break; - case 24: - { - /* reverse the ordering, shifting left 16bit should be the first byte - out of three, etc */ - const guint roff = (16 - RrRedOffset(inst)) / 8; - const guint goff = (16 - RrGreenOffset(inst)) / 8; - const guint boff = (16 - RrBlueOffset(inst)) / 8; - gint outx; - for (y = 0; y < im->height; y++) { - for (x = 0, outx = 0; x < im->width; x++, outx += 3) { - r = (data[x] >> RrDefaultRedOffset) & 0xFF; - g = (data[x] >> RrDefaultGreenOffset) & 0xFF; - b = (data[x] >> RrDefaultBlueOffset) & 0xFF; - p8[outx+roff] = r; - p8[outx+goff] = g; - p8[outx+boff] = b; - } - data += im->width; - p8 += im->bytes_per_line; - } - break; - } - case 16: - for (y = 0; y < im->height; y++) { - for (x = 0; x < im->width; x++) { - r = (data[x] >> RrDefaultRedOffset) & 0xFF; - r = r >> RrRedShift(inst); - g = (data[x] >> RrDefaultGreenOffset) & 0xFF; - g = g >> RrGreenShift(inst); - b = (data[x] >> RrDefaultBlueOffset) & 0xFF; - b = b >> RrBlueShift(inst); - p16[x] = (r << RrRedOffset(inst)) - + (g << RrGreenOffset(inst)) - + (b << RrBlueOffset(inst)); - } - data += im->width; - p16 += im->bytes_per_line/2; - } - break; - case 8: - if (RrVisual(inst)->class == TrueColor) { - for (y = 0; y < im->height; y++) { - for (x = 0; x < im->width; x++) { - r = (data[x] >> RrDefaultRedOffset) & 0xFF; - r = r >> RrRedShift(inst); - g = (data[x] >> RrDefaultGreenOffset) & 0xFF; - g = g >> RrGreenShift(inst); - b = (data[x] >> RrDefaultBlueOffset) & 0xFF; - b = b >> RrBlueShift(inst); - p8[x] = (r << RrRedOffset(inst)) - + (g << RrGreenOffset(inst)) - + (b << RrBlueOffset(inst)); - } - data += im->width; - p8 += im->bytes_per_line; - } - } else { - for (y = 0; y < im->height; y++) { - for (x = 0; x < im->width; x++) { - p8[x] = RrPickColor(inst, - data[x] >> RrDefaultRedOffset, - data[x] >> RrDefaultGreenOffset, - data[x] >> RrDefaultBlueOffset)->pixel; - } - data += im->width; - p8 += im->bytes_per_line; - } - } - break; - default: - g_error("This image bit depth (%i) is currently unhandled", im->bits_per_pixel); - - } -} - -XColor *RrPickColor(const RrInstance *inst, gint r, gint g, gint b) -{ - r = (r & 0xff) >> (8-RrPseudoBPC(inst)); - g = (g & 0xff) >> (8-RrPseudoBPC(inst)); - b = (b & 0xff) >> (8-RrPseudoBPC(inst)); - return &RrPseudoColors(inst)[(r << (2*RrPseudoBPC(inst))) + - (g << (1*RrPseudoBPC(inst))) + - b]; -} - -static void swap_byte_order(XImage *im) -{ - gint x, y, di; - - di = 0; - for (y = 0; y < im->height; ++y) { - for (x = 0; x < im->height; ++x) { - gchar *c = &im->data[di + x * im->bits_per_pixel / 8]; - gchar t; - - switch (im->bits_per_pixel) { - case 32: - t = c[2]; - c[2] = c[3]; - c[3] = t; - case 16: - t = c[0]; - c[0] = c[1]; - c[1] = t; - case 8: - case 1: - break; - default: - g_error("Your bit depth (%i) is currently unhandled", - im->bits_per_pixel); - } - } - di += im->bytes_per_line; - } - - if (im->byte_order == LSBFirst) - im->byte_order = MSBFirst; - else - im->byte_order = LSBFirst; -} - -void RrIncreaseDepth(const RrInstance *inst, RrPixel32 *data, XImage *im) -{ - gint r, g, b; - gint x,y; - RrPixel32 *p32 = (RrPixel32 *) im->data; - RrPixel16 *p16 = (RrPixel16 *) im->data; - guchar *p8 = (guchar *)im->data; - - if (im->byte_order != LSBFirst) - swap_byte_order(im); - - switch (im->bits_per_pixel) { - case 32: - for (y = 0; y < im->height; y++) { - for (x = 0; x < im->width; x++) { - r = (p32[x] >> RrRedOffset(inst)) & 0xff; - g = (p32[x] >> RrGreenOffset(inst)) & 0xff; - b = (p32[x] >> RrBlueOffset(inst)) & 0xff; - data[x] = (r << RrDefaultRedOffset) - + (g << RrDefaultGreenOffset) - + (b << RrDefaultBlueOffset) - + (0xff << RrDefaultAlphaOffset); - } - data += im->width; - p32 += im->bytes_per_line/4; - } - break; - case 16: - for (y = 0; y < im->height; y++) { - for (x = 0; x < im->width; x++) { - r = (p16[x] & RrRedMask(inst)) >> - RrRedOffset(inst) << - RrRedShift(inst); - g = (p16[x] & RrGreenMask(inst)) >> - RrGreenOffset(inst) << - RrGreenShift(inst); - b = (p16[x] & RrBlueMask(inst)) >> - RrBlueOffset(inst) << - RrBlueShift(inst); - data[x] = (r << RrDefaultRedOffset) - + (g << RrDefaultGreenOffset) - + (b << RrDefaultBlueOffset) - + (0xff << RrDefaultAlphaOffset); - } - data += im->width; - p16 += im->bytes_per_line/2; - } - break; - case 8: - g_error("This image bit depth (%i) is currently unhandled", 8); - break; - case 1: - for (y = 0; y < im->height; y++) { - for (x = 0; x < im->width; x++) { - if (!(((p8[x / 8]) >> (x % 8)) & 0x1)) - data[x] = 0xff << RrDefaultAlphaOffset; /* black */ - else - data[x] = 0xffffffff; /* white */ - } - data += im->width; - p8 += im->bytes_per_line; - } - break; - default: - g_error("This image bit depth (%i) is currently unhandled", - im->bits_per_pixel); - } -} - -gint RrColorRed(const RrColor *c) -{ - return c->r; -} - -gint RrColorGreen(const RrColor *c) -{ - return c->g; -} - -gint RrColorBlue(const RrColor *c) -{ - return c->b; -} - -gulong RrColorPixel(const RrColor *c) -{ - return c->pixel; -} - -GC RrColorGC(RrColor *c) -{ - if (!c->gc) - RrColorAllocateGC(c); - return c->gc; -} diff --git a/render/color.h b/render/color.h deleted file mode 100644 index 26fa7afe..00000000 --- a/render/color.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- - - color.h for the Openbox window manager - Copyright (c) 2003-2007 Dana Jansens - Copyright (c) 2003 Derek Foreman - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - See the COPYING file for a copy of the GNU General Public License. -*/ - -#ifndef __color_h -#define __color_h - -#include "render.h" - -#include -#include -#include - -struct _RrColor { - const RrInstance *inst; - - gint r; - gint g; - gint b; - gulong pixel; - GC gc; - - gint key; - gint refcount; - -#ifdef DEBUG - gint id; -#endif -}; - -void RrColorAllocateGC(RrColor *in); -XColor *RrPickColor(const RrInstance *inst, gint r, gint g, gint b); -void RrReduceDepth(const RrInstance *inst, RrPixel32 *data, XImage *im); -void RrIncreaseDepth(const RrInstance *inst, RrPixel32 *data, XImage *im); - -#endif /* __color_h */ diff --git a/render/font.c b/render/font.c deleted file mode 100644 index cde0d030..00000000 --- a/render/font.c +++ /dev/null @@ -1,380 +0,0 @@ -/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- - - font.c for the Openbox window manager - Copyright (c) 2006 Mikael Magnusson - Copyright (c) 2003-2007 Dana Jansens - Copyright (c) 2003 Derek Foreman - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - See the COPYING file for a copy of the GNU General Public License. -*/ - -#include "font.h" -#include "color.h" -#include "mask.h" -#include "theme.h" -#include "geom.h" -#include "instance.h" -#include "gettext.h" - -#include -#include -#include -#include - -static void measure_font(const RrInstance *inst, RrFont *f) -{ - PangoFontMetrics *metrics; - static PangoLanguage *lang = NULL; - - if (lang == NULL) { -#if PANGO_VERSION_MAJOR > 1 || \ - (PANGO_VERSION_MAJOR == 1 && PANGO_VERSION_MINOR >= 16) - lang = pango_language_get_default(); -#else - gchar *locale, *p; - /* get the default language from the locale - (based on gtk_get_default_language in gtkmain.c) */ - locale = g_strdup(setlocale(LC_CTYPE, NULL)); - if ((p = strchr(locale, '.'))) *p = '\0'; /* strip off the . */ - if ((p = strchr(locale, '@'))) *p = '\0'; /* strip off the @ */ - lang = pango_language_from_string(locale); - g_free(locale); -#endif - } - - /* measure the ascent and descent */ - metrics = pango_context_get_metrics(inst->pango, f->font_desc, lang); - f->ascent = pango_font_metrics_get_ascent(metrics); - f->descent = pango_font_metrics_get_descent(metrics); - pango_font_metrics_unref(metrics); - -} - -RrFont *RrFontOpen(const RrInstance *inst, const gchar *name, gint size, - RrFontWeight weight, RrFontSlant slant) -{ - RrFont *out; - PangoWeight pweight; - PangoStyle pstyle; - PangoAttrList *attrlist; - - out = g_new(RrFont, 1); - out->inst = inst; - out->ref = 1; - out->font_desc = pango_font_description_new(); - out->layout = pango_layout_new(inst->pango); - out->shortcut_underline = pango_attr_underline_new(PANGO_UNDERLINE_LOW); - out->shortcut_underline->start_index = 0; - out->shortcut_underline->end_index = 0; - - attrlist = pango_attr_list_new(); - /* shortcut_underline is owned by the attrlist */ - pango_attr_list_insert(attrlist, out->shortcut_underline); - /* the attributes are owned by the layout */ - pango_layout_set_attributes(out->layout, attrlist); - pango_attr_list_unref(attrlist); - - switch (weight) { - case RR_FONTWEIGHT_LIGHT: pweight = PANGO_WEIGHT_LIGHT; break; - case RR_FONTWEIGHT_NORMAL: pweight = PANGO_WEIGHT_NORMAL; break; - case RR_FONTWEIGHT_SEMIBOLD: pweight = PANGO_WEIGHT_SEMIBOLD; break; - case RR_FONTWEIGHT_BOLD: pweight = PANGO_WEIGHT_BOLD; break; - case RR_FONTWEIGHT_ULTRABOLD: pweight = PANGO_WEIGHT_ULTRABOLD; break; - default: g_assert_not_reached(); - } - - switch (slant) { - case RR_FONTSLANT_NORMAL: pstyle = PANGO_STYLE_NORMAL; break; - case RR_FONTSLANT_ITALIC: pstyle = PANGO_STYLE_ITALIC; break; - case RR_FONTSLANT_OBLIQUE: pstyle = PANGO_STYLE_OBLIQUE; break; - default: g_assert_not_reached(); - } - - /* setup the font */ - pango_font_description_set_family(out->font_desc, name); - pango_font_description_set_weight(out->font_desc, pweight); - pango_font_description_set_style(out->font_desc, pstyle); - pango_font_description_set_size(out->font_desc, size * PANGO_SCALE); - - /* setup the layout */ - pango_layout_set_font_description(out->layout, out->font_desc); - pango_layout_set_wrap(out->layout, PANGO_WRAP_WORD_CHAR); - - /* get the ascent and descent */ - measure_font(inst, out); - - return out; -} - -RrFont *RrFontOpenDefault(const RrInstance *inst) -{ - return RrFontOpen(inst, RrDefaultFontFamily, RrDefaultFontSize, - RrDefaultFontWeight, RrDefaultFontSlant); -} - -void RrFontRef(RrFont *f) -{ - ++f->ref; -} - -void RrFontClose(RrFont *f) -{ - if (f) { - if (--f->ref < 1) { - g_object_unref(f->layout); - pango_font_description_free(f->font_desc); - g_free(f); - } - } -} - -static void font_measure_full(const RrFont *f, const gchar *str, - gint *x, gint *y, gint shadow_x, gint shadow_y, - gboolean flow, gint maxwidth) -{ - PangoRectangle rect; - - pango_layout_set_text(f->layout, str, -1); - if (flow) { - pango_layout_set_single_paragraph_mode(f->layout, FALSE); - pango_layout_set_width(f->layout, maxwidth * PANGO_SCALE); - pango_layout_set_ellipsize(f->layout, PANGO_ELLIPSIZE_NONE); - } - else { - /* single line mode */ - pango_layout_set_single_paragraph_mode(f->layout, TRUE); - pango_layout_set_width(f->layout, -1); - pango_layout_set_ellipsize(f->layout, PANGO_ELLIPSIZE_MIDDLE); - } - - /* pango_layout_get_pixel_extents lies! this is the right way to get the - size of the text's area */ - pango_layout_get_extents(f->layout, NULL, &rect); -#if PANGO_VERSION_MAJOR > 1 || \ - (PANGO_VERSION_MAJOR == 1 && PANGO_VERSION_MINOR >= 16) - /* pass the logical rect as the ink rect, this is on purpose so we get the - full area for the text */ - pango_extents_to_pixels(&rect, NULL); -#else - rect.width = (rect.width + PANGO_SCALE - 1) / PANGO_SCALE; - rect.height = (rect.height + PANGO_SCALE - 1) / PANGO_SCALE; -#endif - *x = rect.width + ABS(shadow_x) + 4 /* we put a 2 px edge on each side */; - *y = rect.height + ABS(shadow_y); -} - -RrSize *RrFontMeasureString(const RrFont *f, const gchar *str, - gint shadow_x, gint shadow_y, - gboolean flow, gint maxwidth) -{ - RrSize *size; - - g_assert(!flow || maxwidth > 0); - - size = g_new(RrSize, 1); - font_measure_full(f, str, &size->width, &size->height, shadow_x, shadow_y, - flow, maxwidth); - return size; -} - -gint RrFontHeight(const RrFont *f, gint shadow_y) -{ - return (f->ascent + f->descent) / PANGO_SCALE + ABS(shadow_y); -} - -static inline int font_calculate_baseline(RrFont *f, gint height) -{ -/* For my own reference: - * _________ - * ^space/2 ^height ^baseline - * v_________|_ | - * | ^ascent | _ _ - * | | | | |_ _____ _| |_ _ _ - * | | | | _/ -_) \ / _| || | - * | v_________v \__\___/_\_\\__|\_, | - * | ^descent |__/ - * __________|_v - * ^space/2 | - * V_________v - */ - return (((height * PANGO_SCALE) /* height of the space in pango units */ - - (f->ascent + f->descent)) /* minus space taken up by text */ - / 2 /* divided by two -> half of the empty space (this is the top - of the text) */ - + f->ascent) /* now move down to the baseline */ - / PANGO_SCALE; /* back to pixels */ -} - -void RrFontDraw(XftDraw *d, RrTextureText *t, RrRect *area) -{ - gint x,y,w; - XftColor c; - gint mw; - PangoRectangle rect; - PangoAttrList *attrlist; - PangoEllipsizeMode ell; - - g_assert(!t->flow || t->maxwidth > 0); - - y = area->y; - if (!t->flow) - /* center the text vertically - We do this centering based on the 'baseline' since different fonts - have different top edges. It looks bad when the whole string is - moved when 1 character from a non-default language is included in - the string */ - y += font_calculate_baseline(t->font, area->height); - - /* the +2 and -4 leave a small blank edge on the sides */ - x = area->x + 2; - w = area->width; - if (t->flow) w = MAX(w, t->maxwidth); - w -= 4; - /* h = area->height; */ - - if (t->flow) - ell = PANGO_ELLIPSIZE_NONE; - else { - switch (t->ellipsize) { - case RR_ELLIPSIZE_NONE: - ell = PANGO_ELLIPSIZE_NONE; - break; - case RR_ELLIPSIZE_START: - ell = PANGO_ELLIPSIZE_START; - break; - case RR_ELLIPSIZE_MIDDLE: - ell = PANGO_ELLIPSIZE_MIDDLE; - break; - case RR_ELLIPSIZE_END: - ell = PANGO_ELLIPSIZE_END; - break; - default: - g_assert_not_reached(); - } - } - - pango_layout_set_text(t->font->layout, t->string, -1); - pango_layout_set_width(t->font->layout, w * PANGO_SCALE); - pango_layout_set_ellipsize(t->font->layout, ell); - pango_layout_set_single_paragraph_mode(t->font->layout, !t->flow); - - /* * * end of setting up the layout * * */ - - pango_layout_get_pixel_extents(t->font->layout, NULL, &rect); - mw = rect.width; - - /* pango_layout_set_alignment doesn't work with - pango_xft_render_layout_line */ - switch (t->justify) { - case RR_JUSTIFY_LEFT: - break; - case RR_JUSTIFY_RIGHT: - x += (w - mw); - break; - case RR_JUSTIFY_CENTER: - x += (w - mw) / 2; - break; - } - - if (t->shadow_offset_x || t->shadow_offset_y) { - /* From nvidia's readme (chapter 23): - - When rendering to a 32-bit window, keep in mind that the X RENDER - extension, used by most composite managers, expects "premultiplied - alpha" colors. This means that if your color has components (r,g,b) - and alpha value a, then you must render (a*r, a*g, a*b, a) into the - target window. - */ - c.color.red = (t->shadow_color->r | t->shadow_color->r << 8) * - t->shadow_alpha / 255; - c.color.green = (t->shadow_color->g | t->shadow_color->g << 8) * - t->shadow_alpha / 255; - c.color.blue = (t->shadow_color->b | t->shadow_color->b << 8) * - t->shadow_alpha / 255; - c.color.alpha = 0xffff * t->shadow_alpha / 255; - c.pixel = t->shadow_color->pixel; - - /* see below... */ - if (!t->flow) { - pango_xft_render_layout_line - (d, &c, -#if PANGO_VERSION_MAJOR > 1 || \ - (PANGO_VERSION_MAJOR == 1 && PANGO_VERSION_MINOR >= 16) - pango_layout_get_line_readonly(t->font->layout, 0), -#else - pango_layout_get_line(t->font->layout, 0), -#endif - (x + t->shadow_offset_x) * PANGO_SCALE, - (y + t->shadow_offset_y) * PANGO_SCALE); - } - else { - pango_xft_render_layout(d, &c, t->font->layout, - (x + t->shadow_offset_x) * PANGO_SCALE, - (y + t->shadow_offset_y) * PANGO_SCALE); - } - } - - c.color.red = t->color->r | t->color->r << 8; - c.color.green = t->color->g | t->color->g << 8; - c.color.blue = t->color->b | t->color->b << 8; - c.color.alpha = 0xff | 0xff << 8; /* fully opaque text */ - c.pixel = t->color->pixel; - - if (t->shortcut) { - const gchar *s = t->string + t->shortcut_pos; - - t->font->shortcut_underline->start_index = t->shortcut_pos; - t->font->shortcut_underline->end_index = t->shortcut_pos + - (g_utf8_next_char(s) - s); - - /* the attributes are owned by the layout. - re-add the attributes to the layout after changing the - start and end index */ - attrlist = pango_layout_get_attributes(t->font->layout); - pango_attr_list_ref(attrlist); - pango_layout_set_attributes(t->font->layout, attrlist); - pango_attr_list_unref(attrlist); - } - - /* layout_line() uses y to specify the baseline - The line doesn't need to be freed, it's a part of the layout */ - if (!t->flow) { - pango_xft_render_layout_line - (d, &c, -#if PANGO_VERSION_MAJOR > 1 || \ - (PANGO_VERSION_MAJOR == 1 && PANGO_VERSION_MINOR >= 16) - pango_layout_get_line_readonly(t->font->layout, 0), -#else - pango_layout_get_line(t->font->layout, 0), -#endif - x * PANGO_SCALE, - y * PANGO_SCALE); - } - else { - pango_xft_render_layout(d, &c, t->font->layout, - x * PANGO_SCALE, - y * PANGO_SCALE); - } - - if (t->shortcut) { - t->font->shortcut_underline->start_index = 0; - t->font->shortcut_underline->end_index = 0; - /* the attributes are owned by the layout. - re-add the attributes to the layout after changing the - start and end index */ - attrlist = pango_layout_get_attributes(t->font->layout); - pango_attr_list_ref(attrlist); - pango_layout_set_attributes(t->font->layout, attrlist); - pango_attr_list_unref(attrlist); - } -} diff --git a/render/font.h b/render/font.h deleted file mode 100644 index 07d648d1..00000000 --- a/render/font.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- - - font.h for the Openbox window manager - Copyright (c) 2003-2007 Dana Jansens - Copyright (c) 2003 Derek Foreman - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - See the COPYING file for a copy of the GNU General Public License. -*/ - -#ifndef __font_h -#define __font_h -#include "render.h" -#include "geom.h" -#include - -struct _RrFont { - const RrInstance *inst; - gint ref; - PangoFontDescription *font_desc; - PangoLayout *layout; /*!< Used for measuring and rendering strings */ - PangoAttribute *shortcut_underline; /*< For underlining the shortcut key */ - gint ascent; /*!< The font's ascent in pango-units */ - gint descent; /*!< The font's descent in pango-units */ -}; - -void RrFontDraw(XftDraw *d, RrTextureText *t, RrRect *position); - -/*! Increment the references for this font, RrFontClose will decrement until 0 - and then really close it */ -void RrFontRef(RrFont *f); - -#endif /* __font_h */ diff --git a/render/geom.h b/render/geom.h deleted file mode 100644 index 4d81e4b3..00000000 --- a/render/geom.h +++ /dev/null @@ -1,38 +0,0 @@ -/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- - - geom.h for the Openbox window manager - Copyright (c) 2006 Mikael Magnusson - Copyright (c) 2003-2007 Dana Jansens - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - See the COPYING file for a copy of the GNU General Public License. -*/ - -#ifndef __render_geom_h -#define __render_geom_h - -typedef struct { - int width; - int height; -} RrSize; - -typedef struct { - int x; - int y; - int width; - int height; -} RrRect; - -#define RECT_SET(r, nx, ny, w, h) \ - (r).x = (nx), (r).y = (ny), (r).width = (w), (r).height = (h) - -#endif diff --git a/render/gradient.c b/render/gradient.c deleted file mode 100644 index 60a0a555..00000000 --- a/render/gradient.c +++ /dev/null @@ -1,836 +0,0 @@ -/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- - - gradient.c for the Openbox window manager - Copyright (c) 2006 Mikael Magnusson - Copyright (c) 2003-2008 Dana Jansens - Copyright (c) 2003 Derek Foreman - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - See the COPYING file for a copy of the GNU General Public License. -*/ - -#include "render.h" -#include "gradient.h" -#include "color.h" -#include -#include - -static void highlight(RrSurface *s, RrPixel32 *x, RrPixel32 *y, - gboolean raised); -static void gradient_parentrelative(RrAppearance *a, gint w, gint h); -static void gradient_solid(RrAppearance *l, gint w, gint h); -static void gradient_splitvertical(RrAppearance *a, gint w, gint h); -static void gradient_vertical(RrSurface *sf, gint w, gint h); -static void gradient_horizontal(RrSurface *sf, gint w, gint h); -static void gradient_mirrorhorizontal(RrSurface *sf, gint w, gint h); -static void gradient_diagonal(RrSurface *sf, gint w, gint h); -static void gradient_crossdiagonal(RrSurface *sf, gint w, gint h); -static void gradient_pyramid(RrSurface *sf, gint inw, gint inh); - -void RrRender(RrAppearance *a, gint w, gint h) -{ - RrPixel32 *data = a->surface.pixel_data; - RrPixel32 current; - guint r,g,b; - register gint off, x; - - switch (a->surface.grad) { - case RR_SURFACE_PARENTREL: - gradient_parentrelative(a, w, h); - break; - case RR_SURFACE_SOLID: - gradient_solid(a, w, h); - break; - case RR_SURFACE_SPLIT_VERTICAL: - gradient_splitvertical(a, w, h); - break; - case RR_SURFACE_VERTICAL: - gradient_vertical(&a->surface, w, h); - break; - case RR_SURFACE_HORIZONTAL: - gradient_horizontal(&a->surface, w, h); - break; - case RR_SURFACE_MIRROR_HORIZONTAL: - gradient_mirrorhorizontal(&a->surface, w, h); - break; - case RR_SURFACE_DIAGONAL: - gradient_diagonal(&a->surface, w, h); - break; - case RR_SURFACE_CROSS_DIAGONAL: - gradient_crossdiagonal(&a->surface, w, h); - break; - case RR_SURFACE_PYRAMID: - gradient_pyramid(&a->surface, w, h); - break; - default: - g_assert_not_reached(); /* unhandled gradient */ - return; - } - - if (a->surface.interlaced) { - gint i; - RrPixel32 *p; - - r = a->surface.interlace_color->r; - g = a->surface.interlace_color->g; - b = a->surface.interlace_color->b; - current = (r << RrDefaultRedOffset) - + (g << RrDefaultGreenOffset) - + (b << RrDefaultBlueOffset); - p = data; - for (i = 0; i < h; i += 2, p += w) - for (x = 0; x < w; ++x, ++p) - *p = current; - } - - if (a->surface.relief == RR_RELIEF_FLAT && a->surface.border) { - r = a->surface.border_color->r; - g = a->surface.border_color->g; - b = a->surface.border_color->b; - current = (r << RrDefaultRedOffset) - + (g << RrDefaultGreenOffset) - + (b << RrDefaultBlueOffset); - for (off = 0, x = 0; x < w; ++x, off++) { - *(data + off) = current; - *(data + off + ((h-1) * w)) = current; - } - for (off = 0, x = 0; x < h; ++x, off++) { - *(data + (off * w)) = current; - *(data + (off * w) + w - 1) = current; - } - } - - if (a->surface.relief != RR_RELIEF_FLAT) { - if (a->surface.bevel == RR_BEVEL_1) { - for (off = 1, x = 1; x < w - 1; ++x, off++) - highlight(&a->surface, data + off, - data + off + (h-1) * w, - a->surface.relief==RR_RELIEF_RAISED); - for (off = 0, x = 0; x < h; ++x, off++) - highlight(&a->surface, data + off * w, - data + off * w + w - 1, - a->surface.relief==RR_RELIEF_RAISED); - } - - if (a->surface.bevel == RR_BEVEL_2) { - for (off = 2, x = 2; x < w - 2; ++x, off++) - highlight(&a->surface, data + off + w, - data + off + (h-2) * w, - a->surface.relief==RR_RELIEF_RAISED); - for (off = 1, x = 1; x < h-1; ++x, off++) - highlight(&a->surface, data + off * w + 1, - data + off * w + w - 2, - a->surface.relief==RR_RELIEF_RAISED); - } - } -} - -static void highlight(RrSurface *s, RrPixel32 *x, RrPixel32 *y, gboolean raised) -{ - register gint r, g, b; - - RrPixel32 *up, *down; - if (raised) { - up = x; - down = y; - } else { - up = y; - down = x; - } - - r = (*up >> RrDefaultRedOffset) & 0xFF; - r += (r * s->bevel_light_adjust) >> 8; - g = (*up >> RrDefaultGreenOffset) & 0xFF; - g += (g * s->bevel_light_adjust) >> 8; - b = (*up >> RrDefaultBlueOffset) & 0xFF; - b += (b * s->bevel_light_adjust) >> 8; - if (r > 0xFF) r = 0xFF; - if (g > 0xFF) g = 0xFF; - if (b > 0xFF) b = 0xFF; - *up = (r << RrDefaultRedOffset) + (g << RrDefaultGreenOffset) - + (b << RrDefaultBlueOffset); - - r = (*down >> RrDefaultRedOffset) & 0xFF; - r -= (r * s->bevel_dark_adjust) >> 8; - g = (*down >> RrDefaultGreenOffset) & 0xFF; - g -= (g * s->bevel_dark_adjust) >> 8; - b = (*down >> RrDefaultBlueOffset) & 0xFF; - b -= (b * s->bevel_dark_adjust) >> 8; - *down = (r << RrDefaultRedOffset) + (g << RrDefaultGreenOffset) - + (b << RrDefaultBlueOffset); -} - -static void create_bevel_colors(RrAppearance *l) -{ - register gint r, g, b; - - /* light color */ - r = l->surface.primary->r; - r += (r * l->surface.bevel_light_adjust) >> 8; - g = l->surface.primary->g; - g += (g * l->surface.bevel_light_adjust) >> 8; - b = l->surface.primary->b; - b += (b * l->surface.bevel_light_adjust) >> 8; - if (r > 0xFF) r = 0xFF; - if (g > 0xFF) g = 0xFF; - if (b > 0xFF) b = 0xFF; - g_assert(!l->surface.bevel_light); - l->surface.bevel_light = RrColorNew(l->inst, r, g, b); - - /* dark color */ - r = l->surface.primary->r; - r -= (r * l->surface.bevel_dark_adjust) >> 8; - g = l->surface.primary->g; - g -= (g * l->surface.bevel_dark_adjust) >> 8; - b = l->surface.primary->b; - b -= (b * l->surface.bevel_dark_adjust) >> 8; - g_assert(!l->surface.bevel_dark); - l->surface.bevel_dark = RrColorNew(l->inst, r, g, b); -} - -/*! Repeat the first pixel over the entire block of memory - @param start The block of memory. start[0] will be copied - to the rest of the block. - @param w The width of the block of memory (including the already-set first - element -*/ -static inline void repeat_pixel(RrPixel32 *start, gint w) -{ - register gint x; - RrPixel32 *dest; - - dest = start + 1; - - /* for really small things, just copy ourselves */ - if (w < 8) { - for (x = w-1; x > 0; --x) - *(dest++) = *start; - } - - /* for >= 8, then use O(log n) memcpy's... */ - else { - gchar *cdest; - gint lenbytes; - - /* copy the first 3 * 32 bits (3 words) ourselves - then we have - 3 + the original 1 = 4 words to make copies of at a time - - this is faster than doing memcpy for 1 or 2 words at a time - */ - for (x = 3; x > 0; --x) - *(dest++) = *start; - - /* cdest is a pointer to the pixel data that is typed char* so that - adding 1 to its position moves it only one byte - - lenbytes is the amount of bytes that we will be copying each - iteration. this doubles each time through the loop. - - x is the number of bytes left to copy into. lenbytes will alwaysa - be bounded by x - - this loop will run O(log n) times (n is the number of bytes we - need to copy into), since the size of the copy is doubled each - iteration. it seems that gcc does some nice optimizations to make - this memcpy very fast on hardware with support for vector operations - such as mmx or see. here is an idea of the kind of speed up we are - getting by doing this (splitvertical3 switches from doing - "*(data++) = color" n times to doing this memcpy thing log n times: - - % cumulative self self total - time seconds seconds calls ms/call ms/call name - 49.44 0.88 0.88 1063 0.83 0.83 splitvertical1 - 47.19 1.72 0.84 1063 0.79 0.79 splitvertical2 - 2.81 1.77 0.05 1063 0.05 0.05 splitvertical3 - */ - cdest = (gchar*)dest; - lenbytes = 4 * sizeof(RrPixel32); - for (x = (w - 4) * sizeof(RrPixel32); x > 0;) { - memcpy(cdest, start, lenbytes); - x -= lenbytes; - cdest += lenbytes; - lenbytes <<= 1; - if (lenbytes > x) - lenbytes = x; - } - } -} - -static void gradient_parentrelative(RrAppearance *a, gint w, gint h) -{ - RrPixel32 *source, *dest; - gint sw, sh, partial_w, partial_h; - register gint i; - - g_assert (a->surface.parent); - g_assert (a->surface.parent->w); - - sw = a->surface.parent->w; - sh = a->surface.parent->h; - - /* This is a little hack. When a texture is parentrelative, and the same - area as the parent, and has a bevel, it will draw its bevel on top - of the parent's, amplifying it. So instead, rerender the child with - the parent's settings, but the child's bevel and interlace */ - if (a->surface.relief != RR_RELIEF_FLAT && - (a->surface.parent->surface.relief != RR_RELIEF_FLAT || - a->surface.parent->surface.border) && - !a->surface.parentx && !a->surface.parenty && - sw == w && sh == h) - { - RrSurface old = a->surface; - a->surface = a->surface.parent->surface; - - /* turn these off for the parent */ - a->surface.relief = RR_RELIEF_FLAT; - a->surface.border = FALSE; - - a->surface.pixel_data = old.pixel_data; - - RrRender(a, w, h); - a->surface = old; - } else { - source = (a->surface.parent->surface.pixel_data + - a->surface.parentx + sw * a->surface.parenty); - dest = a->surface.pixel_data; - - if (a->surface.parentx + w > sw) { - partial_w = sw - a->surface.parentx; - } else partial_w = w; - - if (a->surface.parenty + h > sh) { - partial_h = sh - a->surface.parenty; - } else partial_h = h; - - for (i = 0; i < partial_h; i++, source += sw, dest += w) { - memcpy(dest, source, partial_w * sizeof(RrPixel32)); - } - } -} - -static void gradient_solid(RrAppearance *l, gint w, gint h) -{ - register gint i; - RrPixel32 pix; - RrPixel32 *data = l->surface.pixel_data; - RrSurface *sp = &l->surface; - gint left = 0, top = 0, right = w - 1, bottom = h - 1; - - pix = (sp->primary->r << RrDefaultRedOffset) - + (sp->primary->g << RrDefaultGreenOffset) - + (sp->primary->b << RrDefaultBlueOffset); - - for (i = 0; i < w * h; i++) - *data++ = pix; - - if (sp->interlaced) - return; - - XFillRectangle(RrDisplay(l->inst), l->pixmap, RrColorGC(sp->primary), - 0, 0, w, h); - - switch (sp->relief) { - case RR_RELIEF_RAISED: - if (!sp->bevel_dark) - create_bevel_colors(l); - - switch (sp->bevel) { - case RR_BEVEL_1: - XDrawLine(RrDisplay(l->inst), l->pixmap, RrColorGC(sp->bevel_dark), - left, bottom, right, bottom); - XDrawLine(RrDisplay(l->inst), l->pixmap, RrColorGC(sp->bevel_dark), - right, bottom, right, top); - - XDrawLine(RrDisplay(l->inst), l->pixmap,RrColorGC(sp->bevel_light), - left, top, right, top); - XDrawLine(RrDisplay(l->inst), l->pixmap,RrColorGC(sp->bevel_light), - left, bottom, left, top); - break; - case RR_BEVEL_2: - XDrawLine(RrDisplay(l->inst), l->pixmap, RrColorGC(sp->bevel_dark), - left + 2, bottom - 1, right - 2, bottom - 1); - XDrawLine(RrDisplay(l->inst), l->pixmap, RrColorGC(sp->bevel_dark), - right - 1, bottom - 1, right - 1, top + 1); - - XDrawLine(RrDisplay(l->inst), l->pixmap,RrColorGC(sp->bevel_light), - left + 2, top + 1, right - 2, top + 1); - XDrawLine(RrDisplay(l->inst), l->pixmap,RrColorGC(sp->bevel_light), - left + 1, bottom - 1, left + 1, top + 1); - break; - default: - g_assert_not_reached(); /* unhandled BevelType */ - } - break; - case RR_RELIEF_SUNKEN: - if (!sp->bevel_dark) - create_bevel_colors(l); - - switch (sp->bevel) { - case RR_BEVEL_1: - XDrawLine(RrDisplay(l->inst), l->pixmap,RrColorGC(sp->bevel_light), - left, bottom, right, bottom); - XDrawLine(RrDisplay(l->inst), l->pixmap,RrColorGC(sp->bevel_light), - right, bottom, right, top); - - XDrawLine(RrDisplay(l->inst), l->pixmap, RrColorGC(sp->bevel_dark), - left, top, right, top); - XDrawLine(RrDisplay(l->inst), l->pixmap, RrColorGC(sp->bevel_dark), - left, bottom, left, top); - break; - case RR_BEVEL_2: - XDrawLine(RrDisplay(l->inst), l->pixmap,RrColorGC(sp->bevel_light), - left + 2, bottom - 1, right - 2, bottom - 1); - XDrawLine(RrDisplay(l->inst), l->pixmap,RrColorGC(sp->bevel_light), - right - 1, bottom - 1, right - 1, top + 1); - - XDrawLine(RrDisplay(l->inst), l->pixmap, RrColorGC(sp->bevel_dark), - left + 2, top + 1, right - 2, top + 1); - XDrawLine(RrDisplay(l->inst), l->pixmap, RrColorGC(sp->bevel_dark), - left + 1, bottom - 1, left + 1, top + 1); - break; - default: - g_assert_not_reached(); /* unhandled BevelType */ - } - break; - case RR_RELIEF_FLAT: - if (sp->border) { - XDrawRectangle(RrDisplay(l->inst), l->pixmap, - RrColorGC(sp->border_color), - left, top, right, bottom); - } - break; - default: - g_assert_not_reached(); /* unhandled ReliefType */ - } -} - -/* * * * * * * * * * * * * * GRADIENT MAGIC WOOT * * * * * * * * * * * * * * */ - -#define VARS(x) \ - register gint len##x; \ - guint color##x[3]; \ - gint cdelta##x[3], error##x[3] = { 0, 0, 0 }, inc##x[3]; \ - gboolean bigslope##x[3] /* color slope > 1 */ - -#define SETUP(x, from, to, w) \ - len##x = w; \ - \ - color##x[0] = from->r; \ - color##x[1] = from->g; \ - color##x[2] = from->b; \ - \ - cdelta##x[0] = to->r - from->r; \ - cdelta##x[1] = to->g - from->g; \ - cdelta##x[2] = to->b - from->b; \ - \ - if (cdelta##x[0] < 0) { \ - cdelta##x[0] = -cdelta##x[0]; \ - inc##x[0] = -1; \ - } else \ - inc##x[0] = 1; \ - if (cdelta##x[1] < 0) { \ - cdelta##x[1] = -cdelta##x[1]; \ - inc##x[1] = -1; \ - } else \ - inc##x[1] = 1; \ - if (cdelta##x[2] < 0) { \ - cdelta##x[2] = -cdelta##x[2]; \ - inc##x[2] = -1; \ - } else \ - inc##x[2] = 1; \ - bigslope##x[0] = cdelta##x[0] > w;\ - bigslope##x[1] = cdelta##x[1] > w;\ - bigslope##x[2] = cdelta##x[2] > w - -#define COLOR_RR(x, c) \ - c->r = color##x[0]; \ - c->g = color##x[1]; \ - c->b = color##x[2] - -#define COLOR(x) \ - ((color##x[0] << RrDefaultRedOffset) + \ - (color##x[1] << RrDefaultGreenOffset) + \ - (color##x[2] << RrDefaultBlueOffset)) - -#define INCREMENT(x, i) \ - (inc##x[i]) - -#define NEXT(x) \ -{ \ - register gint i; \ - for (i = 2; i >= 0; --i) { \ - if (!cdelta##x[i]) continue; \ - \ - if (!bigslope##x[i]) { \ - /* Y (color) is dependant on X */ \ - error##x[i] += cdelta##x[i]; \ - if ((error##x[i] << 1) >= len##x) { \ - color##x[i] += INCREMENT(x, i); \ - error##x[i] -= len##x; \ - } \ - } else { \ - /* X is dependant on Y (color) */ \ - while (1) { \ - color##x[i] += INCREMENT(x, i); \ - error##x[i] += len##x; \ - if ((error##x[i] << 1) >= cdelta##x[i]) { \ - error##x[i] -= cdelta##x[i]; \ - break; \ - } \ - } \ - } \ - } \ -} - -static void gradient_splitvertical(RrAppearance *a, gint w, gint h) -{ - register gint y1, y2, y3; - RrSurface *sf = &a->surface; - RrPixel32 *data; - register gint y1sz, y2sz, y3sz; - - VARS(y1); - VARS(y2); - VARS(y3); - - /* if h <= 5, then a 0 or 1px middle gradient. - if h > 5, then always a 1px middle gradient. - */ - if (h <= 5) { - y1sz = MAX(h/2, 0); - y2sz = (h < 3) ? 0 : (h & 1); - y3sz = MAX(h/2, 1); - } - else { - y1sz = h/2 - (1 - (h & 1)); - y2sz = 1; - y3sz = h/2; - } - - SETUP(y1, sf->split_primary, sf->primary, y1sz); - if (y2sz) { - /* setup to get the colors _in between_ these other 2 */ - SETUP(y2, sf->primary, sf->secondary, y2sz + 2); - NEXT(y2); /* skip the first one, its the same as the last of y1 */ - } - SETUP(y3, sf->secondary, sf->split_secondary, y3sz); - - /* find the color for the first pixel of each row first */ - data = sf->pixel_data; - - for (y1 = y1sz-1; y1 > 0; --y1) { - *data = COLOR(y1); - data += w; - NEXT(y1); - } - *data = COLOR(y1); - data += w; - if (y2sz) { - for (y2 = y2sz-1; y2 > 0; --y2) { - *data = COLOR(y2); - data += w; - NEXT(y2); - } - *data = COLOR(y2); - data += w; - } - for (y3 = y3sz-1; y3 > 0; --y3) { - *data = COLOR(y3); - data += w; - NEXT(y3); - } - *data = COLOR(y3); - - /* copy the first pixels into the whole rows */ - data = sf->pixel_data; - for (y1 = h; y1 > 0; --y1) { - repeat_pixel(data, w); - data += w; - } -} - -static void gradient_horizontal(RrSurface *sf, gint w, gint h) -{ - register gint x, y, cpbytes; - RrPixel32 *data = sf->pixel_data, *datav; - gchar *datac; - - VARS(x); - SETUP(x, sf->primary, sf->secondary, w); - - /* set the color values for the first row */ - datav = data; - for (x = w - 1; x > 0; --x) { /* 0 -> w - 1 */ - *datav = COLOR(x); - ++datav; - NEXT(x); - } - *datav = COLOR(x); - ++datav; - - /* copy the first row to the rest in O(logn) copies */ - datac = (gchar*)datav; - cpbytes = 1 * w * sizeof(RrPixel32); - for (y = (h - 1) * w * sizeof(RrPixel32); y > 0;) { - memcpy(datac, data, cpbytes); - y -= cpbytes; - datac += cpbytes; - cpbytes <<= 1; - if (cpbytes > y) - cpbytes = y; - } -} - -static void gradient_mirrorhorizontal(RrSurface *sf, gint w, gint h) -{ - register gint x, y, half1, half2, cpbytes; - RrPixel32 *data = sf->pixel_data, *datav; - gchar *datac; - - VARS(x); - - half1 = (w + 1) / 2; - half2 = w / 2; - - /* set the color values for the first row */ - - SETUP(x, sf->primary, sf->secondary, half1); - datav = data; - for (x = half1 - 1; x > 0; --x) { /* 0 -> half1 - 1 */ - *datav = COLOR(x); - ++datav; - NEXT(x); - } - *datav = COLOR(x); - ++datav; - - if (half2 > 0) { - SETUP(x, sf->secondary, sf->primary, half2); - for (x = half2 - 1; x > 0; --x) { /* 0 -> half2 - 1 */ - *datav = COLOR(x); - ++datav; - NEXT(x); - } - *datav = COLOR(x); - ++datav; - } - - /* copy the first row to the rest in O(logn) copies */ - datac = (gchar*)datav; - cpbytes = 1 * w * sizeof(RrPixel32); - for (y = (h - 1) * w * sizeof(RrPixel32); y > 0;) { - memcpy(datac, data, cpbytes); - y -= cpbytes; - datac += cpbytes; - cpbytes <<= 1; - if (cpbytes > y) - cpbytes = y; - } -} - -static void gradient_vertical(RrSurface *sf, gint w, gint h) -{ - register gint y; - RrPixel32 *data; - - VARS(y); - SETUP(y, sf->primary, sf->secondary, h); - - /* find the color for the first pixel of each row first */ - data = sf->pixel_data; - - for (y = h - 1; y > 0; --y) { /* 0 -> h-1 */ - *data = COLOR(y); - data += w; - NEXT(y); - } - *data = COLOR(y); - - /* copy the first pixels into the whole rows */ - data = sf->pixel_data; - for (y = h; y > 0; --y) { - repeat_pixel(data, w); - data += w; - } -} - -static void gradient_diagonal(RrSurface *sf, gint w, gint h) -{ - register gint x, y; - RrPixel32 *data = sf->pixel_data; - RrColor left, right; - RrColor extracorner; - - VARS(lefty); - VARS(righty); - VARS(x); - - extracorner.r = (sf->primary->r + sf->secondary->r) / 2; - extracorner.g = (sf->primary->g + sf->secondary->g) / 2; - extracorner.b = (sf->primary->b + sf->secondary->b) / 2; - - SETUP(lefty, sf->primary, (&extracorner), h); - SETUP(righty, (&extracorner), sf->secondary, h); - - for (y = h - 1; y > 0; --y) { /* 0 -> h-1 */ - COLOR_RR(lefty, (&left)); - COLOR_RR(righty, (&right)); - - SETUP(x, (&left), (&right), w); - - for (x = w - 1; x > 0; --x) { /* 0 -> w-1 */ - *(data++) = COLOR(x); - - NEXT(x); - } - *(data++) = COLOR(x); - - NEXT(lefty); - NEXT(righty); - } - COLOR_RR(lefty, (&left)); - COLOR_RR(righty, (&right)); - - SETUP(x, (&left), (&right), w); - - for (x = w - 1; x > 0; --x) { /* 0 -> w-1 */ - *(data++) = COLOR(x); - - NEXT(x); - } - *data = COLOR(x); -} - -static void gradient_crossdiagonal(RrSurface *sf, gint w, gint h) -{ - register gint x, y; - RrPixel32 *data = sf->pixel_data; - RrColor left, right; - RrColor extracorner; - - VARS(lefty); - VARS(righty); - VARS(x); - - extracorner.r = (sf->primary->r + sf->secondary->r) / 2; - extracorner.g = (sf->primary->g + sf->secondary->g) / 2; - extracorner.b = (sf->primary->b + sf->secondary->b) / 2; - - SETUP(lefty, (&extracorner), sf->secondary, h); - SETUP(righty, sf->primary, (&extracorner), h); - - for (y = h - 1; y > 0; --y) { /* 0 -> h-1 */ - COLOR_RR(lefty, (&left)); - COLOR_RR(righty, (&right)); - - SETUP(x, (&left), (&right), w); - - for (x = w - 1; x > 0; --x) { /* 0 -> w-1 */ - *(data++) = COLOR(x); - - NEXT(x); - } - *(data++) = COLOR(x); - - NEXT(lefty); - NEXT(righty); - } - COLOR_RR(lefty, (&left)); - COLOR_RR(righty, (&right)); - - SETUP(x, (&left), (&right), w); - - for (x = w - 1; x > 0; --x) { /* 0 -> w-1 */ - *(data++) = COLOR(x); - - NEXT(x); - } - *data = COLOR(x); -} - -static void gradient_pyramid(RrSurface *sf, gint w, gint h) -{ - RrPixel32 *ldata, *rdata; - RrPixel32 *cp; - RrColor left, right; - RrColor extracorner; - register gint x, y, halfw, halfh, midx, midy; - - VARS(lefty); - VARS(righty); - VARS(x); - - extracorner.r = (sf->primary->r + sf->secondary->r) / 2; - extracorner.g = (sf->primary->g + sf->secondary->g) / 2; - extracorner.b = (sf->primary->b + sf->secondary->b) / 2; - - halfw = w >> 1; - halfh = h >> 1; - midx = w - halfw - halfw; /* 0 or 1, depending if w is even or odd */ - midy = h - halfh - halfh; /* 0 or 1, depending if h is even or odd */ - - SETUP(lefty, sf->primary, (&extracorner), halfh + midy); - SETUP(righty, (&extracorner), sf->secondary, halfh + midy); - - /* draw the top half - - it is faster to draw both top quarters together than to draw one and - then copy it over to the other side. - */ - - ldata = sf->pixel_data; - rdata = ldata + w - 1; - for (y = halfh + midy; y > 0; --y) { /* 0 -> (h+1)/2 */ - RrPixel32 c; - - COLOR_RR(lefty, (&left)); - COLOR_RR(righty, (&right)); - - SETUP(x, (&left), (&right), halfw + midx); - - for (x = halfw + midx - 1; x > 0; --x) { /* 0 -> (w+1)/2 */ - c = COLOR(x); - *(ldata++) = *(rdata--) = c; - - NEXT(x); - } - c = COLOR(x); - *ldata = *rdata = c; - ldata += halfw + 1; - rdata += halfw - 1 + midx + w; - - NEXT(lefty); - NEXT(righty); - } - - /* copy the top half into the bottom half, mirroring it, so we can only - copy one row at a time - - it is faster, to move the writing pointer forward, and the reading - pointer backward - - this is the current code, moving the write pointer forward and read - pointer backward - 41.78 4.26 1.78 504 3.53 3.53 gradient_pyramid2 - this is the opposite, moving the read pointer forward and the write - pointer backward - 42.27 4.40 1.86 504 3.69 3.69 gradient_pyramid2 - - */ - ldata = sf->pixel_data + (halfh - 1) * w; - cp = ldata + (midy + 1) * w; - for (y = halfh; y > 0; --y) { - memcpy(cp, ldata, w * sizeof(RrPixel32)); - ldata -= w; - cp += w; - } -} diff --git a/render/gradient.h b/render/gradient.h deleted file mode 100644 index 8613f0ce..00000000 --- a/render/gradient.h +++ /dev/null @@ -1,27 +0,0 @@ -/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- - - gradient.h for the Openbox window manager - Copyright (c) 2003-2007 Dana Jansens - Copyright (c) 2003 Derek Foreman - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - See the COPYING file for a copy of the GNU General Public License. -*/ - -#ifndef __gradient_h -#define __gradient_h - -#include "render.h" - -void RrRender(RrAppearance *a, gint w, gint h); - -#endif /* __gradient_h */ diff --git a/render/icon.h b/render/icon.h deleted file mode 100644 index f0b2d267..00000000 --- a/render/icon.h +++ /dev/null @@ -1,422 +0,0 @@ -/* GIMP RGBA C-Source image dump (icon.h) */ - -/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- - - icon.h for the Openbox window manager - Copyright (c) 2003-2007 Dana Jansens - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - See the COPYING file for a copy of the GNU General Public License. -*/ - -#define OB_DEFAULT_ICON_WIDTH (48) -#define OB_DEFAULT_ICON_HEIGHT (48) -#define OB_DEFAULT_ICON_BYTES_PER_PIXEL (4) /* 3:RGB, 4:RGBA */ -#define OB_DEFAULT_ICON_COMMENT \ - "To recreate this file, save an image as \"C-Source\" in The Gimp. Use \"ob_default_icon\" as the Prefixed Name. Enable Glib Types. Enable Save Alpha Channel. Enable Use Macros instead of Struct." -#define OB_DEFAULT_ICON_PIXEL_DATA ((guint8*) OB_DEFAULT_ICON_pixel_data) -static const guint8 OB_DEFAULT_ICON_pixel_data[48 * 48 * 4 + 1] = -("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\40J\207\15\40J\207\23\40J\207" - "\23\40J\207\23\40J\207\23\40J\207\23\40J\207\23\40J\207\23\40J\207\23\40J" - "\207\23\40J\207\23\40J\207\23\40J\207\23\40J\207\23\40J\207\23\40J\207\23" - "\40J\207\23\40J\207\23\40J\207\23\40J\207\23\40J\207\23\40J\207\23\40J\207" - "\23\40J\207\23\40J\207\23\40J\207\23\40J\207\23\40J\207\23\40J\207\23\40J" - "\207\23\40J\207\23\40J\207\23\40J\207\23\40J\207\23\40J\207\23\40J\207\23" - "\40J\207\23\40J\207\23\40J\207\23\40J\207\23\40J\207\23\40J\207\23\40J\207" - "\23\40J\207\15\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0'P\213\267'Q\214\275'Q\214\275" - "'Q\214\275'Q\214\275'Q\214\275'Q\214\275'Q\214\275'Q\214\275'Q\214\275'Q\214" - "\275'Q\214\275'Q\214\275'Q\214\275'Q\214\275'Q\214\275'Q\214\275'Q\214\275" - "'Q\214\275'Q\214\275'Q\214\275'Q\214\275'Q\214\275(R\215\275'Q\214\275'Q\214" - "\275'Q\214\275'Q\214\275'Q\214\275'Q\214\275'Q\214\275'Q\214\275'Q\214\275" - "'Q\214\275'Q\214\275'Q\214\275'Q\214\275'Q\214\275'Q\214\275'Q\214\275(R\215" - "\275(R\215\275(R\215\275&P\213\267\40J\207\20\0\0\0\0\0\0\0\0\40J\207+Y{\252" - "\377\216\253\320\377\204\243\314\377\204\243\314\377\204\243\314\377\204\243" - "\314\377\204\243\314\377\204\243\314\377\204\243\314\377\204\243\314\377\204" - "\243\314\377\204\243\314\377\204\243\314\377\204\243\314\377\204\243\314\377" - "\204\243\314\377\204\243\314\377\204\243\314\377\204\243\314\377\204\243\314" - "\377\204\243\314\377\204\243\314\377\204\243\314\377\204\243\314\377\204\243" - "\314\377\204\243\314\377\203\243\314\377\203\243\313\377\203\243\313\377\203" - "\243\313\377\203\242\313\377\202\242\313\377\202\242\313\377\202\241\313\377" - "\201\241\312\377\201\241\312\377\201\240\312\377\201\240\312\377\200\240\312" - "\377\200\240\312\377\200\240\312\377\200\240\312\377\211\247\316\377Jn\241" - "\377\40J\207+\0\0\0\0\0\0\0\0\40J\207+Wy\251\377]\207\275\377>o\260\377>o" - "\260\377>o\260\377>o\260\377>o\260\377>o\260\377>o\260\377>o\260\377>o\260" - "\377>o\260\377>o\260\377>o\260\377>o\260\377>o\260\377>o\260\377>o\260\377" - ">o\260\377>o\260\377>o\260\377>o\260\377>o\260\377>o\260\377>o\260\377>o\260" - "\377>o\260\377>o\260\377>o\260\377>o\260\377=o\260\377=o\260\377=o\260\377" - "=o\260\377=o\260\377=o\260\377=o\260\377=o\260\377=o\260\377=o\260\377=o\260" - "\377=o\260\377_\210\275\377Hm\241\377\40J\207+\0\0\0\0\0\0\0\0\40J\207+Tw" - "\251\377]\207\276\377?r\263\377?r\263\377?r\263\377?r\263\377?r\263\377?r" - "\263\377?r\263\377?r\263\377?r\263\377?r\263\377?r\263\377?r\263\377?r\263" - "\377?r\263\377?r\263\377?r\263\377?r\263\377?r\263\377?r\263\377?r\263\377" - "?r\263\377?r\263\377?r\263\377?r\263\377?r\263\377?r\263\377?r\263\377?r\263" - "\377?r\263\377?r\263\377?r\263\377?r\263\377?r\263\377?r\263\377?r\263\377" - "?r\263\377?r\263\377?r\263\377?r\263\377?r\263\377]\210\277\377Fl\241\377" - "\40J\207+\0\0\0\0\0\0\0\0\40J\207+Rv\250\377\\\210\300\377At\265\377At\265" - "\377At\265\377At\265\377At\265\377At\265\377At\265\377At\265\377At\265\377" - "At\265\377At\265\377At\265\377At\265\377At\265\377At\265\377At\265\377At\265" - "\377At\265\377At\265\377At\265\377At\265\377At\265\377At\265\377At\265\377" - "At\265\377At\265\377At\265\377At\265\377At\265\377At\265\377At\265\377At\265" - "\377At\265\377At\265\377At\265\377At\265\377At\265\377At\265\377At\265\377" - "At\265\377\\\210\300\377Dj\240\377\40J\207+\0\0\0\0\0\0\0\0\40J\207+Ot\247" - "\377\\\211\302\377Dw\271\377Dw\271\377Dw\271\377Dw\271\377Dw\271\377Dw\271" - "\377Dw\271\377Dw\271\377Dw\271\377Dw\271\377Dw\271\377Dw\271\377Dw\271\377" - "Dw\271\377Dw\271\377Dw\271\377Dw\271\377Dw\271\377Dw\271\377Dw\271\377Dw\271" - "\377Dw\271\377Dw\271\377Dw\271\377Dw\271\377Dw\271\377Dw\271\377Dw\271\377" - "Dw\271\377Dw\271\377Dw\271\377Dw\271\377Dw\271\377Dw\271\377Dw\271\377Dw\271" - "\377Dw\271\377Dw\271\377Dw\271\377Dw\271\377[\211\302\377Bi\240\377\40J\207" - "+\0\0\0\0\0\0\0\0\40J\207+Ls\247\377\\\211\303\377Fy\273\377Fy\273\377Fy\273" - "\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377" - "Fy\273\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377Fy\273" - "\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377" - "Fy\273\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377Fy\273" - "\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377Fy\273\377" - "\\\211\303\377Ah\240\377\40J\207+\0\0\0\0\0\0\0\0\40J\207+Jq\246\377\\\212" - "\305\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277" - "\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377" - "I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277" - "\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377" - "I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277" - "\377I}\277\377I}\277\377I}\277\377[\212\305\377?g\237\377\40J\207+\0\0\0\0" - "\0\0\0\0\40J\207+Jq\246\377\\\212\305\377I}\277\377I}\277\377I}\277\377I}" - "\277\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277" - "\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377I}\277\377" - "I}\277\377I}\277\377I}\277\377J~\300\377K\177\301\377K\177\301\377K\177\301" - "\377K\177\301\377K\177\301\377K\177\301\377K\177\301\377K\177\301\377K\177" - "\301\377K\177\301\377K\177\301\377K\177\301\377K\177\301\377K\177\301\377" - "K\177\301\377K\177\301\377K\177\301\377K\177\301\377Z\212\307\377=f\237\377" - "\40J\207+\0\0\0\0\0\0\0\0\40J\207+Ip\247\377\\\213\307\377J\177\301\377J\177" - "\301\377J\177\301\377J\177\301\377J\177\301\377J\177\301\377J\177\301\377" - "J\177\301\377J\177\301\377J\177\301\377J\177\301\377J\177\301\377J\177\301" - "\377J\177\301\377J\177\301\377J\177\301\377J\177\301\377J\177\301\377J\177" - "\301\377J\177\301\377J\177\301\377K\200\302\377K\200\302\377K\200\302\377" - "K\200\302\377K\200\302\377K\200\302\377K\200\302\377K\200\302\377K\200\302" - "\377K\200\302\377K\200\302\377K\200\302\377K\200\302\377K\200\302\377K\200" - "\302\377K\200\302\377K\200\302\377K\200\302\377K\200\302\377Z\212\307\377" - "=f\237\377\40J\207+\0\0\0\0\0\0\0\0\40J\207+Ho\247\377e\223\314\377Z\213\310" - "\377Z\213\310\377Z\213\310\377Z\213\310\377Z\213\307\377Z\213\307\377Z\213" - "\307\377Z\213\307\377Z\213\307\377Y\212\307\377Y\212\307\377Y\212\307\377" - "Y\212\307\377Y\212\307\377X\212\307\377X\212\307\377X\212\307\377X\211\307" - "\377X\212\307\377X\212\307\377X\211\307\377X\211\307\377X\211\307\377X\211" - "\307\377X\211\307\377X\211\307\377X\211\307\377X\211\307\377X\211\307\377" - "X\211\307\377W\211\307\377W\211\307\377W\211\307\377W\211\307\377W\211\307" - "\377W\211\307\377V\211\307\377V\211\307\377V\210\307\377V\210\307\377`\217" - "\312\377 - -#define FRACTION 12 -#define FLOOR(i) ((i) & (~0UL << FRACTION)) -#define AVERAGE(a, b) (((((a) ^ (b)) & 0xfefefefeL) >> 1) + ((a) & (b))) - -void RrImagePicInit(RrImagePic *pic, gint w, gint h, RrPixel32 *data) -{ - gint i; - - pic->width = w; - pic->height = h; - pic->data = data; - pic->sum = 0; - for (i = w*h; i > 0; --i) - pic->sum += *(data++); -} - -static void RrImagePicFree(RrImagePic *pic) -{ - if (pic) { - g_free(pic->data); - g_free(pic); - } -} - -/*! Add a picture to an Image, that is, add another copy of the image at - another size. This may add it to the "originals" list or to the - "resized" list. */ -static void AddPicture(RrImage *self, RrImagePic ***list, gint *len, - RrImagePic *pic) -{ - gint i; - - g_assert(pic->width > 0 && pic->height > 0); - - g_assert(g_hash_table_lookup(self->cache->table, pic) == NULL); - - /* grow the list */ - *list = g_renew(RrImagePic*, *list, ++*len); - - /* move everything else down one */ - for (i = *len-1; i > 0; --i) - (*list)[i] = (*list)[i-1]; - - /* set the new picture up at the front of the list */ - (*list)[0] = pic; - - /* add the picture as a key to point to this image in the cache */ - g_hash_table_insert(self->cache->table, (*list)[0], self); - -/* -#ifdef DEBUG - g_debug("Adding %s picture to the cache:\n " - "Image 0x%lx, w %d h %d Hash %u", - (*list == self->original ? "ORIGINAL" : "RESIZED"), - (gulong)self, pic->width, pic->height, RrImagePicHash(pic)); -#endif -*/ -} - -/*! Remove a picture from an Image. This may remove it from the "originals" - list or the "resized" list. */ -static void RemovePicture(RrImage *self, RrImagePic ***list, - gint i, gint *len) -{ - gint j; - -/* -#ifdef DEBUG - g_debug("Removing %s picture from the cache:\n " - "Image 0x%lx, w %d h %d Hash %u", - (*list == self->original ? "ORIGINAL" : "RESIZED"), - (gulong)self, (*list)[i]->width, (*list)[i]->height, - RrImagePicHash((*list)[i])); -#endif -*/ - - /* remove the picture as a key in the cache */ - g_hash_table_remove(self->cache->table, (*list)[i]); - - /* free the picture */ - RrImagePicFree((*list)[i]); - /* shift everything down one */ - for (j = i; j < *len-1; ++j) - (*list)[j] = (*list)[j+1]; - /* shrink the list */ - *list = g_renew(RrImagePic*, *list, --*len); -} - -/*! Given a picture in RGBA format, of a specified size, resize it to the new - requested size (but keep its aspect ratio). If the image does not need to - be resized (it is already the right size) then this returns NULL. Otherwise - it returns a newly allocated RrImagePic with the resized picture inside it -*/ -static RrImagePic* ResizeImage(RrPixel32 *src, - gulong srcW, gulong srcH, - gulong dstW, gulong dstH) -{ - RrPixel32 *dst, *dststart; - RrImagePic *pic; - gulong dstX, dstY, srcX, srcY; - gulong srcX1, srcX2, srcY1, srcY2; - gulong ratioX, ratioY; - gulong aspectW, aspectH; - - /* XXX should these variables be ensured to not be zero in the callers? */ - srcW = srcW ? srcW : 1; - srcH = srcH ? srcH : 1; - dstW = dstW ? dstW : 1; - dstH = dstH ? dstH : 1; - - /* keep the aspect ratio */ - aspectW = dstW; - aspectH = (gint)(dstW * ((gdouble)srcH / srcW)); - if (aspectH > dstH) { - aspectH = dstH; - aspectW = (gint)(dstH * ((gdouble)srcW / srcH)); - } - dstW = aspectW ? aspectW : 1; - dstH = aspectH ? aspectH : 1; - - if (srcW == dstW && srcH == dstH) - return NULL; /* no scaling needed! */ - - dststart = dst = g_new(RrPixel32, dstW * dstH); - - ratioX = (srcW << FRACTION) / dstW; - ratioY = (srcH << FRACTION) / dstH; - - srcY2 = 0; - for (dstY = 0; dstY < dstH; dstY++) { - srcY1 = srcY2; - srcY2 += ratioY; - - srcX2 = 0; - for (dstX = 0; dstX < dstW; dstX++) { - gulong red = 0, green = 0, blue = 0, alpha = 0; - gulong portionX, portionY, portionXY, sumXY = 0; - RrPixel32 pixel; - - srcX1 = srcX2; - srcX2 += ratioX; - - for (srcY = srcY1; srcY < srcY2; srcY += (1UL << FRACTION)) { - if (srcY == srcY1) { - srcY = FLOOR(srcY); - portionY = (1UL << FRACTION) - (srcY1 - srcY); - if (portionY > srcY2 - srcY1) - portionY = srcY2 - srcY1; - } - else if (srcY == FLOOR(srcY2)) - portionY = srcY2 - srcY; - else - portionY = (1UL << FRACTION); - - for (srcX = srcX1; srcX < srcX2; srcX += (1UL << FRACTION)) { - if (srcX == srcX1) { - srcX = FLOOR(srcX); - portionX = (1UL << FRACTION) - (srcX1 - srcX); - if (portionX > srcX2 - srcX1) - portionX = srcX2 - srcX1; - } - else if (srcX == FLOOR(srcX2)) - portionX = srcX2 - srcX; - else - portionX = (1UL << FRACTION); - - portionXY = (portionX * portionY) >> FRACTION; - sumXY += portionXY; - - pixel = *(src + (srcY >> FRACTION) * srcW - + (srcX >> FRACTION)); - red += ((pixel >> RrDefaultRedOffset) & 0xFF) - * portionXY; - green += ((pixel >> RrDefaultGreenOffset) & 0xFF) - * portionXY; - blue += ((pixel >> RrDefaultBlueOffset) & 0xFF) - * portionXY; - alpha += ((pixel >> RrDefaultAlphaOffset) & 0xFF) - * portionXY; - } - } - - g_assert(sumXY != 0); - red /= sumXY; - green /= sumXY; - blue /= sumXY; - alpha /= sumXY; - - *dst++ = (red << RrDefaultRedOffset) | - (green << RrDefaultGreenOffset) | - (blue << RrDefaultBlueOffset) | - (alpha << RrDefaultAlphaOffset); - } - } - - pic = g_new(RrImagePic, 1); - RrImagePicInit(pic, dstW, dstH, dststart); - - return pic; -} - -/*! This draws an RGBA picture into the target, within the rectangle specified - by the area parameter. If the area's size differs from the source's then it - will be centered within the rectangle */ -void DrawRGBA(RrPixel32 *target, gint target_w, gint target_h, - RrPixel32 *source, gint source_w, gint source_h, - gint alpha, RrRect *area) -{ - RrPixel32 *dest; - gint col, num_pixels; - gint dw, dh; - - g_assert(source_w <= area->width && source_h <= area->height); - g_assert(area->x + area->width <= target_w); - g_assert(area->y + area->height <= target_h); - - /* keep the aspect ratio */ - dw = area->width; - dh = (gint)(dw * ((gdouble)source_h / source_w)); - if (dh > area->height) { - dh = area->height; - dw = (gint)(dh * ((gdouble)source_w / source_h)); - } - - /* copy source -> dest, and apply the alpha channel. - center the image if it is smaller than the area */ - col = 0; - num_pixels = dw * dh; - dest = target + area->x + (area->width - dw) / 2 + - (target_w * (area->y + (area->height - dh) / 2)); - while (num_pixels-- > 0) { - guchar a, r, g, b, bgr, bgg, bgb; - - /* apply the rgba's opacity as well */ - a = ((*source >> RrDefaultAlphaOffset) * alpha) >> 8; - r = *source >> RrDefaultRedOffset; - g = *source >> RrDefaultGreenOffset; - b = *source >> RrDefaultBlueOffset; - - /* background color */ - bgr = *dest >> RrDefaultRedOffset; - bgg = *dest >> RrDefaultGreenOffset; - bgb = *dest >> RrDefaultBlueOffset; - - r = bgr + (((r - bgr) * a) >> 8); - g = bgg + (((g - bgg) * a) >> 8); - b = bgb + (((b - bgb) * a) >> 8); - - *dest = ((r << RrDefaultRedOffset) | - (g << RrDefaultGreenOffset) | - (b << RrDefaultBlueOffset)); - - dest++; - source++; - - if (++col >= dw) { - col = 0; - dest += target_w - dw; - } - } -} - -/*! Draw an RGBA texture into a target pixel buffer. */ -void RrImageDrawRGBA(RrPixel32 *target, RrTextureRGBA *rgba, - gint target_w, gint target_h, - RrRect *area) -{ - RrImagePic *scaled; - - scaled = ResizeImage(rgba->data, rgba->width, rgba->height, - area->width, area->height); - - if (scaled) { -#ifdef DEBUG - g_warning("Scaling an RGBA! You should avoid this and just make " - "it the right size yourself!"); -#endif - DrawRGBA(target, target_w, target_h, - scaled->data, scaled->width, scaled->height, - rgba->alpha, area); - RrImagePicFree(scaled); - } - else - DrawRGBA(target, target_w, target_h, - rgba->data, rgba->width, rgba->height, - rgba->alpha, area); -} - -/*! Create a new RrImage, which is linked to an image cache */ -RrImage* RrImageNew(RrImageCache *cache) -{ - RrImage *self; - - g_assert(cache != NULL); - - self = g_new0(RrImage, 1); - self->ref = 1; - self->cache = cache; - return self; -} - -void RrImageRef(RrImage *self) -{ - ++self->ref; -} - -void RrImageUnref(RrImage *self) -{ - if (self && --self->ref == 0) { -/* -#ifdef DEBUG - g_debug("Refcount to 0, removing ALL pictures from the cache:\n " - "Image 0x%lx", (gulong)self); -#endif -*/ - while (self->n_original > 0) - RemovePicture(self, &self->original, 0, &self->n_original); - while (self->n_resized > 0) - RemovePicture(self, &self->resized, 0, &self->n_resized); - g_free(self); - } -} - -/*! Add a new picture with the given RGBA pixel data and dimensions into the - RrImage. This adds an "original" picture to the image. -*/ -void RrImageAddPicture(RrImage *self, RrPixel32 *data, gint w, gint h) -{ - gint i; - RrImagePic *pic; - - /* make sure we don't already have this size.. */ - for (i = 0; i < self->n_original; ++i) - if (self->original[i]->width == w && self->original[i]->height == h) { -/* -#ifdef DEBUG - g_debug("Found duplicate ORIGINAL image:\n " - "Image 0x%lx, w %d h %d", (gulong)self, w, h); -#endif -*/ - return; - } - - /* remove any resized pictures of this same size */ - for (i = 0; i < self->n_resized; ++i) - if (self->resized[i]->width == w || self->resized[i]->height == h) { - RemovePicture(self, &self->resized, i, &self->n_resized); - break; - } - - /* add the new picture */ - pic = g_new(RrImagePic, 1); - RrImagePicInit(pic, w, h, g_memdup(data, w*h*sizeof(RrPixel32))); - AddPicture(self, &self->original, &self->n_original, pic); -} - -/*! Remove the picture from the RrImage which has the given dimensions. This - removes an "original" picture from the image. -*/ -void RrImageRemovePicture(RrImage *self, gint w, gint h) -{ - gint i; - - /* remove any resized pictures of this same size */ - for (i = 0; i < self->n_original; ++i) - if (self->original[i]->width == w && self->original[i]->height == h) { - RemovePicture(self, &self->original, i, &self->n_original); - break; - } -} - -/*! Draw an RrImage texture into a target pixel buffer. If the RrImage does - not contain a picture of the appropriate size, then one of its "original" - pictures will be resized and used (and stored in the RrImage as a "resized" - picture). - */ -void RrImageDrawImage(RrPixel32 *target, RrTextureImage *img, - gint target_w, gint target_h, - RrRect *area) -{ - gint i, min_diff, min_i, min_aspect_diff, min_aspect_i; - RrImage *self; - RrImagePic *pic; - gboolean free_pic; - - self = img->image; - pic = NULL; - free_pic = FALSE; - - /* is there an original of this size? (only the larger of - w or h has to be right cuz we maintain aspect ratios) */ - for (i = 0; i < self->n_original; ++i) - if ((self->original[i]->width >= self->original[i]->height && - self->original[i]->width == area->width) || - (self->original[i]->width <= self->original[i]->height && - self->original[i]->height == area->height)) - { - pic = self->original[i]; - break; - } - - /* is there a resize of this size? */ - for (i = 0; i < self->n_resized; ++i) - if ((self->resized[i]->width >= self->resized[i]->height && - self->resized[i]->width == area->width) || - (self->resized[i]->width <= self->resized[i]->height && - self->resized[i]->height == area->height)) - { - gint j; - RrImagePic *saved; - - /* save the selected one */ - saved = self->resized[i]; - - /* shift all the others down */ - for (j = i; j > 0; --j) - self->resized[j] = self->resized[j-1]; - - /* and move the selected one to the top of the list */ - self->resized[0] = saved; - - pic = self->resized[0]; - break; - } - - if (!pic) { - gdouble aspect; - - /* find an original with a close size */ - min_diff = min_aspect_diff = -1; - min_i = min_aspect_i = 0; - aspect = ((gdouble)area->width) / area->height; - for (i = 0; i < self->n_original; ++i) { - gint diff; - gint wdiff, hdiff; - gdouble myasp; - - /* our size difference metric.. */ - wdiff = self->original[i]->width - area->width; - hdiff = self->original[i]->height - area->height; - diff = (wdiff * wdiff) + (hdiff * hdiff); - - /* find the smallest difference */ - if (min_diff < 0 || diff < min_diff) { - min_diff = diff; - min_i = i; - } - /* and also find the smallest difference with the same aspect - ratio (and prefer this one) */ - myasp = ((gdouble)self->original[i]->width) / - self->original[i]->height; - if (ABS(aspect - myasp) < 0.0000001 && - (min_aspect_diff < 0 || diff < min_aspect_diff)) - { - min_aspect_diff = diff; - min_aspect_i = i; - } - } - - /* use the aspect ratio correct source if there is one */ - if (min_aspect_i >= 0) - min_i = min_aspect_i; - - /* resize the original to the given area */ - pic = ResizeImage(self->original[min_i]->data, - self->original[min_i]->width, - self->original[min_i]->height, - area->width, area->height); - - /* add the resized image to the image, as the first in the resized - list */ - if (self->n_resized >= self->cache->max_resized_saved) - /* remove the last one (last used one) */ - RemovePicture(self, &self->resized, self->n_resized - 1, - &self->n_resized); - if (self->cache->max_resized_saved) - /* add it to the top of the resized list */ - AddPicture(self, &self->resized, &self->n_resized, pic); - else - free_pic = TRUE; /* don't leak mem! */ - } - - g_assert(pic != NULL); - - DrawRGBA(target, target_w, target_h, - pic->data, pic->width, pic->height, - img->alpha, area); - if (free_pic) - RrImagePicFree(pic); -} diff --git a/render/image.h b/render/image.h deleted file mode 100644 index b478daf9..00000000 --- a/render/image.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- - - image.h for the Openbox window manager - Copyright (c) 2003-2007 Dana Jansens - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - See the COPYING file for a copy of the GNU General Public License. -*/ - -#ifndef __image_h -#define __image_h - -#include "render.h" -#include "geom.h" - -/*! Initialize an RrImagePicture to the specified dimensions and pixel data */ -void RrImagePicInit(RrImagePic *pic, gint w, gint h, RrPixel32 *data); - -void RrImageDrawImage(RrPixel32 *target, RrTextureImage *img, - gint target_w, gint target_h, - RrRect *area); -void RrImageDrawRGBA(RrPixel32 *target, RrTextureRGBA *rgba, - gint target_w, gint target_h, - RrRect *area); - -#endif diff --git a/render/imagecache.c b/render/imagecache.c deleted file mode 100644 index 9c605f9d..00000000 --- a/render/imagecache.c +++ /dev/null @@ -1,144 +0,0 @@ -/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- - - imagecache.c for the Openbox window manager - Copyright (c) 2008 Dana Jansens - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - See the COPYING file for a copy of the GNU General Public License. -*/ - -#include "render.h" -#include "imagecache.h" -#include "image.h" - -static gboolean RrImagePicEqual(const RrImagePic *p1, - const RrImagePic *p2); - -RrImageCache* RrImageCacheNew(gint max_resized_saved) -{ - RrImageCache *self; - - g_assert(max_resized_saved >= 0); - - self = g_new(RrImageCache, 1); - self->ref = 1; - self->max_resized_saved = max_resized_saved; - self->table = g_hash_table_new((GHashFunc)RrImagePicHash, - (GEqualFunc)RrImagePicEqual); - return self; -} - -void RrImageCacheRef(RrImageCache *self) -{ - ++self->ref; -} - -void RrImageCacheUnref(RrImageCache *self) -{ - if (self && --self->ref == 0) { - g_assert(g_hash_table_size(self->table) == 0); - g_hash_table_unref(self->table); - - g_free(self); - } -} - -/*! Finds an image in the cache, if it is already in there */ -RrImage* RrImageCacheFind(RrImageCache *self, - RrPixel32 *data, gint w, gint h) -{ - RrImagePic pic; - - RrImagePicInit(&pic, w, h, data); - return g_hash_table_lookup(self->table, &pic); -} - -#define hashsize(n) ((RrPixel32)1<<(n)) -#define hashmask(n) (hashsize(n)-1) -#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) -/* mix -- mix 3 32-bit values reversibly. */ -#define mix(a,b,c) \ -{ \ - a -= c; a ^= rot(c, 4); c += b; \ - b -= a; b ^= rot(a, 6); a += c; \ - c -= b; c ^= rot(b, 8); b += a; \ - a -= c; a ^= rot(c,16); c += b; \ - b -= a; b ^= rot(a,19); a += c; \ - c -= b; c ^= rot(b, 4); b += a; \ -} -/* final -- final mixing of 3 32-bit values (a,b,c) into c */ -#define final(a,b,c) \ -{ \ - c ^= b; c -= rot(b,14); \ - a ^= c; a -= rot(c,11); \ - b ^= a; b -= rot(a,25); \ - c ^= b; c -= rot(b,16); \ - a ^= c; a -= rot(c,4); \ - b ^= a; b -= rot(a,14); \ - c ^= b; c -= rot(b,24); \ -} - -/* This is a fast, reversable hash function called "lookup3", found here: - http://burtleburtle.net/bob/c/lookup3.c, by Bob Jenkins - - This hashing algorithm is "reversible", that is, not cryptographically - secure at all. But we don't care about that, we just want something to - tell when images are the same or different relatively quickly. -*/ -guint32 hashword(const guint32 *key, gint length, guint32 initval) -{ - guint32 a,b,c; - - /* Set up the internal state */ - a = b = c = 0xdeadbeef + (((guint32)length)<<2) + initval; - - /* handle most of the key */ - while (length > 3) - { - a += key[0]; - b += key[1]; - c += key[2]; - mix(a,b,c); - length -= 3; - key += 3; - } - - /* handle the last 3 guint32's */ - switch(length) /* all the case statements fall through */ - { - case 3: c+=key[2]; - case 2: b+=key[1]; - case 1: a+=key[0]; - final(a,b,c); - case 0: /* case 0: nothing left to add */ - break; - } - /* report the result */ - return c; -} - -/*! This is some arbitrary initial value for the hashing function. It's - constant so that you get the same result from the same data each time. -*/ -#define HASH_INITVAL 0xf00d - -guint RrImagePicHash(const RrImagePic *p) -{ - return hashword(p->data, p->width * p->height, HASH_INITVAL); -} - -static gboolean RrImagePicEqual(const RrImagePic *p1, - const RrImagePic *p2) -{ - return p1->width == p2->width && p1->height == p2->height && - p1->sum == p2->sum; -} diff --git a/render/imagecache.h b/render/imagecache.h deleted file mode 100644 index 4ad2deae..00000000 --- a/render/imagecache.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- - - imagecache.h for the Openbox window manager - Copyright (c) 2008 Dana Jansens - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - See the COPYING file for a copy of the GNU General Public License. -*/ - -#ifndef __imagecache_h -#define __imagecache_h - -#include - -struct _RrImagePic; - -guint RrImagePicHash(const struct _RrImagePic *p); - -/*! Create a new image cache. An image cache is basically a hash table to look - up RrImages. Each RrImage in the cache may contain one or more Pictures, - that is one or more actual copies of image data at various sizes. For eg, - for a window, all of its various icons are loaded into the same RrImage. - When an RrImage is drawn and a picture inside it needs to be resized, that - is also saved within the RrImage. - - For each picture that an RrImage has, the picture is hashed and that is used - as a key to find the RrImage. So, given any picture in any RrImage in the - cache, if you hash it, you will find the RrImage. -*/ -struct _RrImageCache { - gint ref; - /*! When an original picture is resized for an RrImage, the resized picture - is saved in the RrImage. This specifies how many pictures should be - saved at a time. When this is exceeded, the least recently used - "resized" picture is deleted. - */ - gint max_resized_saved; - - GHashTable *table; -}; - -#endif diff --git a/render/instance.c b/render/instance.c deleted file mode 100644 index b867815c..00000000 --- a/render/instance.c +++ /dev/null @@ -1,309 +0,0 @@ -/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- - - instance.c for the Openbox window manager - Copyright (c) 2006 Mikael Magnusson - Copyright (c) 2003-2007 Dana Jansens - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - See the COPYING file for a copy of the GNU General Public License. -*/ - -#include "render.h" -#include "instance.h" - -static RrInstance *definst = NULL; - -static void RrTrueColorSetup (RrInstance *inst); -static void RrPseudoColorSetup (RrInstance *inst); - -#ifdef DEBUG -#include "color.h" -#endif -static void -dest(gpointer data) -{ -#ifdef DEBUG - RrColor *c = data; - if (c->refcount > 0) - g_error("color %d (%d,%d,%d) in hash table with %d " - "leftover references", - c->id, RrColorRed(c), RrColorGreen(c), RrColorBlue(c), - c->refcount); -#endif -} - -#if 0 -static void f(gpointer key, gpointer value, gpointer n) -{ - RrColor *c = value; - if (c->id == *(gint*)n) - g_message("color %d has %d references", c->id, c->refcount); -} - -void print_refs(gint id) -{ - g_hash_table_foreach(RrColorHash(definst), f, &id); -} -#endif - -RrInstance* RrInstanceNew (Display *display, gint screen) -{ - g_type_init(); /* supposedly needed for pango but seems to work without */ - - definst = g_new (RrInstance, 1); - definst->display = display; - definst->screen = screen; - - definst->depth = DefaultDepth(display, screen); - definst->visual = DefaultVisual(display, screen); - definst->colormap = DefaultColormap(display, screen); - definst->pango = pango_xft_get_context(display, screen); - - definst->pseudo_colors = NULL; - - definst->color_hash = g_hash_table_new_full(g_int_hash, g_int_equal, - NULL, dest); - - switch (definst->visual->class) { - case TrueColor: - RrTrueColorSetup(definst); - break; - case PseudoColor: - case StaticColor: - case GrayScale: - case StaticGray: - RrPseudoColorSetup(definst); - break; - default: - g_critical("Unsupported visual class"); - g_free (definst); - return definst = NULL; - } - return definst; -} - -static void RrTrueColorSetup (RrInstance *inst) -{ - gulong red_mask, green_mask, blue_mask; - XImage *timage = NULL; - - timage = XCreateImage(inst->display, inst->visual, inst->depth, - ZPixmap, 0, NULL, 1, 1, 32, 0); - g_assert(timage != NULL); - /* find the offsets for each color in the visual's masks */ - inst->red_mask = red_mask = timage->red_mask; - inst->green_mask = green_mask = timage->green_mask; - inst->blue_mask = blue_mask = timage->blue_mask; - - inst->red_offset = 0; - inst->green_offset = 0; - inst->blue_offset = 0; - - while (! (red_mask & 1)) { inst->red_offset++; red_mask >>= 1; } - while (! (green_mask & 1)) { inst->green_offset++; green_mask >>= 1; } - while (! (blue_mask & 1)) { inst->blue_offset++; blue_mask >>= 1; } - - inst->red_shift = inst->green_shift = inst->blue_shift = 8; - while (red_mask) { red_mask >>= 1; inst->red_shift--; } - while (green_mask) { green_mask >>= 1; inst->green_shift--; } - while (blue_mask) { blue_mask >>= 1; inst->blue_shift--; } - XFree(timage); -} - -#define RrPseudoNcolors(inst) (1 << (inst->pseudo_bpc * 3)) - -static void RrPseudoColorSetup (RrInstance *inst) -{ - XColor icolors[256]; - gint tr, tg, tb, n, r, g, b, i, incolors, ii; - gulong dev; - gint cpc, _ncolors; - - /* determine the number of colors and the bits-per-color */ - inst->pseudo_bpc = 2; /* XXX THIS SHOULD BE A USER OPTION */ - g_assert(inst->pseudo_bpc >= 1); - _ncolors = RrPseudoNcolors(inst); - - if (_ncolors > 1 << inst->depth) { - g_message("Invalid colormap size. Resizing."); - inst->pseudo_bpc = 1 << (inst->depth/3) >> 3; - _ncolors = 1 << (inst->pseudo_bpc * 3); - } - - /* build a color cube */ - inst->pseudo_colors = g_new(XColor, _ncolors); - cpc = 1 << inst->pseudo_bpc; /* colors per channel */ - - for (n = 0, r = 0; r < cpc; r++) - for (g = 0; g < cpc; g++) - for (b = 0; b < cpc; b++, n++) { - tr = (gint)(((gfloat)(r)/(gfloat)(cpc-1)) * 0xFF); - tg = (gint)(((gfloat)(g)/(gfloat)(cpc-1)) * 0xFF); - tb = (gint)(((gfloat)(b)/(gfloat)(cpc-1)) * 0xFF); - inst->pseudo_colors[n].red = tr | tr << 8; - inst->pseudo_colors[n].green = tg | tg << 8; - inst->pseudo_colors[n].blue = tb | tb << 8; - /* used to track allocation */ - inst->pseudo_colors[n].flags = DoRed|DoGreen|DoBlue; - } - - /* allocate the colors */ - for (i = 0; i < _ncolors; i++) - if (!XAllocColor(inst->display, inst->colormap, - &inst->pseudo_colors[i])) - inst->pseudo_colors[i].flags = 0; /* mark it as unallocated */ - - /* try allocate any colors that failed allocation above */ - - /* get the allocated values from the X server - (only the first 256 XXX why!?) - */ - incolors = (((1 << inst->depth) > 256) ? 256 : (1 << inst->depth)); - for (i = 0; i < incolors; i++) - icolors[i].pixel = i; - XQueryColors(inst->display, inst->colormap, icolors, incolors); - - /* try match unallocated ones */ - for (i = 0; i < _ncolors; i++) { - if (!inst->pseudo_colors[i].flags) { /* if it wasn't allocated... */ - gulong closest = 0xffffffff, close = 0; - for (ii = 0; ii < incolors; ii++) { - /* find deviations */ - r = (inst->pseudo_colors[i].red - icolors[ii].red) & 0xff; - g = (inst->pseudo_colors[i].green - icolors[ii].green) & 0xff; - b = (inst->pseudo_colors[i].blue - icolors[ii].blue) & 0xff; - /* find a weighted absolute deviation */ - dev = (r * r) + (g * g) + (b * b); - - if (dev < closest) { - closest = dev; - close = ii; - } - } - - inst->pseudo_colors[i].red = icolors[close].red; - inst->pseudo_colors[i].green = icolors[close].green; - inst->pseudo_colors[i].blue = icolors[close].blue; - inst->pseudo_colors[i].pixel = icolors[close].pixel; - - /* try alloc this closest color, it had better succeed! */ - if (XAllocColor(inst->display, inst->colormap, - &inst->pseudo_colors[i])) - /* mark as alloced */ - inst->pseudo_colors[i].flags = DoRed|DoGreen|DoBlue; - else - /* wtf has gone wrong, its already alloced for chissake! */ - g_assert_not_reached(); - } - } -} - -void RrInstanceFree (RrInstance *inst) -{ - if (inst) { - if (inst == definst) definst = NULL; - g_free(inst->pseudo_colors); - g_hash_table_destroy(inst->color_hash); - g_object_unref(inst->pango); - g_free(inst); - } -} - -Display* RrDisplay (const RrInstance *inst) -{ - return (inst ? inst : definst)->display; -} - -gint RrScreen (const RrInstance *inst) -{ - return (inst ? inst : definst)->screen; -} - -Window RrRootWindow (const RrInstance *inst) -{ - return RootWindow (RrDisplay (inst), RrScreen (inst)); -} - -Visual *RrVisual (const RrInstance *inst) -{ - return (inst ? inst : definst)->visual; -} - -gint RrDepth (const RrInstance *inst) -{ - return (inst ? inst : definst)->depth; -} - -Colormap RrColormap (const RrInstance *inst) -{ - return (inst ? inst : definst)->colormap; -} - -gint RrRedOffset (const RrInstance *inst) -{ - return (inst ? inst : definst)->red_offset; -} - -gint RrGreenOffset (const RrInstance *inst) -{ - return (inst ? inst : definst)->green_offset; -} - -gint RrBlueOffset (const RrInstance *inst) -{ - return (inst ? inst : definst)->blue_offset; -} - -gint RrRedShift (const RrInstance *inst) -{ - return (inst ? inst : definst)->red_shift; -} - -gint RrGreenShift (const RrInstance *inst) -{ - return (inst ? inst : definst)->green_shift; -} - -gint RrBlueShift (const RrInstance *inst) -{ - return (inst ? inst : definst)->blue_shift; -} - -gint RrRedMask (const RrInstance *inst) -{ - return (inst ? inst : definst)->red_mask; -} - -gint RrGreenMask (const RrInstance *inst) -{ - return (inst ? inst : definst)->green_mask; -} - -gint RrBlueMask (const RrInstance *inst) -{ - return (inst ? inst : definst)->blue_mask; -} - -guint RrPseudoBPC (const RrInstance *inst) -{ - return (inst ? inst : definst)->pseudo_bpc; -} - -XColor *RrPseudoColors (const RrInstance *inst) -{ - return (inst ? inst : definst)->pseudo_colors; -} - -GHashTable* RrColorHash (const RrInstance *inst) -{ - return (inst ? inst : definst)->color_hash; -} diff --git a/render/instance.h b/render/instance.h deleted file mode 100644 index 324f061a..00000000 --- a/render/instance.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- - - instance.h for the Openbox window manager - Copyright (c) 2003-2007 Dana Jansens - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - See the COPYING file for a copy of the GNU General Public License. -*/ - -#ifndef __render_instance_h -#define __render_instance_h - -#include -#include -#include - -struct _RrInstance { - Display *display; - gint screen; - - Visual *visual; - gint depth; - Colormap colormap; - PangoContext *pango; - - gint red_offset; - gint green_offset; - gint blue_offset; - - gint red_shift; - gint green_shift; - gint blue_shift; - - gint red_mask; - gint green_mask; - gint blue_mask; - - gint pseudo_bpc; - XColor *pseudo_colors; - - GHashTable *color_hash; -}; - -guint RrPseudoBPC (const RrInstance *inst); -XColor* RrPseudoColors (const RrInstance *inst); -GHashTable* RrColorHash (const RrInstance *inst); - -#endif diff --git a/render/mask.c b/render/mask.c deleted file mode 100644 index b6e3c443..00000000 --- a/render/mask.c +++ /dev/null @@ -1,82 +0,0 @@ -/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- - - mask.c for the Openbox window manager - Copyright (c) 2003-2007 Dana Jansens - Copyright (c) 2003 Derek Foreman - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - See the COPYING file for a copy of the GNU General Public License. -*/ - -#include "render.h" -#include "color.h" -#include "mask.h" - -RrPixmapMask *RrPixmapMaskNew(const RrInstance *inst, - gint w, gint h, const gchar *data) -{ - RrPixmapMask *m = g_new(RrPixmapMask, 1); - m->inst = inst; - m->width = w; - m->height = h; - /* round up to nearest byte */ - m->data = g_memdup(data, (w + 7) / 8 * h); - m->mask = XCreateBitmapFromData(RrDisplay(inst), RrRootWindow(inst), - data, w, h); - return m; -} - -void RrPixmapMaskFree(RrPixmapMask *m) -{ - if (m) { - XFreePixmap(RrDisplay(m->inst), m->mask); - g_free(m->data); - g_free(m); - } -} - -void RrPixmapMaskDraw(Pixmap p, const RrTextureMask *m, const RrRect *area) -{ - gint x, y; - if (m->mask == NULL) return; /* no mask given */ - - /* set the clip region */ - x = area->x + (area->width - m->mask->width) / 2; - y = area->y + (area->height - m->mask->height) / 2; - - if (x < 0) x = 0; - if (y < 0) y = 0; - - XSetClipMask(RrDisplay(m->mask->inst), RrColorGC(m->color), m->mask->mask); - XSetClipOrigin(RrDisplay(m->mask->inst), RrColorGC(m->color), x, y); - - /* fill in the clipped region */ - XFillRectangle(RrDisplay(m->mask->inst), p, RrColorGC(m->color), x, y, - x + m->mask->width, y + m->mask->height); - - /* unset the clip region */ - XSetClipMask(RrDisplay(m->mask->inst), RrColorGC(m->color), None); - XSetClipOrigin(RrDisplay(m->mask->inst), RrColorGC(m->color), 0, 0); -} - -RrPixmapMask *RrPixmapMaskCopy(const RrPixmapMask *src) -{ - RrPixmapMask *m = g_new(RrPixmapMask, 1); - m->inst = src->inst; - m->width = src->width; - m->height = src->height; - /* round up to nearest byte */ - m->data = g_memdup(src->data, (src->width + 7) / 8 * src->height); - m->mask = XCreateBitmapFromData(RrDisplay(m->inst), RrRootWindow(m->inst), - m->data, m->width, m->height); - return m; -} diff --git a/render/mask.h b/render/mask.h deleted file mode 100644 index 4dc85031..00000000 --- a/render/mask.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- - - mask.h for the Openbox window manager - Copyright (c) 2003-2007 Dana Jansens - Copyright (c) 2003 Derek Foreman - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - See the COPYING file for a copy of the GNU General Public License. -*/ - -#ifndef __mask_h -#define __mask_h - -#include "render.h" -#include "geom.h" - -RrPixmapMask *RrPixmapMaskNew(const RrInstance *inst, - gint w, gint h, const gchar *data); -void RrPixmapMaskFree(RrPixmapMask *m); -RrPixmapMask *RrPixmapMaskCopy(const RrPixmapMask *src); -void RrPixmapMaskDraw(Pixmap p, const RrTextureMask *m, const RrRect *area); - -#endif diff --git a/render/obrender-4.0.pc.in b/render/obrender-4.0.pc.in deleted file mode 100644 index 539606a4..00000000 --- a/render/obrender-4.0.pc.in +++ /dev/null @@ -1,14 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -xcflags=@X_CFLAGS@ -xlibs=@X_LIBS@ - -Name: ObRender -Description: Openbox Render Library -Version: @RR_VERSION@ -Requires: obt-4.0 glib-2.0 xft pangoxft -Libs: -L${libdir} -lobrender ${xlibs} -Cflags: -I${includedir}/openbox/@RR_VERSION@ ${xcflags} diff --git a/render/render.c b/render/render.c deleted file mode 100644 index 20002e32..00000000 --- a/render/render.c +++ /dev/null @@ -1,564 +0,0 @@ -/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- - - render.c for the Openbox window manager - Copyright (c) 2006 Mikael Magnusson - Copyright (c) 2003-2007 Dana Jansens - Copyright (c) 2003 Derek Foreman - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - See the COPYING file for a copy of the GNU General Public License. -*/ - -#include "render.h" -#include "gradient.h" -#include "font.h" -#include "mask.h" -#include "color.h" -#include "image.h" -#include "theme.h" - -#include -#include -#include -#include - -#ifdef HAVE_STDLIB_H -# include -#endif - -static void pixel_data_to_pixmap(RrAppearance *l, - gint x, gint y, gint w, gint h); - -Pixmap RrPaintPixmap(RrAppearance *a, gint w, gint h) -{ - gint i, transferred = 0, force_transfer = 0; - Pixmap oldp = None; - RrRect tarea; /* area in which to draw textures */ - gboolean resized; - - if (w <= 0 || h <= 0) return None; - - if (a->surface.parentx < 0 || a->surface.parenty < 0) { - /* ob_debug("Invalid parent co-ordinates\n"); */ - return None; - } - - if (a->surface.grad == RR_SURFACE_PARENTREL && - (a->surface.parentx >= a->surface.parent->w || - a->surface.parenty >= a->surface.parent->h)) - { - return None; - } - - resized = (a->w != w || a->h != h); - - oldp = a->pixmap; /* save to free after changing the visible pixmap */ - a->pixmap = XCreatePixmap(RrDisplay(a->inst), - RrRootWindow(a->inst), - w, h, RrDepth(a->inst)); - - g_assert(a->pixmap != None); - a->w = w; - a->h = h; - - if (a->xftdraw != NULL) - XftDrawDestroy(a->xftdraw); - a->xftdraw = XftDrawCreate(RrDisplay(a->inst), a->pixmap, - RrVisual(a->inst), RrColormap(a->inst)); - g_assert(a->xftdraw != NULL); - - if (resized) { - g_free(a->surface.pixel_data); - a->surface.pixel_data = g_new(RrPixel32, w * h); - } - - RrRender(a, w, h); - - { - gint l, t, r, b; - RrMargins(a, &l, &t, &r, &b); - RECT_SET(tarea, l, t, w - l - r, h - t - b); - } - - for (i = 0; i < a->textures; i++) { - switch (a->texture[i].type) { - case RR_TEXTURE_NONE: - break; - case RR_TEXTURE_TEXT: - if (!transferred) { - transferred = 1; - if ((a->surface.grad != RR_SURFACE_SOLID) - || (a->surface.interlaced)) - pixel_data_to_pixmap(a, 0, 0, w, h); - } - if (a->xftdraw == NULL) { - a->xftdraw = XftDrawCreate(RrDisplay(a->inst), a->pixmap, - RrVisual(a->inst), - RrColormap(a->inst)); - } - RrFontDraw(a->xftdraw, &a->texture[i].data.text, &tarea); - break; - case RR_TEXTURE_LINE_ART: - if (!transferred) { - transferred = 1; - if ((a->surface.grad != RR_SURFACE_SOLID) - || (a->surface.interlaced)) - pixel_data_to_pixmap(a, 0, 0, w, h); - } - XDrawLine(RrDisplay(a->inst), a->pixmap, - RrColorGC(a->texture[i].data.lineart.color), - a->texture[i].data.lineart.x1, - a->texture[i].data.lineart.y1, - a->texture[i].data.lineart.x2, - a->texture[i].data.lineart.y2); - break; - case RR_TEXTURE_MASK: - if (!transferred) { - transferred = 1; - if ((a->surface.grad != RR_SURFACE_SOLID) - || (a->surface.interlaced)) - pixel_data_to_pixmap(a, 0, 0, w, h); - } - RrPixmapMaskDraw(a->pixmap, &a->texture[i].data.mask, &tarea); - break; - case RR_TEXTURE_IMAGE: - g_assert(!transferred); - { - RrRect narea = tarea; - RrTextureImage *img = &a->texture[i].data.image; - narea.x += img->tx; - narea.width -= img->tx; - narea.y += img->ty; - narea.height -= img->ty; - if (img->twidth) - narea.width = MIN(narea.width, img->twidth); - if (img->theight) - narea.height = MIN(narea.height, img->theight); - RrImageDrawImage(a->surface.pixel_data, - &a->texture[i].data.image, - a->w, a->h, - &narea); - } - force_transfer = 1; - break; - case RR_TEXTURE_RGBA: - g_assert(!transferred); - { - RrRect narea = tarea; - RrTextureRGBA *rgb = &a->texture[i].data.rgba; - narea.x += rgb->tx; - narea.width -= rgb->tx; - narea.y += rgb->ty; - narea.height -= rgb->ty; - if (rgb->twidth) - narea.width = MIN(narea.width, rgb->twidth); - if (rgb->theight) - narea.height = MIN(narea.height, rgb->theight); - RrImageDrawRGBA(a->surface.pixel_data, - &a->texture[i].data.rgba, - a->w, a->h, - &narea); - } - force_transfer = 1; - break; - } - } - - if (!transferred) { - transferred = 1; - if ((a->surface.grad != RR_SURFACE_SOLID) || (a->surface.interlaced) || - force_transfer) - { - pixel_data_to_pixmap(a, 0, 0, w, h); - } - } - - return oldp; -} - -void RrPaint(RrAppearance *a, Window win, gint w, gint h) -{ - Pixmap oldp; - - oldp = RrPaintPixmap(a, w, h); - XSetWindowBackgroundPixmap(RrDisplay(a->inst), win, a->pixmap); - XClearWindow(RrDisplay(a->inst), win); - /* free this after changing the visible pixmap */ - if (oldp) XFreePixmap(RrDisplay(a->inst), oldp); -} - -RrAppearance *RrAppearanceNew(const RrInstance *inst, gint numtex) -{ - RrAppearance *out; - - out = g_new0(RrAppearance, 1); - out->inst = inst; - out->textures = numtex; - out->surface.bevel_light_adjust = 128; - out->surface.bevel_dark_adjust = 64; - if (numtex) out->texture = g_new0(RrTexture, numtex); - - return out; -} - -void RrAppearanceRemoveTextures(RrAppearance *a) -{ - g_free(a->texture); - a->textures = 0; -} - -void RrAppearanceAddTextures(RrAppearance *a, gint numtex) -{ - g_assert(a->textures == 0); - - a->textures = numtex; - if (numtex) a->texture = g_new0(RrTexture, numtex); -} - -void RrAppearanceClearTextures(RrAppearance *a) -{ - memset(a->texture, 0, a->textures * sizeof(RrTexture)); -} - -RrAppearance *RrAppearanceCopy(RrAppearance *orig) -{ - RrSurface *spo, *spc; - RrAppearance *copy = g_new(RrAppearance, 1); - - copy->inst = orig->inst; - - spo = &(orig->surface); - spc = &(copy->surface); - spc->grad = spo->grad; - spc->relief = spo->relief; - spc->bevel = spo->bevel; - if (spo->primary != NULL) - spc->primary = RrColorNew(copy->inst, - spo->primary->r, - spo->primary->g, - spo->primary->b); - else spc->primary = NULL; - - if (spo->secondary != NULL) - spc->secondary = RrColorNew(copy->inst, - spo->secondary->r, - spo->secondary->g, - spo->secondary->b); - else spc->secondary = NULL; - - if (spo->border_color != NULL) - spc->border_color = RrColorNew(copy->inst, - spo->border_color->r, - spo->border_color->g, - spo->border_color->b); - else spc->border_color = NULL; - - if (spo->interlace_color != NULL) - spc->interlace_color = RrColorNew(copy->inst, - spo->interlace_color->r, - spo->interlace_color->g, - spo->interlace_color->b); - else spc->interlace_color = NULL; - - if (spo->bevel_dark != NULL) - spc->bevel_dark = RrColorNew(copy->inst, - spo->bevel_dark->r, - spo->bevel_dark->g, - spo->bevel_dark->b); - else spc->bevel_dark = NULL; - - if (spo->bevel_light != NULL) - spc->bevel_light = RrColorNew(copy->inst, - spo->bevel_light->r, - spo->bevel_light->g, - spo->bevel_light->b); - else spc->bevel_light = NULL; - - if (spo->split_primary != NULL) - spc->split_primary = RrColorNew(copy->inst, - spo->split_primary->r, - spo->split_primary->g, - spo->split_primary->b); - else spc->split_primary = NULL; - - if (spo->split_secondary != NULL) - spc->split_secondary = RrColorNew(copy->inst, - spo->split_secondary->r, - spo->split_secondary->g, - spo->split_secondary->b); - else spc->split_secondary = NULL; - - spc->interlaced = spo->interlaced; - spc->bevel_light_adjust = spo->bevel_light_adjust; - spc->bevel_dark_adjust = spo->bevel_dark_adjust; - spc->border = spo->border; - spc->parent = NULL; - spc->parentx = spc->parenty = 0; - spc->pixel_data = NULL; - - copy->textures = orig->textures; - copy->texture = g_memdup(orig->texture, - orig->textures * sizeof(RrTexture)); - copy->pixmap = None; - copy->xftdraw = NULL; - copy->w = copy->h = 0; - return copy; -} - -void RrAppearanceFree(RrAppearance *a) -{ - if (a) { - RrSurface *p; - if (a->pixmap != None) XFreePixmap(RrDisplay(a->inst), a->pixmap); - if (a->xftdraw != NULL) XftDrawDestroy(a->xftdraw); - if (a->textures) - g_free(a->texture); - p = &a->surface; - RrColorFree(p->primary); - RrColorFree(p->secondary); - RrColorFree(p->border_color); - RrColorFree(p->interlace_color); - RrColorFree(p->bevel_dark); - RrColorFree(p->bevel_light); - RrColorFree(p->split_primary); - RrColorFree(p->split_secondary); - g_free(p->pixel_data); - p->pixel_data = NULL; - g_free(a); - } -} - -static void pixel_data_to_pixmap(RrAppearance *l, - gint x, gint y, gint w, gint h) -{ - RrPixel32 *in, *scratch; - Pixmap out; - XImage *im = NULL; - im = XCreateImage(RrDisplay(l->inst), RrVisual(l->inst), RrDepth(l->inst), - ZPixmap, 0, NULL, w, h, 32, 0); - g_assert(im != NULL); - - in = l->surface.pixel_data; - out = l->pixmap; - -/* this malloc is a complete waste of time on normal 32bpp - as reduce_depth just sets im->data = data and returns -*/ - scratch = g_new(RrPixel32, im->width * im->height); - im->data = (gchar*) scratch; - RrReduceDepth(l->inst, in, im); - XPutImage(RrDisplay(l->inst), out, - DefaultGC(RrDisplay(l->inst), RrScreen(l->inst)), - im, 0, 0, x, y, w, h); - im->data = NULL; - XDestroyImage(im); - g_free(scratch); -} - -void RrMargins (RrAppearance *a, gint *l, gint *t, gint *r, gint *b) -{ - *l = *t = *r = *b = 0; - - if (a->surface.grad != RR_SURFACE_PARENTREL) { - if (a->surface.relief != RR_RELIEF_FLAT) { - switch (a->surface.bevel) { - case RR_BEVEL_1: - *l = *t = *r = *b = 1; - break; - case RR_BEVEL_2: - *l = *t = *r = *b = 2; - break; - } - } else if (a->surface.border) { - *l = *t = *r = *b = 1; - } - } -} - -void RrMinSize(RrAppearance *a, gint *w, gint *h) -{ - *w = RrMinWidth(a); - *h = RrMinHeight(a); -} - -gint RrMinWidth(RrAppearance *a) -{ - gint i; - RrSize *m; - gint l, t, r, b; - gint w = 0; - - RrMargins(a, &l, &t, &r, &b); - - for (i = 0; i < a->textures; ++i) { - switch (a->texture[i].type) { - case RR_TEXTURE_NONE: - break; - case RR_TEXTURE_MASK: - w = MAX(w, a->texture[i].data.mask.mask->width); - break; - case RR_TEXTURE_TEXT: - m = RrFontMeasureString(a->texture[i].data.text.font, - a->texture[i].data.text.string, - a->texture[i].data.text.shadow_offset_x, - a->texture[i].data.text.shadow_offset_y, - a->texture[i].data.text.flow, - a->texture[i].data.text.maxwidth); - w = MAX(w, m->width); - g_free(m); - break; - case RR_TEXTURE_RGBA: - w += MAX(w, a->texture[i].data.rgba.width); - break; - case RR_TEXTURE_IMAGE: - /* images resize so they don't contribute anything to the min */ - break; - case RR_TEXTURE_LINE_ART: - w = MAX(w, MAX(a->texture[i].data.lineart.x1 - l - r, - a->texture[i].data.lineart.x2 - l - r)); - break; - } - } - - w += l + r; - - if (w < 1) w = 1; - return w; -} - -gint RrMinHeight(RrAppearance *a) -{ - gint i; - gint l, t, r, b; - RrSize *m; - gint h = 0; - - RrMargins(a, &l, &t, &r, &b); - - for (i = 0; i < a->textures; ++i) { - switch (a->texture[i].type) { - case RR_TEXTURE_NONE: - break; - case RR_TEXTURE_MASK: - h = MAX(h, a->texture[i].data.mask.mask->height); - break; - case RR_TEXTURE_TEXT: - if (a->texture[i].data.text.flow) { - g_assert(a->texture[i].data.text.string != NULL); - - m = RrFontMeasureString - (a->texture[i].data.text.font, - a->texture[i].data.text.string, - a->texture[i].data.text.shadow_offset_x, - a->texture[i].data.text.shadow_offset_y, - a->texture[i].data.text.flow, - a->texture[i].data.text.maxwidth); - h += MAX(h, m->height); - g_free(m); - } - else - h += MAX(h, - RrFontHeight - (a->texture[i].data.text.font, - a->texture[i].data.text.shadow_offset_y)); - break; - case RR_TEXTURE_RGBA: - h += MAX(h, a->texture[i].data.rgba.height); - break; - case RR_TEXTURE_IMAGE: - /* images resize so they don't contribute anything to the min */ - break; - case RR_TEXTURE_LINE_ART: - h = MAX(h, MAX(a->texture[i].data.lineart.y1 - t - b, - a->texture[i].data.lineart.y2 - t - b)); - break; - } - } - - h += t + b; - - if (h < 1) h = 1; - return h; -} - -static void reverse_bits(gchar *c, gint n) -{ - gint i; - for (i = 0; i < n; i++, c++) - *c = (((*c * 0x0802UL & 0x22110UL) | - (*c * 0x8020UL & 0x88440UL)) * 0x10101UL) >> 16; -} - -gboolean RrPixmapToRGBA(const RrInstance *inst, - Pixmap pmap, Pixmap mask, - gint *w, gint *h, RrPixel32 **data) -{ - Window xr; - gint xx, xy; - guint pw, ph, mw, mh, xb, xd, i, x, y, di; - XImage *xi, *xm = NULL; - - if (!XGetGeometry(RrDisplay(inst), pmap, - &xr, &xx, &xy, &pw, &ph, &xb, &xd)) - return FALSE; - - if (mask) { - if (!XGetGeometry(RrDisplay(inst), mask, - &xr, &xx, &xy, &mw, &mh, &xb, &xd)) - return FALSE; - if (pw != mw || ph != mh || xd != 1) - return FALSE; - } - - xi = XGetImage(RrDisplay(inst), pmap, - 0, 0, pw, ph, 0xffffffff, ZPixmap); - if (!xi) - return FALSE; - - if (mask) { - xm = XGetImage(RrDisplay(inst), mask, - 0, 0, mw, mh, 0xffffffff, ZPixmap); - if (!xm) { - XDestroyImage(xi); - return FALSE; - } - if ((xm->bits_per_pixel == 1) && (xm->bitmap_bit_order != LSBFirst)) - reverse_bits(xm->data, xm->bytes_per_line * xm->height); - } - - if ((xi->bits_per_pixel == 1) && (xi->bitmap_bit_order != LSBFirst)) - reverse_bits(xi->data, xi->bytes_per_line * xi->height); - - *data = g_new(RrPixel32, pw * ph); - RrIncreaseDepth(inst, *data, xi); - - if (mask) { - /* apply transparency from the mask */ - di = 0; - for (i = 0, y = 0; y < ph; ++y) { - for (x = 0; x < pw; ++x, ++i) { - if (!((((unsigned)xm->data[di + x / 8]) >> (x % 8)) & 0x1)) - (*data)[i] &= ~(0xff << RrDefaultAlphaOffset); - } - di += xm->bytes_per_line; - } - } - - *w = pw; - *h = ph; - - XDestroyImage(xi); - if (mask) - XDestroyImage(xm); - - return TRUE; -} diff --git a/render/render.h b/render/render.h deleted file mode 100644 index 706843e3..00000000 --- a/render/render.h +++ /dev/null @@ -1,350 +0,0 @@ -/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- - - render.h for the Openbox window manager - Copyright (c) 2006 Mikael Magnusson - Copyright (c) 2003-2007 Dana Jansens - Copyright (c) 2003 Derek Foreman - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - See the COPYING file for a copy of the GNU General Public License. -*/ - -#ifndef __render_h -#define __render_h - -#include "geom.h" -#include "render/version.h" - -#include /* some platforms dont include this as needed for Xft */ -#include -#include - -G_BEGIN_DECLS - -typedef union _RrTextureData RrTextureData; -typedef struct _RrAppearance RrAppearance; -typedef struct _RrSurface RrSurface; -typedef struct _RrFont RrFont; -typedef struct _RrTexture RrTexture; -typedef struct _RrTextureMask RrTextureMask; -typedef struct _RrTextureRGBA RrTextureRGBA; -typedef struct _RrTextureImage RrTextureImage; -typedef struct _RrTextureText RrTextureText; -typedef struct _RrTextureLineArt RrTextureLineArt; -typedef struct _RrPixmapMask RrPixmapMask; -typedef struct _RrInstance RrInstance; -typedef struct _RrColor RrColor; -typedef struct _RrImage RrImage; -typedef struct _RrImagePic RrImagePic; -typedef struct _RrImageCache RrImageCache; - -typedef guint32 RrPixel32; -typedef guint16 RrPixel16; -typedef guchar RrPixel8; - -typedef enum { - RR_RELIEF_FLAT, - RR_RELIEF_RAISED, - RR_RELIEF_SUNKEN -} RrReliefType; - -typedef enum { - RR_BEVEL_1, - RR_BEVEL_2 -} RrBevelType; - -typedef enum { - RR_SURFACE_NONE, - RR_SURFACE_PARENTREL, - RR_SURFACE_SOLID, - RR_SURFACE_SPLIT_VERTICAL, - RR_SURFACE_HORIZONTAL, - RR_SURFACE_VERTICAL, - RR_SURFACE_DIAGONAL, - RR_SURFACE_CROSS_DIAGONAL, - RR_SURFACE_PYRAMID, - RR_SURFACE_MIRROR_HORIZONTAL -} RrSurfaceColorType; - -typedef enum { - RR_TEXTURE_NONE, - RR_TEXTURE_MASK, - RR_TEXTURE_TEXT, - RR_TEXTURE_LINE_ART, - RR_TEXTURE_RGBA, - RR_TEXTURE_IMAGE -} RrTextureType; - -typedef enum { - RR_JUSTIFY_LEFT, - RR_JUSTIFY_CENTER, - RR_JUSTIFY_RIGHT -} RrJustify; - -/* Put middle first so it's the default */ -typedef enum { - RR_ELLIPSIZE_MIDDLE, - RR_ELLIPSIZE_NONE, - RR_ELLIPSIZE_START, - RR_ELLIPSIZE_END -} RrEllipsizeMode; - -typedef enum { - RR_FONTWEIGHT_LIGHT, - RR_FONTWEIGHT_NORMAL, - RR_FONTWEIGHT_SEMIBOLD, - RR_FONTWEIGHT_BOLD, - RR_FONTWEIGHT_ULTRABOLD -} RrFontWeight; - -typedef enum { - RR_FONTSLANT_NORMAL, - RR_FONTSLANT_ITALIC, - RR_FONTSLANT_OBLIQUE -} RrFontSlant; - -struct _RrSurface { - RrSurfaceColorType grad; - RrReliefType relief; - RrBevelType bevel; - RrColor *primary; - RrColor *secondary; - RrColor *border_color; - RrColor *bevel_dark; - RrColor *bevel_light; - RrColor *interlace_color; - gboolean interlaced; - gboolean border; - RrAppearance *parent; - gint parentx; - gint parenty; - RrPixel32 *pixel_data; - gint bevel_dark_adjust; /* 0-255, default is 64 */ - gint bevel_light_adjust; /* 0-255, default is 128 */ - RrColor *split_primary; - RrColor *split_secondary; -}; - -struct _RrTextureText { - RrFont *font; - RrJustify justify; - RrColor *color; - const gchar *string; - gint shadow_offset_x; - gint shadow_offset_y; - RrColor *shadow_color; - gboolean shortcut; /*!< Underline a character */ - guint shortcut_pos; /*!< Position in bytes of the character to underline */ - RrEllipsizeMode ellipsize; - gboolean flow; /* allow multiple lines. must set maxwidth below */ - gint maxwidth; - guchar shadow_alpha; /* at the bottom to improve alignment */ -}; - -struct _RrPixmapMask { - const RrInstance *inst; - Pixmap mask; - gint width; - gint height; - gchar *data; -}; - -struct _RrTextureMask { - RrColor *color; - RrPixmapMask *mask; -}; - -struct _RrTextureRGBA { - gint width; - gint height; - gint alpha; - RrPixel32 *data; - /* size and position to draw at (if these are zero, then it will be - drawn to fill the entire texture */ - gint tx; - gint ty; - gint twidth; - gint theight; -}; - -struct _RrTextureImage { - RrImage *image; - gint alpha; - /* size and position to draw at (if these are zero, then it will be - drawn to fill the entire texture */ - gint tx; - gint ty; - gint twidth; - gint theight; -}; - -struct _RrTextureLineArt { - RrColor *color; - gint x1; - gint y1; - gint x2; - gint y2; -}; - -union _RrTextureData { - RrTextureRGBA rgba; - RrTextureImage image; - RrTextureText text; - RrTextureMask mask; - RrTextureLineArt lineart; -}; - -struct _RrTexture { - /* If changing the type of a texture, you should DEFINITELY call - RrAppearanceClearTextures() first! */ - RrTextureType type; - RrTextureData data; -}; - -struct _RrAppearance { - const RrInstance *inst; - - RrSurface surface; - gint textures; - RrTexture *texture; - Pixmap pixmap; - XftDraw *xftdraw; - - /* cached for internal use */ - gint w, h; -}; - -/*! Holds a RGBA image picture */ -struct _RrImagePic { - gint width, height; - RrPixel32 *data; - /* The sum of all the pixels. This is used to compare pictures if their - hashes match. */ - gint sum; -}; - -/*! An RrImage is a sort of meta-image. It can contain multiple versions of - an image at different sizes, which may or may not be completely different - pictures */ -struct _RrImage { - gint ref; - RrImageCache *cache; - - /*! An array of "originals", that is of RrPictures that have been added - to the image in various sizes, and that have not been resized. These - are explicitly added to the RrImage. */ - RrImagePic **original; - gint n_original; - /*! An array of "resized" pictures. When an "original" RrPicture - needs to be resized for drawing, it is saved in here so that it doesn't - need to be resized again. These are automatically added to the - RrImage. */ - RrImagePic **resized; - gint n_resized; -}; - -/* these are the same on all endian machines because it seems to be dependant - on the endianness of the gfx card, not the cpu. */ -#define RrDefaultAlphaOffset 24 -#define RrDefaultRedOffset 16 -#define RrDefaultGreenOffset 8 -#define RrDefaultBlueOffset 0 - -#define RrDefaultFontFamily "arial,sans" -#define RrDefaultFontSize 8 -#define RrDefaultFontWeight RR_FONTWEIGHT_NORMAL -#define RrDefaultFontSlant RR_FONTSLANT_NORMAL - -RrInstance* RrInstanceNew (Display *display, gint screen); -void RrInstanceFree (RrInstance *inst); - -Display* RrDisplay (const RrInstance *inst); -gint RrScreen (const RrInstance *inst); -Window RrRootWindow (const RrInstance *inst); -Visual* RrVisual (const RrInstance *inst); -gint RrDepth (const RrInstance *inst); -Colormap RrColormap (const RrInstance *inst); -gint RrRedOffset (const RrInstance *inst); -gint RrGreenOffset (const RrInstance *inst); -gint RrBlueOffset (const RrInstance *inst); -gint RrRedShift (const RrInstance *inst); -gint RrGreenShift (const RrInstance *inst); -gint RrBlueShift (const RrInstance *inst); -gint RrRedMask (const RrInstance *inst); -gint RrGreenMask (const RrInstance *inst); -gint RrBlueMask (const RrInstance *inst); - -RrColor *RrColorNew (const RrInstance *inst, gint r, gint g, gint b); -RrColor *RrColorParse (const RrInstance *inst, gchar *colorname); -void RrColorFree (RrColor *in); - -gint RrColorRed (const RrColor *c); -gint RrColorGreen (const RrColor *c); -gint RrColorBlue (const RrColor *c); -gulong RrColorPixel (const RrColor *c); -GC RrColorGC (RrColor *c); - -RrAppearance *RrAppearanceNew (const RrInstance *inst, gint numtex); -RrAppearance *RrAppearanceCopy (RrAppearance *a); -void RrAppearanceFree (RrAppearance *a); -void RrAppearanceRemoveTextures(RrAppearance *a); -void RrAppearanceAddTextures(RrAppearance *a, gint numtex); -/*! Always call this when changing the type of a texture in an appearance */ -void RrAppearanceClearTextures(RrAppearance *a); - -RrFont *RrFontOpen (const RrInstance *inst, const gchar *name, - gint size, RrFontWeight weight, RrFontSlant slant); -RrFont *RrFontOpenDefault (const RrInstance *inst); -void RrFontClose (RrFont *f); -RrSize *RrFontMeasureString (const RrFont *f, const gchar *str, - gint shadow_offset_x, gint shadow_offset_y, - gboolean flow, gint maxwidth); -gint RrFontHeight (const RrFont *f, gint shadow_offset_y); -gint RrFontMaxCharWidth (const RrFont *f); - -/* Paint into the appearance. The old pixmap is returned (if there was one). It - is the responsibility of the caller to call XFreePixmap on the return when - it is non-null. */ -Pixmap RrPaintPixmap (RrAppearance *a, gint w, gint h); -void RrPaint (RrAppearance *a, Window win, gint w, gint h); -void RrMinSize (RrAppearance *a, gint *w, gint *h); -gint RrMinWidth (RrAppearance *a); -/* For text textures, if flow is TRUE, then the string must be set before - calling this, otherwise it doesn't need to be */ -gint RrMinHeight (RrAppearance *a); -void RrMargins (RrAppearance *a, gint *l, gint *t, gint *r, gint *b); - -gboolean RrPixmapToRGBA(const RrInstance *inst, - Pixmap pmap, Pixmap mask, - gint *w, gint *h, RrPixel32 **data); - -/*! Create a new image cache for RrImages. - @param max_resized_saved The number of resized copies of an image to save -*/ -RrImageCache* RrImageCacheNew(gint max_resized_saved); -void RrImageCacheRef(RrImageCache *self); -void RrImageCacheUnref(RrImageCache *self); - -/*! Finds an image in the cache, if it is already in there */ -RrImage* RrImageCacheFind(RrImageCache *self, - RrPixel32 *data, gint w, gint h); - -RrImage* RrImageNew(RrImageCache *cache); -void RrImageRef(RrImage *im); -void RrImageUnref(RrImage *im); - -void RrImageAddPicture(RrImage *im, RrPixel32 *data, gint w, gint h); -void RrImageRemovePicture(RrImage *im, gint w, gint h); - -G_END_DECLS - -#endif /*__render_h*/ diff --git a/render/test.c b/render/test.c deleted file mode 100644 index 55ab621e..00000000 --- a/render/test.c +++ /dev/null @@ -1,115 +0,0 @@ -/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- - - test.c for the Openbox window manager - Copyright (c) 2006 Mikael Magnusson - Copyright (c) 2003-2007 Dana Jansens - Copyright (c) 2003 Derek Foreman - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - See the COPYING file for a copy of the GNU General Public License. -*/ - -#include -#include -#include -#include -#include -#include -#include "render.h" -#include - -static gint x_error_handler(Display * disp, XErrorEvent * error) -{ - gchar buf[1024]; - XGetErrorText(disp, error->error_code, buf, 1024); - printf("%s\n", buf); - return 0; -} - -Display *ob_display; -gint ob_screen; -Window ob_root; - -gint main() -{ - Window win; - RrInstance *inst; - RrAppearance *look; - int done; - - Window root; - XEvent report; - gint h = 500, w = 500; - - ob_display = XOpenDisplay(NULL); - XSetErrorHandler(x_error_handler); - ob_screen = DefaultScreen(ob_display); - ob_root = RootWindow(ob_display, ob_screen); - win = - XCreateWindow(ob_display, RootWindow(ob_display, 0), - 10, 10, w, h, 10, - CopyFromParent, /* depth */ - CopyFromParent, /* class */ - CopyFromParent, /* visual */ - 0, /* valuemask */ - 0); /* attributes */ - XMapWindow(ob_display, win); - XSelectInput(ob_display, win, ExposureMask | StructureNotifyMask); - root = RootWindow (ob_display, DefaultScreen (ob_display)); - inst = RrInstanceNew(ob_display, ob_screen); - - look = RrAppearanceNew(inst, 0); - look->surface.grad = RR_SURFACE_MIRROR_HORIZONTAL; - look->surface.secondary = RrColorParse(inst, "Yellow"); - look->surface.split_secondary = RrColorParse(inst, "Red"); - look->surface.split_primary = RrColorParse(inst, "Green"); - look->surface.primary = RrColorParse(inst, "Blue"); - look->surface.interlaced = FALSE; - if (ob_display == NULL) { - fprintf(stderr, "couldn't connect to X server :0\n"); - return 0; - } - -#if BIGTEST - int i; - look->surface.pixel_data = g_new(RrPixel32, w*h); - for (i = 0; i < 10000; ++i) { - printf("\r%d", i); - fflush(stdout); - RrRender(look, w, h); - } - exit (0); -#endif - - RrPaint(look, win, w, h); - done = 0; - while (!done) { - XNextEvent(ob_display, &report); - switch (report.type) { - case Expose: - break; - case ConfigureNotify: - RrPaint(look, win, - report.xconfigure.width, - report.xconfigure.height); - break; - case UnmapNotify: - done = 1; - break; - } - } - - RrAppearanceFree (look); - RrInstanceFree (inst); - - return 1; -} diff --git a/render/theme.c b/render/theme.c deleted file mode 100644 index 6c136bf5..00000000 --- a/render/theme.c +++ /dev/null @@ -1,2007 +0,0 @@ -/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- - - theme.c for the Openbox window manager - Copyright (c) 2006 Mikael Magnusson - Copyright (c) 2003-2007 Dana Jansens - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - See the COPYING file for a copy of the GNU General Public License. -*/ - -#include "render.h" -#include "color.h" -#include "font.h" -#include "mask.h" -#include "theme.h" -#include "icon.h" -#include "obt/paths.h" - -#include -#include -#include -#include -#include - -static XrmDatabase loaddb(const gchar *name, gchar **path); -static gboolean read_int(XrmDatabase db, const gchar *rname, gint *value); -static gboolean read_string(XrmDatabase db, const gchar *rname, gchar **value); -static gboolean read_color(XrmDatabase db, const RrInstance *inst, - const gchar *rname, RrColor **value); -static gboolean read_mask(const RrInstance *inst, const gchar *path, - RrTheme *theme, const gchar *maskname, - RrPixmapMask **value); -static gboolean read_appearance(XrmDatabase db, const RrInstance *inst, - const gchar *rname, RrAppearance *value, - gboolean allow_trans); -static int parse_inline_number(const char *p); -static RrPixel32* read_c_image(gint width, gint height, const guint8 *data); -static void set_default_appearance(RrAppearance *a); - -static RrFont *get_font(RrFont *target, RrFont **default_font, - const RrInstance *inst) -{ - if (target) { - RrFontRef(target); - return target; - } else { - /* Only load the default font once */ - if (*default_font) { - RrFontRef(*default_font); - } else { - *default_font = RrFontOpenDefault(inst); - } - return *default_font; - } -} - -RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name, - gboolean allow_fallback, - RrFont *active_window_font, RrFont *inactive_window_font, - RrFont *menu_title_font, RrFont *menu_item_font, - RrFont *active_osd_font, RrFont *inactive_osd_font) -{ - XrmDatabase db = NULL; - RrJustify winjust, mtitlejust; - gchar *str; - RrTheme *theme; - RrFont *default_font = NULL; - gchar *path; - gboolean userdef; - - if (name) { - db = loaddb(name, &path); - if (db == NULL) { - g_message("Unable to load the theme '%s'", name); - if (allow_fallback) - g_message("Falling back to the default theme '%s'", - DEFAULT_THEME); - /* fallback to the default theme */ - name = NULL; - } - } - if (name == NULL) { - if (allow_fallback) { - db = loaddb(DEFAULT_THEME, &path); - if (db == NULL) { - g_message("Unable to load the theme '%s'", DEFAULT_THEME); - return NULL; - } - } else - return NULL; - } - - theme = g_new0(RrTheme, 1); - - theme->inst = inst; - theme->name = g_strdup(name ? name : DEFAULT_THEME); - - theme->a_disabled_focused_max = RrAppearanceNew(inst, 1); - theme->a_disabled_unfocused_max = RrAppearanceNew(inst, 1); - theme->a_hover_focused_max = RrAppearanceNew(inst, 1); - theme->a_hover_unfocused_max = RrAppearanceNew(inst, 1); - theme->a_toggled_focused_unpressed_max = RrAppearanceNew(inst, 1); - theme->a_toggled_unfocused_unpressed_max = RrAppearanceNew(inst, 1); - theme->a_toggled_hover_focused_max = RrAppearanceNew(inst, 1); - theme->a_toggled_hover_unfocused_max = RrAppearanceNew(inst, 1); - theme->a_toggled_focused_pressed_max = RrAppearanceNew(inst, 1); - theme->a_toggled_unfocused_pressed_max = RrAppearanceNew(inst, 1); - theme->a_focused_unpressed_max = RrAppearanceNew(inst, 1); - theme->a_focused_pressed_max = RrAppearanceNew(inst, 1); - theme->a_unfocused_unpressed_max = RrAppearanceNew(inst, 1); - theme->a_unfocused_pressed_max = RrAppearanceNew(inst, 1); - theme->a_focused_grip = RrAppearanceNew(inst, 0); - theme->a_unfocused_grip = RrAppearanceNew(inst, 0); - theme->a_focused_title = RrAppearanceNew(inst, 0); - theme->a_unfocused_title = RrAppearanceNew(inst, 0); - theme->a_focused_label = RrAppearanceNew(inst, 1); - theme->a_unfocused_label = RrAppearanceNew(inst, 1); - theme->a_icon = RrAppearanceNew(inst, 1); - theme->a_focused_handle = RrAppearanceNew(inst, 0); - theme->a_unfocused_handle = RrAppearanceNew(inst, 0); - theme->a_menu = RrAppearanceNew(inst, 0); - theme->a_menu_title = RrAppearanceNew(inst, 0); - theme->a_menu_text_title = RrAppearanceNew(inst, 1); - theme->a_menu_normal = RrAppearanceNew(inst, 0); - theme->a_menu_selected = RrAppearanceNew(inst, 0); - theme->a_menu_disabled = RrAppearanceNew(inst, 0); - /* a_menu_disabled_selected is copied from a_menu_selected */ - theme->a_menu_text_normal = RrAppearanceNew(inst, 1); - theme->a_menu_text_selected = RrAppearanceNew(inst, 1); - theme->a_menu_text_disabled = RrAppearanceNew(inst, 1); - theme->a_menu_text_disabled_selected = RrAppearanceNew(inst, 1); - theme->a_menu_bullet_normal = RrAppearanceNew(inst, 1); - theme->a_menu_bullet_selected = RrAppearanceNew(inst, 1); - theme->a_clear = RrAppearanceNew(inst, 0); - theme->a_clear_tex = RrAppearanceNew(inst, 1); - theme->osd_bg = RrAppearanceNew(inst, 0); - theme->osd_hilite_label = RrAppearanceNew(inst, 1); - theme->osd_hilite_bg = RrAppearanceNew(inst, 0); - theme->osd_unhilite_label = RrAppearanceNew(inst, 1); - theme->osd_unhilite_bg = RrAppearanceNew(inst, 0); - - /* load the font stuff */ - theme->win_font_focused = get_font(active_window_font, - &default_font, inst); - theme->win_font_unfocused = get_font(inactive_window_font, - &default_font, inst); - - winjust = RR_JUSTIFY_LEFT; - if (read_string(db, "window.label.text.justify", &str)) { - if (!g_ascii_strcasecmp(str, "right")) - winjust = RR_JUSTIFY_RIGHT; - else if (!g_ascii_strcasecmp(str, "center")) - winjust = RR_JUSTIFY_CENTER; - } - - theme->menu_title_font = get_font(menu_title_font, &default_font, inst); - - mtitlejust = RR_JUSTIFY_LEFT; - if (read_string(db, "menu.title.text.justify", &str)) { - if (!g_ascii_strcasecmp(str, "right")) - mtitlejust = RR_JUSTIFY_RIGHT; - else if (!g_ascii_strcasecmp(str, "center")) - mtitlejust = RR_JUSTIFY_CENTER; - } - - theme->menu_font = get_font(menu_item_font, &default_font, inst); - - theme->osd_font_hilite = get_font(active_osd_font, &default_font, inst); - theme->osd_font_unhilite = get_font(inactive_osd_font, &default_font,inst); - - /* load direct dimensions */ - if ((!read_int(db, "menu.overlap.x", &theme->menu_overlap_x) && - !read_int(db, "menu.overlap", &theme->menu_overlap_x)) || - theme->menu_overlap_x < -100 || theme->menu_overlap_x > 100) - theme->menu_overlap_x = 0; - if ((!read_int(db, "menu.overlap.y", &theme->menu_overlap_y) && - !read_int(db, "menu.overlap", &theme->menu_overlap_y)) || - theme->menu_overlap_y < -100 || theme->menu_overlap_y > 100) - theme->menu_overlap_y = 0; - if (!read_int(db, "window.handle.width", &theme->handle_height) || - theme->handle_height < 0 || theme->handle_height > 100) - theme->handle_height = 6; - if (!read_int(db, "padding.width", &theme->paddingx) || - theme->paddingx < 0 || theme->paddingx > 100) - theme->paddingx = 3; - if (!read_int(db, "padding.height", &theme->paddingy) || - theme->paddingy < 0 || theme->paddingy > 100) - theme->paddingy = theme->paddingx; - if (!read_int(db, "border.width", &theme->fbwidth) || - theme->fbwidth < 0 || theme->fbwidth > 100) - theme->fbwidth = 1; - /* menu border width inherits from the frame border width */ - if (!read_int(db, "menu.border.width", &theme->mbwidth) || - theme->mbwidth < 0 || theme->mbwidth > 100) - theme->mbwidth = theme->fbwidth; - /* osd border width inherits from the frame border width */ - if (!read_int(db, "osd.border.width", &theme->obwidth) || - theme->obwidth < 0 || theme->obwidth > 100) - theme->obwidth = theme->fbwidth; - if (!read_int(db, "window.client.padding.width", &theme->cbwidthx) || - theme->cbwidthx < 0 || theme->cbwidthx > 100) - theme->cbwidthx = theme->paddingx; - if (!read_int(db, "window.client.padding.height", &theme->cbwidthy) || - theme->cbwidthy < 0 || theme->cbwidthy > 100) - theme->cbwidthy = theme->cbwidthx; - if (!read_int(db, "menu.separator.width", &theme->menu_sep_width) || - theme->menu_sep_width < 1 || theme->menu_sep_width > 100) - theme->menu_sep_width = 1; - if (!read_int(db, "menu.separator.padding.width", - &theme->menu_sep_paddingx) || - theme->menu_sep_paddingx < 0 || theme->menu_sep_paddingx > 100) - theme->menu_sep_paddingx = 6; - if (!read_int(db, "menu.separator.padding.height", - &theme->menu_sep_paddingy) || - theme->menu_sep_paddingy < 0 || theme->menu_sep_paddingy > 100) - theme->menu_sep_paddingy = 3; - - /* load colors */ - if (!read_color(db, inst, - "window.active.border.color", - &theme->frame_focused_border_color) && - !read_color(db, inst, - "border.color", - &theme->frame_focused_border_color)) - theme->frame_focused_border_color = RrColorNew(inst, 0, 0, 0); - /* title separator focused color inherits from focused border color */ - if (!read_color(db, inst, - "window.active.title.separator.color", - &theme->title_separator_focused_color)) - theme->title_separator_focused_color = - RrColorNew(inst, - theme->frame_focused_border_color->r, - theme->frame_focused_border_color->g, - theme->frame_focused_border_color->b); - /* unfocused border color inherits from frame focused border color */ - if (!read_color(db, inst, - "window.inactive.border.color", - &theme->frame_unfocused_border_color)) - theme->frame_unfocused_border_color = - RrColorNew(inst, theme->frame_focused_border_color->r, - theme->frame_focused_border_color->g, - theme->frame_focused_border_color->b); - /* title separator unfocused color inherits from unfocused border color */ - if (!read_color(db, inst, - "window.inactive.title.separator.color", - &theme->title_separator_unfocused_color)) - theme->title_separator_unfocused_color = - RrColorNew(inst, - theme->frame_unfocused_border_color->r, - theme->frame_unfocused_border_color->g, - theme->frame_unfocused_border_color->b); - - /* menu border color inherits from frame focused border color */ - if (!read_color(db, inst, "menu.border.color", &theme->menu_border_color)) - theme->menu_border_color = - RrColorNew(inst, - theme->frame_focused_border_color->r, - theme->frame_focused_border_color->g, - theme->frame_focused_border_color->b); - /* osd border color inherits from frame focused border color */ - if (!read_color(db, inst, "osd.border.color", &theme->osd_border_color)) - theme->osd_border_color = - RrColorNew(inst, - theme->frame_focused_border_color->r, - theme->frame_focused_border_color->g, - theme->frame_focused_border_color->b); - if (!read_color(db, inst, - "window.active.client.color", - &theme->cb_focused_color)) - theme->cb_focused_color = RrColorNew(inst, 0xff, 0xff, 0xff); - if (!read_color(db, inst, - "window.inactive.client.color", - &theme->cb_unfocused_color)) - theme->cb_unfocused_color = RrColorNew(inst, 0xff, 0xff, 0xff); - if (!read_color(db, inst, - "window.active.label.text.color", - &theme->title_focused_color)) - theme->title_focused_color = RrColorNew(inst, 0x0, 0x0, 0x0); - if (!read_color(db, inst, "osd.active.label.text.color", - &theme->osd_text_active_color) && - !read_color(db, inst, "osd.label.text.color", - &theme->osd_text_active_color)) - theme->osd_text_active_color = - RrColorNew(inst, - theme->title_focused_color->r, - theme->title_focused_color->g, - theme->title_focused_color->b); - if (!read_color(db, inst, - "window.inactive.label.text.color", - &theme->title_unfocused_color)) - theme->title_unfocused_color = RrColorNew(inst, 0xff, 0xff, 0xff); - if (!read_color(db, inst, "osd.inactive.label.text.color", - &theme->osd_text_inactive_color)) - theme->osd_text_inactive_color = - RrColorNew(inst, - theme->title_unfocused_color->r, - theme->title_unfocused_color->g, - theme->title_unfocused_color->b); - if (!read_color(db, inst, - "window.active.button.unpressed.image.color", - &theme->titlebut_focused_unpressed_color)) - theme->titlebut_focused_unpressed_color = RrColorNew(inst, 0, 0, 0); - if (!read_color(db, inst, - "window.inactive.button.unpressed.image.color", - &theme->titlebut_unfocused_unpressed_color)) - theme->titlebut_unfocused_unpressed_color = - RrColorNew(inst, 0xff, 0xff, 0xff); - if (!read_color(db, inst, - "window.active.button.pressed.image.color", - &theme->titlebut_focused_pressed_color)) - theme->titlebut_focused_pressed_color = - RrColorNew(inst, - theme->titlebut_focused_unpressed_color->r, - theme->titlebut_focused_unpressed_color->g, - theme->titlebut_focused_unpressed_color->b); - if (!read_color(db, inst, - "window.inactive.button.pressed.image.color", - &theme->titlebut_unfocused_pressed_color)) - theme->titlebut_unfocused_pressed_color = - RrColorNew(inst, - theme->titlebut_unfocused_unpressed_color->r, - theme->titlebut_unfocused_unpressed_color->g, - theme->titlebut_unfocused_unpressed_color->b); - if (!read_color(db, inst, - "window.active.button.disabled.image.color", - &theme->titlebut_disabled_focused_color)) - theme->titlebut_disabled_focused_color = - RrColorNew(inst, 0xff, 0xff, 0xff); - if (!read_color(db, inst, - "window.inactive.button.disabled.image.color", - &theme->titlebut_disabled_unfocused_color)) - theme->titlebut_disabled_unfocused_color = RrColorNew(inst, 0, 0, 0); - if (!read_color(db, inst, - "window.active.button.hover.image.color", - &theme->titlebut_hover_focused_color)) - theme->titlebut_hover_focused_color = - RrColorNew(inst, - theme->titlebut_focused_unpressed_color->r, - theme->titlebut_focused_unpressed_color->g, - theme->titlebut_focused_unpressed_color->b); - if (!read_color(db, inst, - "window.inactive.button.hover.image.color", - &theme->titlebut_hover_unfocused_color)) - theme->titlebut_hover_unfocused_color = - RrColorNew(inst, - theme->titlebut_unfocused_unpressed_color->r, - theme->titlebut_unfocused_unpressed_color->g, - theme->titlebut_unfocused_unpressed_color->b); - if (!read_color(db, inst, - "window.active.button.toggled.unpressed.image.color", - &theme->titlebut_toggled_focused_unpressed_color) && - !read_color(db, inst, - "window.active.button.toggled.image.color", - &theme->titlebut_toggled_focused_unpressed_color)) - theme->titlebut_toggled_focused_unpressed_color = - RrColorNew(inst, - theme->titlebut_focused_pressed_color->r, - theme->titlebut_focused_pressed_color->g, - theme->titlebut_focused_pressed_color->b); - if (!read_color(db, inst, - "window.inactive.button.toggled.unpressed.image.color", - &theme->titlebut_toggled_unfocused_unpressed_color) && - !read_color(db, inst, - "window.inactive.button.toggled.image.color", - &theme->titlebut_toggled_unfocused_unpressed_color)) - theme->titlebut_toggled_unfocused_unpressed_color = - RrColorNew(inst, - theme->titlebut_unfocused_pressed_color->r, - theme->titlebut_unfocused_pressed_color->g, - theme->titlebut_unfocused_pressed_color->b); - if (!read_color(db, inst, - "window.active.button.toggled.hover.image.color", - &theme->titlebut_toggled_hover_focused_color)) - theme->titlebut_toggled_hover_focused_color = - RrColorNew(inst, - theme->titlebut_toggled_focused_unpressed_color->r, - theme->titlebut_toggled_focused_unpressed_color->g, - theme->titlebut_toggled_focused_unpressed_color->b); - if (!read_color(db, inst, - "window.inactive.button.toggled.hover.image.color", - &theme->titlebut_toggled_hover_unfocused_color)) - theme->titlebut_toggled_hover_unfocused_color = - RrColorNew(inst, - theme->titlebut_toggled_unfocused_unpressed_color->r, - theme->titlebut_toggled_unfocused_unpressed_color->g, - theme->titlebut_toggled_unfocused_unpressed_color->b); - if (!read_color(db, inst, - "window.active.button.toggled.pressed.image.color", - &theme->titlebut_toggled_focused_pressed_color)) - theme->titlebut_toggled_focused_pressed_color = - RrColorNew(inst, - theme->titlebut_focused_pressed_color->r, - theme->titlebut_focused_pressed_color->g, - theme->titlebut_focused_pressed_color->b); - if (!read_color(db, inst, - "window.inactive.button.toggled.pressed.image.color", - &theme->titlebut_toggled_unfocused_pressed_color)) - theme->titlebut_toggled_unfocused_pressed_color = - RrColorNew(inst, - theme->titlebut_unfocused_pressed_color->r, - theme->titlebut_unfocused_pressed_color->g, - theme->titlebut_unfocused_pressed_color->b); - if (!read_color(db, inst, - "menu.title.text.color", &theme->menu_title_color)) - theme->menu_title_color = RrColorNew(inst, 0, 0, 0); - if (!read_color(db, inst, - "menu.items.text.color", &theme->menu_color)) - theme->menu_color = RrColorNew(inst, 0xff, 0xff, 0xff); - if (!read_color(db, inst, - "menu.items.disabled.text.color", - &theme->menu_disabled_color)) - theme->menu_disabled_color = RrColorNew(inst, 0, 0, 0); - if (!read_color(db, inst, - "menu.items.active.disabled.text.color", - &theme->menu_disabled_selected_color)) - theme->menu_disabled_selected_color = - RrColorNew(inst, - theme->menu_disabled_color->r, - theme->menu_disabled_color->g, - theme->menu_disabled_color->b); - if (!read_color(db, inst, - "menu.items.active.text.color", - &theme->menu_selected_color)) - theme->menu_selected_color = RrColorNew(inst, 0, 0, 0); - if (!read_color(db, inst, - "menu.separator.color", &theme->menu_sep_color)) - theme->menu_sep_color = RrColorNew(inst, - theme->menu_color->r, - theme->menu_color->g, - theme->menu_color->b); - - /* load the image masks */ - - /* maximize button masks */ - userdef = TRUE; - if (!read_mask(inst, path, theme, "max.xbm", &theme->max_mask)) { - guchar data[] = { 0x3f, 0x3f, 0x21, 0x21, 0x21, 0x3f }; - theme->max_mask = RrPixmapMaskNew(inst, 6, 6, (gchar*)data); - userdef = FALSE; - } - if (!read_mask(inst, path, theme, "max_toggled.xbm", - &theme->max_toggled_mask)) - { - if (userdef) - theme->max_toggled_mask = RrPixmapMaskCopy(theme->max_mask); - else { - guchar data[] = { 0x3e, 0x22, 0x2f, 0x29, 0x39, 0x0f }; - theme->max_toggled_mask = RrPixmapMaskNew(inst, 6, 6,(gchar*)data); - } - } - if (!read_mask(inst, path, theme, "max_pressed.xbm", - &theme->max_pressed_mask)) - theme->max_pressed_mask = RrPixmapMaskCopy(theme->max_mask); - if (!read_mask(inst,path,theme,"max_disabled.xbm", - &theme->max_disabled_mask)) - theme->max_disabled_mask = RrPixmapMaskCopy(theme->max_mask); - if (!read_mask(inst, path, theme, "max_hover.xbm", &theme->max_hover_mask)) - theme->max_hover_mask = RrPixmapMaskCopy(theme->max_mask); - if (!read_mask(inst, path, theme, "max_toggled_pressed.xbm", - &theme->max_toggled_pressed_mask)) - theme->max_toggled_pressed_mask = - RrPixmapMaskCopy(theme->max_toggled_mask); - if (!read_mask(inst, path, theme, "max_toggled_hover.xbm", - &theme->max_toggled_hover_mask)) - theme->max_toggled_hover_mask = - RrPixmapMaskCopy(theme->max_toggled_mask); - - /* iconify button masks */ - if (!read_mask(inst, path, theme, "iconify.xbm", &theme->iconify_mask)) { - guchar data[] = { 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f }; - theme->iconify_mask = RrPixmapMaskNew(inst, 6, 6, (gchar*)data); - } - if (!read_mask(inst, path, theme, "iconify_pressed.xbm", - &theme->iconify_pressed_mask)) - theme->iconify_pressed_mask = RrPixmapMaskCopy(theme->iconify_mask); - if (!read_mask(inst, path, theme, "iconify_disabled.xbm", - &theme->iconify_disabled_mask)) - theme->iconify_disabled_mask = RrPixmapMaskCopy(theme->iconify_mask); - if (!read_mask(inst, path, theme, "iconify_hover.xbm", - &theme->iconify_hover_mask)) - theme->iconify_hover_mask = RrPixmapMaskCopy(theme->iconify_mask); - - /* all desktops button masks */ - userdef = TRUE; - if (!read_mask(inst, path, theme, "desk.xbm", &theme->desk_mask)) { - guchar data[] = { 0x33, 0x33, 0x00, 0x00, 0x33, 0x33 }; - theme->desk_mask = RrPixmapMaskNew(inst, 6, 6, (gchar*)data); - userdef = FALSE; - } - if (!read_mask(inst, path, theme, "desk_toggled.xbm", - &theme->desk_toggled_mask)) { - if (userdef) - theme->desk_toggled_mask = RrPixmapMaskCopy(theme->desk_mask); - else { - guchar data[] = { 0x00, 0x1e, 0x1a, 0x16, 0x1e, 0x00 }; - theme->desk_toggled_mask = - RrPixmapMaskNew(inst, 6, 6, (gchar*)data); - } - } - if (!read_mask(inst, path, theme, "desk_pressed.xbm", - &theme->desk_pressed_mask)) - theme->desk_pressed_mask = RrPixmapMaskCopy(theme->desk_mask); - if (!read_mask(inst, path, theme, "desk_disabled.xbm", - &theme->desk_disabled_mask)) - theme->desk_disabled_mask = RrPixmapMaskCopy(theme->desk_mask); - if (!read_mask(inst, path, theme, "desk_hover.xbm", - &theme->desk_hover_mask)) - theme->desk_hover_mask = RrPixmapMaskCopy(theme->desk_mask); - if (!read_mask(inst, path, theme, "desk_toggled_pressed.xbm", - &theme->desk_toggled_pressed_mask)) - theme->desk_toggled_pressed_mask = - RrPixmapMaskCopy(theme->desk_toggled_mask); - if (!read_mask(inst, path, theme, "desk_toggled_hover.xbm", - &theme->desk_toggled_hover_mask)) - theme->desk_toggled_hover_mask = - RrPixmapMaskCopy(theme->desk_toggled_mask); - - /* shade button masks */ - if (!read_mask(inst, path, theme, "shade.xbm", &theme->shade_mask)) { - guchar data[] = { 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00 }; - theme->shade_mask = RrPixmapMaskNew(inst, 6, 6, (gchar*)data); - } - if (!read_mask(inst, path, theme, "shade_toggled.xbm", - &theme->shade_toggled_mask)) - theme->shade_toggled_mask = RrPixmapMaskCopy(theme->shade_mask); - if (!read_mask(inst, path, theme, "shade_pressed.xbm", - &theme->shade_pressed_mask)) - theme->shade_pressed_mask = RrPixmapMaskCopy(theme->shade_mask); - if (!read_mask(inst, path, theme, "shade_disabled.xbm", - &theme->shade_disabled_mask)) - theme->shade_disabled_mask = RrPixmapMaskCopy(theme->shade_mask); - if (!read_mask(inst, path, theme, "shade_hover.xbm", - &theme->shade_hover_mask)) - theme->shade_hover_mask = RrPixmapMaskCopy(theme->shade_mask); - if (!read_mask(inst, path, theme, "shade_toggled_pressed.xbm", - &theme->shade_toggled_pressed_mask)) - theme->shade_toggled_pressed_mask = - RrPixmapMaskCopy(theme->shade_toggled_mask); - if (!read_mask(inst, path, theme, "shade_toggled_hover.xbm", - &theme->shade_toggled_hover_mask)) - theme->shade_toggled_hover_mask = - RrPixmapMaskCopy(theme->shade_toggled_mask); - - /* close button masks */ - if (!read_mask(inst, path, theme, "close.xbm", &theme->close_mask)) { - guchar data[] = { 0x33, 0x3f, 0x1e, 0x1e, 0x3f, 0x33 }; - theme->close_mask = RrPixmapMaskNew(inst, 6, 6, (gchar*)data); - } - if (!read_mask(inst, path, theme, "close_pressed.xbm", - &theme->close_pressed_mask)) - theme->close_pressed_mask = RrPixmapMaskCopy(theme->close_mask); - if (!read_mask(inst, path, theme, "close_disabled.xbm", - &theme->close_disabled_mask)) - theme->close_disabled_mask = RrPixmapMaskCopy(theme->close_mask); - if (!read_mask(inst, path, theme, "close_hover.xbm", - &theme->close_hover_mask)) - theme->close_hover_mask = RrPixmapMaskCopy(theme->close_mask); - - /* submenu bullet mask */ - if (!read_mask(inst, path, theme, "bullet.xbm", &theme->menu_bullet_mask)) - { - guchar data[] = { 0x01, 0x03, 0x07, 0x0f, 0x07, 0x03, 0x01 }; - theme->menu_bullet_mask = RrPixmapMaskNew(inst, 4, 7, (gchar*)data); - } - - /* up and down arrows */ - { - guchar data[] = { 0xfe, 0x00, 0x7c, 0x00, 0x38, 0x00, 0x10, 0x00 }; - theme->down_arrow_mask = RrPixmapMaskNew(inst, 9, 4, (gchar*)data); - } - { - guchar data[] = { 0x10, 0x00, 0x38, 0x00, 0x7c, 0x00, 0xfe, 0x00 }; - theme->up_arrow_mask = RrPixmapMaskNew(inst, 9, 4, (gchar*)data); - } - - /* setup the default window icon */ - theme->def_win_icon = read_c_image(OB_DEFAULT_ICON_WIDTH, - OB_DEFAULT_ICON_HEIGHT, - OB_DEFAULT_ICON_pixel_data); - theme->def_win_icon_w = OB_DEFAULT_ICON_WIDTH; - theme->def_win_icon_h = OB_DEFAULT_ICON_HEIGHT; - - /* read the decoration textures */ - if (!read_appearance(db, inst, - "window.active.title.bg", theme->a_focused_title, - FALSE)) - set_default_appearance(theme->a_focused_title); - if (!read_appearance(db, inst, - "window.inactive.title.bg", theme->a_unfocused_title, - FALSE)) - set_default_appearance(theme->a_unfocused_title); - if (!read_appearance(db, inst, - "window.active.label.bg", theme->a_focused_label, - TRUE)) - set_default_appearance(theme->a_focused_label); - if (!read_appearance(db, inst, - "window.inactive.label.bg", theme->a_unfocused_label, - TRUE)) - set_default_appearance(theme->a_unfocused_label); - if (!read_appearance(db, inst, - "window.active.handle.bg", theme->a_focused_handle, - FALSE)) - set_default_appearance(theme->a_focused_handle); - if (!read_appearance(db, inst, - "window.inactive.handle.bg",theme->a_unfocused_handle, - FALSE)) - set_default_appearance(theme->a_unfocused_handle); - if (!read_appearance(db, inst, - "window.active.grip.bg", theme->a_focused_grip, - TRUE)) - set_default_appearance(theme->a_focused_grip); - if (!read_appearance(db, inst, - "window.inactive.grip.bg", theme->a_unfocused_grip, - TRUE)) - set_default_appearance(theme->a_unfocused_grip); - if (!read_appearance(db, inst, - "menu.items.bg", theme->a_menu, - FALSE)) - set_default_appearance(theme->a_menu); - if (!read_appearance(db, inst, - "menu.title.bg", theme->a_menu_title, - TRUE)) - set_default_appearance(theme->a_menu_title); - if (!read_appearance(db, inst, - "menu.items.active.bg", theme->a_menu_selected, - TRUE)) - set_default_appearance(theme->a_menu_selected); - theme->a_menu_disabled_selected = - RrAppearanceCopy(theme->a_menu_selected); - - /* read appearances for non-decorations (on-screen-display) */ - if (!read_appearance(db, inst, "osd.bg", theme->osd_bg, FALSE)) { - RrAppearanceFree(theme->osd_bg); - theme->osd_bg = RrAppearanceCopy(theme->a_focused_title); - } - if (!read_appearance(db, inst, "osd.active.label.bg", - theme->osd_hilite_label, TRUE) && - !read_appearance(db, inst, "osd.label.bg", - theme->osd_hilite_label, TRUE)) { - RrAppearanceFree(theme->osd_hilite_label); - theme->osd_hilite_label = RrAppearanceCopy(theme->a_focused_label); - } - if (!read_appearance(db, inst, "osd.inactive.label.bg", - theme->osd_unhilite_label, TRUE)) { - RrAppearanceFree(theme->osd_unhilite_label); - theme->osd_unhilite_label = RrAppearanceCopy(theme->a_unfocused_label); - } - /* osd_hilite_fg can't be parentrel */ - if (!read_appearance(db, inst, "osd.hilight.bg", - theme->osd_hilite_bg, FALSE)) { - RrAppearanceFree(theme->osd_hilite_bg); - if (theme->a_focused_label->surface.grad != RR_SURFACE_PARENTREL) - theme->osd_hilite_bg = RrAppearanceCopy(theme->a_focused_label); - else - theme->osd_hilite_bg = RrAppearanceCopy(theme->a_focused_title); - } - /* osd_unhilite_fg can't be parentrel either */ - if (!read_appearance(db, inst, "osd.unhilight.bg", - theme->osd_unhilite_bg, FALSE)) { - RrAppearanceFree(theme->osd_unhilite_bg); - if (theme->a_unfocused_label->surface.grad != RR_SURFACE_PARENTREL) - theme->osd_unhilite_bg=RrAppearanceCopy(theme->a_unfocused_label); - else - theme->osd_unhilite_bg=RrAppearanceCopy(theme->a_unfocused_title); - } - - /* read buttons textures */ - if (!read_appearance(db, inst, - "window.active.button.disabled.bg", - theme->a_disabled_focused_max, - TRUE)) - set_default_appearance(theme->a_disabled_focused_max); - if (!read_appearance(db, inst, - "window.inactive.button.disabled.bg", - theme->a_disabled_unfocused_max, - TRUE)) - set_default_appearance(theme->a_disabled_unfocused_max); - if (!read_appearance(db, inst, - "window.active.button.pressed.bg", - theme->a_focused_pressed_max, - TRUE)) - set_default_appearance(theme->a_focused_pressed_max); - if (!read_appearance(db, inst, - "window.inactive.button.pressed.bg", - theme->a_unfocused_pressed_max, - TRUE)) - set_default_appearance(theme->a_unfocused_pressed_max); - if (!read_appearance(db, inst, - "window.active.button.toggled.unpressed.bg", - theme->a_toggled_focused_unpressed_max, - TRUE) && - !read_appearance(db, inst, - "window.active.button.toggled.bg", - theme->a_toggled_focused_unpressed_max, - TRUE)) - { - RrAppearanceFree(theme->a_toggled_focused_unpressed_max); - theme->a_toggled_focused_unpressed_max = - RrAppearanceCopy(theme->a_focused_pressed_max); - } - if (!read_appearance(db, inst, - "window.inactive.button.toggled.unpressed.bg", - theme->a_toggled_unfocused_unpressed_max, - TRUE) && - !read_appearance(db, inst, - "window.inactive.button.toggled.bg", - theme->a_toggled_unfocused_unpressed_max, - TRUE)) - { - RrAppearanceFree(theme->a_toggled_unfocused_unpressed_max); - theme->a_toggled_unfocused_unpressed_max = - RrAppearanceCopy(theme->a_unfocused_pressed_max); - } - if (!read_appearance(db, inst, - "window.active.button.toggled.hover.bg", - theme->a_toggled_hover_focused_max, - TRUE)) - { - RrAppearanceFree(theme->a_toggled_hover_focused_max); - theme->a_toggled_hover_focused_max = - RrAppearanceCopy(theme->a_toggled_focused_unpressed_max); - } - if (!read_appearance(db, inst, - "window.inactive.button.toggled.hover.bg", - theme->a_toggled_hover_unfocused_max, - TRUE)) - { - RrAppearanceFree(theme->a_toggled_hover_unfocused_max); - theme->a_toggled_hover_unfocused_max = - RrAppearanceCopy(theme->a_toggled_unfocused_unpressed_max); - } - if (!read_appearance(db, inst, - "window.active.button.toggled.pressed.bg", - theme->a_toggled_focused_pressed_max, - TRUE)) - { - RrAppearanceFree(theme->a_toggled_focused_pressed_max); - theme->a_toggled_focused_pressed_max = - RrAppearanceCopy(theme->a_focused_pressed_max); - } - if (!read_appearance(db, inst, - "window.inactive.button.toggled.pressed.bg", - theme->a_toggled_unfocused_pressed_max, - TRUE)) - { - RrAppearanceFree(theme->a_toggled_unfocused_pressed_max); - theme->a_toggled_unfocused_pressed_max = - RrAppearanceCopy(theme->a_unfocused_pressed_max); - } - if (!read_appearance(db, inst, - "window.active.button.unpressed.bg", - theme->a_focused_unpressed_max, - TRUE)) - set_default_appearance(theme->a_focused_unpressed_max); - if (!read_appearance(db, inst, - "window.inactive.button.unpressed.bg", - theme->a_unfocused_unpressed_max, - TRUE)) - set_default_appearance(theme->a_unfocused_unpressed_max); - if (!read_appearance(db, inst, - "window.active.button.hover.bg", - theme->a_hover_focused_max, - TRUE)) - { - RrAppearanceFree(theme->a_hover_focused_max); - theme->a_hover_focused_max = - RrAppearanceCopy(theme->a_focused_unpressed_max); - } - if (!read_appearance(db, inst, - "window.inactive.button.hover.bg", - theme->a_hover_unfocused_max, - TRUE)) - { - RrAppearanceFree(theme->a_hover_unfocused_max); - theme->a_hover_unfocused_max = - RrAppearanceCopy(theme->a_unfocused_unpressed_max); - } - - theme->a_disabled_focused_close = - RrAppearanceCopy(theme->a_disabled_focused_max); - theme->a_disabled_unfocused_close = - RrAppearanceCopy(theme->a_disabled_unfocused_max); - theme->a_hover_focused_close = - RrAppearanceCopy(theme->a_hover_focused_max); - theme->a_hover_unfocused_close = - RrAppearanceCopy(theme->a_hover_unfocused_max); - theme->a_unfocused_unpressed_close = - RrAppearanceCopy(theme->a_unfocused_unpressed_max); - theme->a_unfocused_pressed_close = - RrAppearanceCopy(theme->a_unfocused_pressed_max); - theme->a_focused_unpressed_close = - RrAppearanceCopy(theme->a_focused_unpressed_max); - theme->a_focused_pressed_close = - RrAppearanceCopy(theme->a_focused_pressed_max); - theme->a_disabled_focused_desk = - RrAppearanceCopy(theme->a_disabled_focused_max); - theme->a_disabled_unfocused_desk = - RrAppearanceCopy(theme->a_disabled_unfocused_max); - theme->a_hover_focused_desk = - RrAppearanceCopy(theme->a_hover_focused_max); - theme->a_hover_unfocused_desk = - RrAppearanceCopy(theme->a_hover_unfocused_max); - theme->a_toggled_hover_focused_desk = - RrAppearanceCopy(theme->a_toggled_hover_focused_max); - theme->a_toggled_hover_unfocused_desk = - RrAppearanceCopy(theme->a_toggled_hover_unfocused_max); - theme->a_toggled_focused_unpressed_desk = - RrAppearanceCopy(theme->a_toggled_focused_unpressed_max); - theme->a_toggled_unfocused_unpressed_desk = - RrAppearanceCopy(theme->a_toggled_unfocused_unpressed_max); - theme->a_toggled_focused_pressed_desk = - RrAppearanceCopy(theme->a_toggled_focused_pressed_max); - theme->a_toggled_unfocused_pressed_desk = - RrAppearanceCopy(theme->a_toggled_unfocused_pressed_max); - theme->a_unfocused_unpressed_desk = - RrAppearanceCopy(theme->a_unfocused_unpressed_max); - theme->a_unfocused_pressed_desk = - RrAppearanceCopy(theme->a_unfocused_pressed_max); - theme->a_focused_unpressed_desk = - RrAppearanceCopy(theme->a_focused_unpressed_max); - theme->a_focused_pressed_desk = - RrAppearanceCopy(theme->a_focused_pressed_max); - theme->a_disabled_focused_shade = - RrAppearanceCopy(theme->a_disabled_focused_max); - theme->a_disabled_unfocused_shade = - RrAppearanceCopy(theme->a_disabled_unfocused_max); - theme->a_hover_focused_shade = - RrAppearanceCopy(theme->a_hover_focused_max); - theme->a_hover_unfocused_shade = - RrAppearanceCopy(theme->a_hover_unfocused_max); - theme->a_toggled_hover_focused_shade = - RrAppearanceCopy(theme->a_toggled_hover_focused_max); - theme->a_toggled_hover_unfocused_shade = - RrAppearanceCopy(theme->a_toggled_hover_unfocused_max); - theme->a_toggled_focused_unpressed_shade = - RrAppearanceCopy(theme->a_toggled_focused_unpressed_max); - theme->a_toggled_unfocused_unpressed_shade = - RrAppearanceCopy(theme->a_toggled_unfocused_unpressed_max); - theme->a_toggled_focused_pressed_shade = - RrAppearanceCopy(theme->a_toggled_focused_pressed_max); - theme->a_toggled_unfocused_pressed_shade = - RrAppearanceCopy(theme->a_toggled_unfocused_pressed_max); - theme->a_unfocused_unpressed_shade = - RrAppearanceCopy(theme->a_unfocused_unpressed_max); - theme->a_unfocused_pressed_shade = - RrAppearanceCopy(theme->a_unfocused_pressed_max); - theme->a_focused_unpressed_shade = - RrAppearanceCopy(theme->a_focused_unpressed_max); - theme->a_focused_pressed_shade = - RrAppearanceCopy(theme->a_focused_pressed_max); - theme->a_disabled_focused_iconify = - RrAppearanceCopy(theme->a_disabled_focused_max); - theme->a_disabled_unfocused_iconify = - RrAppearanceCopy(theme->a_disabled_focused_max); - theme->a_hover_focused_iconify = - RrAppearanceCopy(theme->a_hover_focused_max); - theme->a_hover_unfocused_iconify = - RrAppearanceCopy(theme->a_hover_unfocused_max); - theme->a_unfocused_unpressed_iconify = - RrAppearanceCopy(theme->a_unfocused_unpressed_max); - theme->a_unfocused_pressed_iconify = - RrAppearanceCopy(theme->a_unfocused_pressed_max); - theme->a_focused_unpressed_iconify = - RrAppearanceCopy(theme->a_focused_unpressed_max); - theme->a_focused_pressed_iconify = - RrAppearanceCopy(theme->a_focused_pressed_max); - - theme->a_icon->surface.grad = - theme->a_clear->surface.grad = - theme->a_clear_tex->surface.grad = - theme->a_menu_text_title->surface.grad = - theme->a_menu_normal->surface.grad = - theme->a_menu_disabled->surface.grad = - theme->a_menu_text_normal->surface.grad = - theme->a_menu_text_selected->surface.grad = - theme->a_menu_text_disabled->surface.grad = - theme->a_menu_text_disabled_selected->surface.grad = - theme->a_menu_bullet_normal->surface.grad = - theme->a_menu_bullet_selected->surface.grad = RR_SURFACE_PARENTREL; - - /* set up the textures */ - theme->a_focused_label->texture[0].type = RR_TEXTURE_TEXT; - theme->a_focused_label->texture[0].data.text.justify = winjust; - theme->a_focused_label->texture[0].data.text.font=theme->win_font_focused; - theme->a_focused_label->texture[0].data.text.color = - theme->title_focused_color; - - if (read_string(db, "window.active.label.text.font", &str)) { - char *p; - gint i = 0; - gint j; - if (strstr(str, "shadow=y")) { - if ((p = strstr(str, "shadowoffset="))) - i = parse_inline_number(p + strlen("shadowoffset=")); - else - i = 1; - theme->a_focused_label->texture[0].data.text.shadow_offset_x = i; - theme->a_focused_label->texture[0].data.text.shadow_offset_y = i; - } - if ((p = strstr(str, "shadowtint="))) - { - i = parse_inline_number(p + strlen("shadowtint=")); - j = (i > 0 ? 0 : 255); - i = ABS(i*255/100); - - theme->title_focused_shadow_color = RrColorNew(inst, j, j, j); - theme->title_focused_shadow_alpha = i; - } else { - theme->title_focused_shadow_color = RrColorNew(inst, 0, 0, 0); - theme->title_focused_shadow_alpha = 50; - } - } - - theme->a_focused_label->texture[0].data.text.shadow_color = - theme->title_focused_shadow_color; - theme->a_focused_label->texture[0].data.text.shadow_alpha = - theme->title_focused_shadow_alpha; - - theme->osd_hilite_label->texture[0].type = RR_TEXTURE_TEXT; - theme->osd_hilite_label->texture[0].data.text.justify = RR_JUSTIFY_LEFT; - theme->osd_hilite_label->texture[0].data.text.font = - theme->osd_font_hilite; - theme->osd_hilite_label->texture[0].data.text.color = - theme->osd_text_active_color; - - theme->osd_unhilite_label->texture[0].type = RR_TEXTURE_TEXT; - theme->osd_unhilite_label->texture[0].data.text.justify = RR_JUSTIFY_LEFT; - theme->osd_unhilite_label->texture[0].data.text.font = - theme->osd_font_unhilite; - theme->osd_unhilite_label->texture[0].data.text.color = - theme->osd_text_inactive_color; - - if (read_string(db, "osd.active.label.text.font", &str) || - read_string(db, "osd.label.text.font", &str)) - { - char *p; - gint i = 0; - gint j; - if (strstr(str, "shadow=y")) { - if ((p = strstr(str, "shadowoffset="))) - i = parse_inline_number(p + strlen("shadowoffset=")); - else - i = 1; - theme->osd_hilite_label->texture[0].data.text.shadow_offset_x = i; - theme->osd_hilite_label->texture[0].data.text.shadow_offset_y = i; - } - if ((p = strstr(str, "shadowtint="))) - { - i = parse_inline_number(p + strlen("shadowtint=")); - j = (i > 0 ? 0 : 255); - i = ABS(i*255/100); - - theme->osd_text_active_shadow_color = RrColorNew(inst, j, j, j); - theme->osd_text_active_shadow_alpha = i; - } else { - theme->osd_text_active_shadow_color = RrColorNew(inst, 0, 0, 0); - theme->osd_text_active_shadow_alpha = 50; - } - } else { - /* inherit the font settings from the focused label */ - theme->osd_hilite_label->texture[0].data.text.shadow_offset_x = - theme->a_focused_label->texture[0].data.text.shadow_offset_x; - theme->osd_hilite_label->texture[0].data.text.shadow_offset_y = - theme->a_focused_label->texture[0].data.text.shadow_offset_y; - if (theme->title_focused_shadow_color) - theme->osd_text_active_shadow_color = - RrColorNew(inst, - theme->title_focused_shadow_color->r, - theme->title_focused_shadow_color->g, - theme->title_focused_shadow_color->b); - else - theme->osd_text_active_shadow_color = RrColorNew(inst, 0, 0, 0); - theme->osd_text_active_shadow_alpha = - theme->title_focused_shadow_alpha; - } - - theme->osd_hilite_label->texture[0].data.text.shadow_color = - theme->osd_text_active_shadow_color; - theme->osd_hilite_label->texture[0].data.text.shadow_alpha = - theme->osd_text_active_shadow_alpha; - - if (read_string(db, "osd.inactive.label.text.font", &str)) - { - char *p; - gint i = 0; - gint j; - if (strstr(str, "shadow=y")) { - if ((p = strstr(str, "shadowoffset="))) - i = parse_inline_number(p + strlen("shadowoffset=")); - else - i = 1; - theme->osd_unhilite_label->texture[0].data.text.shadow_offset_x=i; - theme->osd_unhilite_label->texture[0].data.text.shadow_offset_y=i; - } - if ((p = strstr(str, "shadowtint="))) - { - i = parse_inline_number(p + strlen("shadowtint=")); - j = (i > 0 ? 0 : 255); - i = ABS(i*255/100); - - theme->osd_text_inactive_shadow_color = RrColorNew(inst, j, j, j); - theme->osd_text_inactive_shadow_alpha = i; - } else { - theme->osd_text_inactive_shadow_color = RrColorNew(inst, 0, 0, 0); - theme->osd_text_inactive_shadow_alpha = 50; - } - } else { - /* inherit the font settings from the focused label */ - theme->osd_unhilite_label->texture[0].data.text.shadow_offset_x = - theme->a_unfocused_label->texture[0].data.text.shadow_offset_x; - theme->osd_unhilite_label->texture[0].data.text.shadow_offset_y = - theme->a_unfocused_label->texture[0].data.text.shadow_offset_y; - if (theme->title_unfocused_shadow_color) - theme->osd_text_inactive_shadow_color = - RrColorNew(inst, - theme->title_unfocused_shadow_color->r, - theme->title_unfocused_shadow_color->g, - theme->title_unfocused_shadow_color->b); - else - theme->osd_text_inactive_shadow_color = RrColorNew(inst, 0, 0, 0); - theme->osd_text_inactive_shadow_alpha = - theme->title_unfocused_shadow_alpha; - } - - theme->osd_unhilite_label->texture[0].data.text.shadow_color = - theme->osd_text_inactive_shadow_color; - theme->osd_unhilite_label->texture[0].data.text.shadow_alpha = - theme->osd_text_inactive_shadow_alpha; - - theme->a_unfocused_label->texture[0].type = RR_TEXTURE_TEXT; - theme->a_unfocused_label->texture[0].data.text.justify = winjust; - theme->a_unfocused_label->texture[0].data.text.font = - theme->win_font_unfocused; - theme->a_unfocused_label->texture[0].data.text.color = - theme->title_unfocused_color; - - if (read_string(db, "window.inactive.label.text.font", &str)) { - char *p; - gint i = 0; - gint j; - if (strstr(str, "shadow=y")) { - if ((p = strstr(str, "shadowoffset="))) - i = parse_inline_number(p + strlen("shadowoffset=")); - else - i = 1; - theme->a_unfocused_label->texture[0].data.text.shadow_offset_x = i; - theme->a_unfocused_label->texture[0].data.text.shadow_offset_y = i; - } - if ((p = strstr(str, "shadowtint="))) - { - i = parse_inline_number(p + strlen("shadowtint=")); - j = (i > 0 ? 0 : 255); - i = ABS(i*255/100); - - theme->title_unfocused_shadow_color = RrColorNew(inst, j, j, j); - theme->title_unfocused_shadow_alpha = i; - } else { - theme->title_unfocused_shadow_color = RrColorNew(inst, 0, 0, 0); - theme->title_unfocused_shadow_alpha = 50; - } - } - - theme->a_unfocused_label->texture[0].data.text.shadow_color = - theme->title_unfocused_shadow_color; - theme->a_unfocused_label->texture[0].data.text.shadow_alpha = - theme->title_unfocused_shadow_alpha; - - theme->a_menu_text_title->texture[0].type = RR_TEXTURE_TEXT; - theme->a_menu_text_title->texture[0].data.text.justify = mtitlejust; - theme->a_menu_text_title->texture[0].data.text.font = - theme->menu_title_font; - theme->a_menu_text_title->texture[0].data.text.color = - theme->menu_title_color; - - if (read_string(db, "menu.title.text.font", &str)) { - char *p; - gint i = 0; - gint j; - if (strstr(str, "shadow=y")) { - if ((p = strstr(str, "shadowoffset="))) - i = parse_inline_number(p + strlen("shadowoffset=")); - else - i = 1; - theme->a_menu_text_title->texture[0].data.text.shadow_offset_x = i; - theme->a_menu_text_title->texture[0].data.text.shadow_offset_y = i; - } - if ((p = strstr(str, "shadowtint="))) - { - i = parse_inline_number(p + strlen("shadowtint=")); - j = (i > 0 ? 0 : 255); - i = ABS(i*255/100); - - theme->menu_title_shadow_color = RrColorNew(inst, j, j, j); - theme->menu_title_shadow_alpha = i; - } else { - theme->menu_title_shadow_color = RrColorNew(inst, 0, 0, 0); - theme->menu_title_shadow_alpha = 50; - } - } - - theme->a_menu_text_title->texture[0].data.text.shadow_color = - theme->menu_title_shadow_color; - theme->a_menu_text_title->texture[0].data.text.shadow_alpha = - theme->menu_title_shadow_alpha; - - theme->a_menu_text_normal->texture[0].type = - theme->a_menu_text_selected->texture[0].type = - theme->a_menu_text_disabled->texture[0].type = - theme->a_menu_text_disabled_selected->texture[0].type = - RR_TEXTURE_TEXT; - theme->a_menu_text_normal->texture[0].data.text.justify = - theme->a_menu_text_selected->texture[0].data.text.justify = - theme->a_menu_text_disabled->texture[0].data.text.justify = - theme->a_menu_text_disabled_selected->texture[0].data.text.justify = - RR_JUSTIFY_LEFT; - theme->a_menu_text_normal->texture[0].data.text.font = - theme->a_menu_text_selected->texture[0].data.text.font = - theme->a_menu_text_disabled->texture[0].data.text.font = - theme->a_menu_text_disabled_selected->texture[0].data.text.font = - theme->menu_font; - theme->a_menu_text_normal->texture[0].data.text.color = theme->menu_color; - theme->a_menu_text_selected->texture[0].data.text.color = - theme->menu_selected_color; - theme->a_menu_text_disabled->texture[0].data.text.color = - theme->menu_disabled_color; - theme->a_menu_text_disabled_selected->texture[0].data.text.color = - theme->menu_disabled_selected_color; - - if (read_string(db, "menu.items.font", &str)) { - char *p; - gint i = 0; - gint j; - if (strstr(str, "shadow=y")) { - if ((p = strstr(str, "shadowoffset="))) - i = parse_inline_number(p + strlen("shadowoffset=")); - else - i = 1; - theme->a_menu_text_normal-> - texture[0].data.text.shadow_offset_x = i; - theme->a_menu_text_normal-> - texture[0].data.text.shadow_offset_y = i; - theme->a_menu_text_selected-> - texture[0].data.text.shadow_offset_x = i; - theme->a_menu_text_selected-> - texture[0].data.text.shadow_offset_y = i; - theme->a_menu_text_disabled-> - texture[0].data.text.shadow_offset_x = i; - theme->a_menu_text_disabled-> - texture[0].data.text.shadow_offset_y = i; - theme->a_menu_text_disabled_selected-> - texture[0].data.text.shadow_offset_x = i; - theme->a_menu_text_disabled_selected-> - texture[0].data.text.shadow_offset_y = i; - } - if ((p = strstr(str, "shadowtint="))) - { - i = parse_inline_number(p + strlen("shadowtint=")); - j = (i > 0 ? 0 : 255); - i = ABS(i*255/100); - - theme->menu_text_normal_shadow_color = RrColorNew(inst, j, j, j); - theme->menu_text_selected_shadow_color = RrColorNew(inst, j, j, j); - theme->menu_text_disabled_shadow_color = RrColorNew(inst, j, j, j); - theme->menu_text_normal_shadow_alpha = i; - theme->menu_text_selected_shadow_alpha = i; - theme->menu_text_disabled_shadow_alpha = i; - theme->menu_text_disabled_selected_shadow_alpha = i; - } else { - theme->menu_text_normal_shadow_color = RrColorNew(inst, 0, 0, 0); - theme->menu_text_selected_shadow_color = RrColorNew(inst, 0, 0, 0); - theme->menu_text_disabled_shadow_color = RrColorNew(inst, 0, 0, 0); - theme->menu_text_normal_shadow_alpha = 50; - theme->menu_text_selected_shadow_alpha = 50; - theme->menu_text_disabled_selected_shadow_alpha = 50; - } - } - - theme->a_menu_text_normal->texture[0].data.text.shadow_color = - theme->menu_text_normal_shadow_color; - theme->a_menu_text_normal->texture[0].data.text.shadow_alpha = - theme->menu_text_normal_shadow_alpha; - theme->a_menu_text_selected->texture[0].data.text.shadow_color = - theme->menu_text_selected_shadow_color; - theme->a_menu_text_selected->texture[0].data.text.shadow_alpha = - theme->menu_text_selected_shadow_alpha; - theme->a_menu_text_disabled->texture[0].data.text.shadow_color = - theme->menu_text_disabled_shadow_color; - theme->a_menu_text_disabled->texture[0].data.text.shadow_alpha = - theme->menu_text_disabled_shadow_alpha; - theme->a_menu_text_disabled_selected->texture[0].data.text.shadow_color = - theme->menu_text_disabled_shadow_color; - theme->a_menu_text_disabled_selected->texture[0].data.text.shadow_alpha = - theme->menu_text_disabled_shadow_alpha; - - theme->a_disabled_focused_max->texture[0].type = - theme->a_disabled_unfocused_max->texture[0].type = - theme->a_hover_focused_max->texture[0].type = - theme->a_hover_unfocused_max->texture[0].type = - theme->a_toggled_hover_focused_max->texture[0].type = - theme->a_toggled_hover_unfocused_max->texture[0].type = - theme->a_toggled_focused_unpressed_max->texture[0].type = - theme->a_toggled_unfocused_unpressed_max->texture[0].type = - theme->a_toggled_focused_pressed_max->texture[0].type = - theme->a_toggled_unfocused_pressed_max->texture[0].type = - theme->a_focused_unpressed_max->texture[0].type = - theme->a_focused_pressed_max->texture[0].type = - theme->a_unfocused_unpressed_max->texture[0].type = - theme->a_unfocused_pressed_max->texture[0].type = - theme->a_disabled_focused_close->texture[0].type = - theme->a_disabled_unfocused_close->texture[0].type = - theme->a_hover_focused_close->texture[0].type = - theme->a_hover_unfocused_close->texture[0].type = - theme->a_focused_unpressed_close->texture[0].type = - theme->a_focused_pressed_close->texture[0].type = - theme->a_unfocused_unpressed_close->texture[0].type = - theme->a_unfocused_pressed_close->texture[0].type = - theme->a_disabled_focused_desk->texture[0].type = - theme->a_disabled_unfocused_desk->texture[0].type = - theme->a_hover_focused_desk->texture[0].type = - theme->a_hover_unfocused_desk->texture[0].type = - theme->a_toggled_hover_focused_desk->texture[0].type = - theme->a_toggled_hover_unfocused_desk->texture[0].type = - theme->a_toggled_focused_unpressed_desk->texture[0].type = - theme->a_toggled_unfocused_unpressed_desk->texture[0].type = - theme->a_toggled_focused_pressed_desk->texture[0].type = - theme->a_toggled_unfocused_pressed_desk->texture[0].type = - theme->a_focused_unpressed_desk->texture[0].type = - theme->a_focused_pressed_desk->texture[0].type = - theme->a_unfocused_unpressed_desk->texture[0].type = - theme->a_unfocused_pressed_desk->texture[0].type = - theme->a_disabled_focused_shade->texture[0].type = - theme->a_disabled_unfocused_shade->texture[0].type = - theme->a_hover_focused_shade->texture[0].type = - theme->a_hover_unfocused_shade->texture[0].type = - theme->a_toggled_hover_focused_shade->texture[0].type = - theme->a_toggled_hover_unfocused_shade->texture[0].type = - theme->a_toggled_focused_unpressed_shade->texture[0].type = - theme->a_toggled_unfocused_unpressed_shade->texture[0].type = - theme->a_toggled_focused_pressed_shade->texture[0].type = - theme->a_toggled_unfocused_pressed_shade->texture[0].type = - theme->a_focused_unpressed_shade->texture[0].type = - theme->a_focused_pressed_shade->texture[0].type = - theme->a_unfocused_unpressed_shade->texture[0].type = - theme->a_unfocused_pressed_shade->texture[0].type = - theme->a_disabled_focused_iconify->texture[0].type = - theme->a_disabled_unfocused_iconify->texture[0].type = - theme->a_hover_focused_iconify->texture[0].type = - theme->a_hover_unfocused_iconify->texture[0].type = - theme->a_focused_unpressed_iconify->texture[0].type = - theme->a_focused_pressed_iconify->texture[0].type = - theme->a_unfocused_unpressed_iconify->texture[0].type = - theme->a_unfocused_pressed_iconify->texture[0].type = - theme->a_menu_bullet_normal->texture[0].type = - theme->a_menu_bullet_selected->texture[0].type = RR_TEXTURE_MASK; - - theme->a_disabled_focused_max->texture[0].data.mask.mask = - theme->a_disabled_unfocused_max->texture[0].data.mask.mask = - theme->max_disabled_mask; - theme->a_hover_focused_max->texture[0].data.mask.mask = - theme->a_hover_unfocused_max->texture[0].data.mask.mask = - theme->max_hover_mask; - theme->a_focused_pressed_max->texture[0].data.mask.mask = - theme->a_unfocused_pressed_max->texture[0].data.mask.mask = - theme->max_pressed_mask; - theme->a_focused_unpressed_max->texture[0].data.mask.mask = - theme->a_unfocused_unpressed_max->texture[0].data.mask.mask = - theme->max_mask; - theme->a_toggled_hover_focused_max->texture[0].data.mask.mask = - theme->a_toggled_hover_unfocused_max->texture[0].data.mask.mask = - theme->max_toggled_hover_mask; - theme->a_toggled_focused_unpressed_max->texture[0].data.mask.mask = - theme->a_toggled_unfocused_unpressed_max->texture[0].data.mask.mask = - theme->max_toggled_mask; - theme->a_toggled_focused_pressed_max->texture[0].data.mask.mask = - theme->a_toggled_unfocused_pressed_max->texture[0].data.mask.mask = - theme->max_toggled_pressed_mask; - theme->a_disabled_focused_close->texture[0].data.mask.mask = - theme->a_disabled_unfocused_close->texture[0].data.mask.mask = - theme->close_disabled_mask; - theme->a_hover_focused_close->texture[0].data.mask.mask = - theme->a_hover_unfocused_close->texture[0].data.mask.mask = - theme->close_hover_mask; - theme->a_focused_pressed_close->texture[0].data.mask.mask = - theme->a_unfocused_pressed_close->texture[0].data.mask.mask = - theme->close_pressed_mask; - theme->a_focused_unpressed_close->texture[0].data.mask.mask = - theme->a_unfocused_unpressed_close->texture[0].data.mask.mask = - theme->close_mask; - theme->a_disabled_focused_desk->texture[0].data.mask.mask = - theme->a_disabled_unfocused_desk->texture[0].data.mask.mask = - theme->desk_disabled_mask; - theme->a_hover_focused_desk->texture[0].data.mask.mask = - theme->a_hover_unfocused_desk->texture[0].data.mask.mask = - theme->desk_hover_mask; - theme->a_focused_pressed_desk->texture[0].data.mask.mask = - theme->a_unfocused_pressed_desk->texture[0].data.mask.mask = - theme->desk_pressed_mask; - theme->a_focused_unpressed_desk->texture[0].data.mask.mask = - theme->a_unfocused_unpressed_desk->texture[0].data.mask.mask = - theme->desk_mask; - theme->a_toggled_hover_focused_desk->texture[0].data.mask.mask = - theme->a_toggled_hover_unfocused_desk->texture[0].data.mask.mask = - theme->desk_toggled_hover_mask; - theme->a_toggled_focused_unpressed_desk->texture[0].data.mask.mask = - theme->a_toggled_unfocused_unpressed_desk->texture[0].data.mask.mask = - theme->desk_toggled_mask; - theme->a_toggled_focused_pressed_desk->texture[0].data.mask.mask = - theme->a_toggled_unfocused_pressed_desk->texture[0].data.mask.mask = - theme->desk_toggled_pressed_mask; - theme->a_disabled_focused_shade->texture[0].data.mask.mask = - theme->a_disabled_unfocused_shade->texture[0].data.mask.mask = - theme->shade_disabled_mask; - theme->a_hover_focused_shade->texture[0].data.mask.mask = - theme->a_hover_unfocused_shade->texture[0].data.mask.mask = - theme->shade_hover_mask; - theme->a_focused_pressed_shade->texture[0].data.mask.mask = - theme->a_unfocused_pressed_shade->texture[0].data.mask.mask = - theme->shade_pressed_mask; - theme->a_focused_unpressed_shade->texture[0].data.mask.mask = - theme->a_unfocused_unpressed_shade->texture[0].data.mask.mask = - theme->shade_mask; - theme->a_toggled_hover_focused_shade->texture[0].data.mask.mask = - theme->a_toggled_hover_unfocused_shade->texture[0].data.mask.mask = - theme->shade_toggled_hover_mask; - theme->a_toggled_focused_unpressed_shade->texture[0].data.mask.mask = - theme->a_toggled_unfocused_unpressed_shade->texture[0].data.mask.mask = - theme->shade_toggled_mask; - theme->a_toggled_focused_pressed_shade->texture[0].data.mask.mask = - theme->a_toggled_unfocused_pressed_shade->texture[0].data.mask.mask = - theme->shade_toggled_pressed_mask; - theme->a_disabled_focused_iconify->texture[0].data.mask.mask = - theme->a_disabled_unfocused_iconify->texture[0].data.mask.mask = - theme->iconify_disabled_mask; - theme->a_hover_focused_iconify->texture[0].data.mask.mask = - theme->a_hover_unfocused_iconify->texture[0].data.mask.mask = - theme->iconify_hover_mask; - theme->a_focused_pressed_iconify->texture[0].data.mask.mask = - theme->a_unfocused_pressed_iconify->texture[0].data.mask.mask = - theme->iconify_pressed_mask; - theme->a_focused_unpressed_iconify->texture[0].data.mask.mask = - theme->a_unfocused_unpressed_iconify->texture[0].data.mask.mask = - theme->iconify_mask; - theme->a_menu_bullet_normal->texture[0].data.mask.mask = - theme->a_menu_bullet_selected->texture[0].data.mask.mask = - theme->menu_bullet_mask; - theme->a_disabled_focused_max->texture[0].data.mask.color = - theme->a_disabled_focused_close->texture[0].data.mask.color = - theme->a_disabled_focused_desk->texture[0].data.mask.color = - theme->a_disabled_focused_shade->texture[0].data.mask.color = - theme->a_disabled_focused_iconify->texture[0].data.mask.color = - theme->titlebut_disabled_focused_color; - theme->a_disabled_unfocused_max->texture[0].data.mask.color = - theme->a_disabled_unfocused_close->texture[0].data.mask.color = - theme->a_disabled_unfocused_desk->texture[0].data.mask.color = - theme->a_disabled_unfocused_shade->texture[0].data.mask.color = - theme->a_disabled_unfocused_iconify->texture[0].data.mask.color = - theme->titlebut_disabled_unfocused_color; - theme->a_hover_focused_max->texture[0].data.mask.color = - theme->a_hover_focused_close->texture[0].data.mask.color = - theme->a_hover_focused_desk->texture[0].data.mask.color = - theme->a_hover_focused_shade->texture[0].data.mask.color = - theme->a_hover_focused_iconify->texture[0].data.mask.color = - theme->titlebut_hover_focused_color; - theme->a_hover_unfocused_max->texture[0].data.mask.color = - theme->a_hover_unfocused_close->texture[0].data.mask.color = - theme->a_hover_unfocused_desk->texture[0].data.mask.color = - theme->a_hover_unfocused_shade->texture[0].data.mask.color = - theme->a_hover_unfocused_iconify->texture[0].data.mask.color = - theme->titlebut_hover_unfocused_color; - theme->a_toggled_hover_focused_max->texture[0].data.mask.color = - theme->a_toggled_hover_focused_desk->texture[0].data.mask.color = - theme->a_toggled_hover_focused_shade->texture[0].data.mask.color = - theme->titlebut_toggled_hover_focused_color; - theme->a_toggled_hover_unfocused_max->texture[0].data.mask.color = - theme->a_toggled_hover_unfocused_desk->texture[0].data.mask.color = - theme->a_toggled_hover_unfocused_shade->texture[0].data.mask.color = - theme->titlebut_toggled_hover_unfocused_color; - theme->a_toggled_focused_unpressed_max->texture[0].data.mask.color = - theme->a_toggled_focused_unpressed_desk->texture[0].data.mask.color = - theme->a_toggled_focused_unpressed_shade->texture[0].data.mask.color = - theme->titlebut_toggled_focused_unpressed_color; - theme->a_toggled_unfocused_unpressed_max->texture[0].data.mask.color = - theme->a_toggled_unfocused_unpressed_desk->texture[0].data.mask.color = - theme->a_toggled_unfocused_unpressed_shade->texture[0].data.mask.color= - theme->titlebut_toggled_unfocused_unpressed_color; - theme->a_toggled_focused_pressed_max->texture[0].data.mask.color = - theme->a_toggled_focused_pressed_desk->texture[0].data.mask.color = - theme->a_toggled_focused_pressed_shade->texture[0].data.mask.color = - theme->titlebut_toggled_focused_pressed_color; - theme->a_toggled_unfocused_pressed_max->texture[0].data.mask.color = - theme->a_toggled_unfocused_pressed_desk->texture[0].data.mask.color = - theme->a_toggled_unfocused_pressed_shade->texture[0].data.mask.color = - theme->titlebut_toggled_unfocused_pressed_color; - theme->a_focused_unpressed_max->texture[0].data.mask.color = - theme->a_focused_unpressed_close->texture[0].data.mask.color = - theme->a_focused_unpressed_desk->texture[0].data.mask.color = - theme->a_focused_unpressed_shade->texture[0].data.mask.color = - theme->a_focused_unpressed_iconify->texture[0].data.mask.color = - theme->titlebut_focused_unpressed_color; - theme->a_focused_pressed_max->texture[0].data.mask.color = - theme->a_focused_pressed_close->texture[0].data.mask.color = - theme->a_focused_pressed_desk->texture[0].data.mask.color = - theme->a_focused_pressed_shade->texture[0].data.mask.color = - theme->a_focused_pressed_iconify->texture[0].data.mask.color = - theme->titlebut_focused_pressed_color; - theme->a_unfocused_unpressed_max->texture[0].data.mask.color = - theme->a_unfocused_unpressed_close->texture[0].data.mask.color = - theme->a_unfocused_unpressed_desk->texture[0].data.mask.color = - theme->a_unfocused_unpressed_shade->texture[0].data.mask.color = - theme->a_unfocused_unpressed_iconify->texture[0].data.mask.color = - theme->titlebut_unfocused_unpressed_color; - theme->a_unfocused_pressed_max->texture[0].data.mask.color = - theme->a_unfocused_pressed_close->texture[0].data.mask.color = - theme->a_unfocused_pressed_desk->texture[0].data.mask.color = - theme->a_unfocused_pressed_shade->texture[0].data.mask.color = - theme->a_unfocused_pressed_iconify->texture[0].data.mask.color = - theme->titlebut_unfocused_pressed_color; - theme->a_menu_bullet_normal->texture[0].data.mask.color = - theme->menu_color; - theme->a_menu_bullet_selected->texture[0].data.mask.color = - theme->menu_selected_color; - - g_free(path); - XrmDestroyDatabase(db); - - /* set the font heights */ - theme->win_font_height = RrFontHeight - (theme->win_font_focused, - theme->a_focused_label->texture[0].data.text.shadow_offset_y); - theme->win_font_height = - MAX(theme->win_font_height, - RrFontHeight - (theme->win_font_focused, - theme->a_unfocused_label->texture[0].data.text.shadow_offset_y)); - theme->menu_title_font_height = RrFontHeight - (theme->menu_title_font, - theme->a_menu_text_title->texture[0].data.text.shadow_offset_y); - theme->menu_font_height = RrFontHeight - (theme->menu_font, - theme->a_menu_text_normal->texture[0].data.text.shadow_offset_y); - - /* calculate some last extents */ - { - gint ft, fb, fl, fr, ut, ub, ul, ur; - - RrMargins(theme->a_focused_label, &fl, &ft, &fr, &fb); - RrMargins(theme->a_unfocused_label, &ul, &ut, &ur, &ub); - theme->label_height = theme->win_font_height + MAX(ft + fb, ut + ub); - theme->label_height += theme->label_height % 2; - - /* this would be nice I think, since padding.width can now be 0, - but it breaks frame.c horribly and I don't feel like fixing that - right now, so if anyone complains, here is how to keep text from - going over the title's bevel/border with a padding.width of 0 and a - bevelless/borderless label - RrMargins(theme->a_focused_title, &fl, &ft, &fr, &fb); - RrMargins(theme->a_unfocused_title, &ul, &ut, &ur, &ub); - theme->title_height = theme->label_height + - MAX(MAX(theme->padding * 2, ft + fb), - MAX(theme->padding * 2, ut + ub)); - */ - theme->title_height = theme->label_height + theme->paddingy * 2; - - RrMargins(theme->a_menu_title, &ul, &ut, &ur, &ub); - theme->menu_title_label_height = theme->menu_title_font_height+ut+ub; - theme->menu_title_height = theme->menu_title_label_height + - theme->paddingy * 2; - } - theme->button_size = theme->label_height - 2; - theme->grip_width = 25; - - return theme; -} - -void RrThemeFree(RrTheme *theme) -{ - if (theme) { - g_free(theme->name); - - RrColorFree(theme->menu_border_color); - RrColorFree(theme->osd_border_color); - RrColorFree(theme->frame_focused_border_color); - RrColorFree(theme->frame_unfocused_border_color); - RrColorFree(theme->title_separator_focused_color); - RrColorFree(theme->title_separator_unfocused_color); - RrColorFree(theme->cb_unfocused_color); - RrColorFree(theme->cb_focused_color); - RrColorFree(theme->title_focused_color); - RrColorFree(theme->title_unfocused_color); - RrColorFree(theme->titlebut_disabled_focused_color); - RrColorFree(theme->titlebut_disabled_unfocused_color); - RrColorFree(theme->titlebut_hover_focused_color); - RrColorFree(theme->titlebut_hover_unfocused_color); - RrColorFree(theme->titlebut_toggled_hover_focused_color); - RrColorFree(theme->titlebut_toggled_hover_unfocused_color); - RrColorFree(theme->titlebut_toggled_focused_pressed_color); - RrColorFree(theme->titlebut_toggled_unfocused_pressed_color); - RrColorFree(theme->titlebut_toggled_focused_unpressed_color); - RrColorFree(theme->titlebut_toggled_unfocused_unpressed_color); - RrColorFree(theme->titlebut_focused_pressed_color); - RrColorFree(theme->titlebut_unfocused_pressed_color); - RrColorFree(theme->titlebut_focused_unpressed_color); - RrColorFree(theme->titlebut_unfocused_unpressed_color); - RrColorFree(theme->menu_title_color); - RrColorFree(theme->menu_sep_color); - RrColorFree(theme->menu_color); - RrColorFree(theme->menu_selected_color); - RrColorFree(theme->menu_disabled_color); - RrColorFree(theme->menu_disabled_selected_color); - RrColorFree(theme->title_focused_shadow_color); - RrColorFree(theme->title_unfocused_shadow_color); - RrColorFree(theme->osd_text_active_color); - RrColorFree(theme->osd_text_inactive_color); - RrColorFree(theme->osd_text_active_shadow_color); - RrColorFree(theme->osd_text_inactive_shadow_color); - RrColorFree(theme->menu_title_shadow_color); - RrColorFree(theme->menu_text_normal_shadow_color); - RrColorFree(theme->menu_text_selected_shadow_color); - RrColorFree(theme->menu_text_disabled_shadow_color); - RrColorFree(theme->menu_text_disabled_selected_shadow_color); - - g_free(theme->def_win_icon); - - RrPixmapMaskFree(theme->max_mask); - RrPixmapMaskFree(theme->max_toggled_mask); - RrPixmapMaskFree(theme->max_toggled_hover_mask); - RrPixmapMaskFree(theme->max_toggled_pressed_mask); - RrPixmapMaskFree(theme->max_disabled_mask); - RrPixmapMaskFree(theme->max_hover_mask); - RrPixmapMaskFree(theme->max_pressed_mask); - RrPixmapMaskFree(theme->desk_mask); - RrPixmapMaskFree(theme->desk_toggled_mask); - RrPixmapMaskFree(theme->desk_toggled_hover_mask); - RrPixmapMaskFree(theme->desk_toggled_pressed_mask); - RrPixmapMaskFree(theme->desk_disabled_mask); - RrPixmapMaskFree(theme->desk_hover_mask); - RrPixmapMaskFree(theme->desk_pressed_mask); - RrPixmapMaskFree(theme->shade_mask); - RrPixmapMaskFree(theme->shade_toggled_mask); - RrPixmapMaskFree(theme->shade_toggled_hover_mask); - RrPixmapMaskFree(theme->shade_toggled_pressed_mask); - RrPixmapMaskFree(theme->shade_disabled_mask); - RrPixmapMaskFree(theme->shade_hover_mask); - RrPixmapMaskFree(theme->shade_pressed_mask); - RrPixmapMaskFree(theme->iconify_mask); - RrPixmapMaskFree(theme->iconify_disabled_mask); - RrPixmapMaskFree(theme->iconify_hover_mask); - RrPixmapMaskFree(theme->iconify_pressed_mask); - RrPixmapMaskFree(theme->close_mask); - RrPixmapMaskFree(theme->close_disabled_mask); - RrPixmapMaskFree(theme->close_hover_mask); - RrPixmapMaskFree(theme->close_pressed_mask); - RrPixmapMaskFree(theme->menu_bullet_mask); - RrPixmapMaskFree(theme->down_arrow_mask); - RrPixmapMaskFree(theme->up_arrow_mask); - - RrFontClose(theme->win_font_focused); - RrFontClose(theme->win_font_unfocused); - RrFontClose(theme->menu_title_font); - RrFontClose(theme->menu_font); - RrFontClose(theme->osd_font_hilite); - RrFontClose(theme->osd_font_unhilite); - - RrAppearanceFree(theme->a_disabled_focused_max); - RrAppearanceFree(theme->a_disabled_unfocused_max); - RrAppearanceFree(theme->a_hover_focused_max); - RrAppearanceFree(theme->a_hover_unfocused_max); - RrAppearanceFree(theme->a_toggled_hover_focused_max); - RrAppearanceFree(theme->a_toggled_hover_unfocused_max); - RrAppearanceFree(theme->a_toggled_focused_unpressed_max); - RrAppearanceFree(theme->a_toggled_focused_pressed_max); - RrAppearanceFree(theme->a_toggled_unfocused_unpressed_max); - RrAppearanceFree(theme->a_toggled_unfocused_pressed_max); - RrAppearanceFree(theme->a_focused_unpressed_max); - RrAppearanceFree(theme->a_focused_pressed_max); - RrAppearanceFree(theme->a_unfocused_unpressed_max); - RrAppearanceFree(theme->a_unfocused_pressed_max); - RrAppearanceFree(theme->a_disabled_focused_close); - RrAppearanceFree(theme->a_disabled_unfocused_close); - RrAppearanceFree(theme->a_hover_focused_close); - RrAppearanceFree(theme->a_hover_unfocused_close); - RrAppearanceFree(theme->a_focused_unpressed_close); - RrAppearanceFree(theme->a_focused_pressed_close); - RrAppearanceFree(theme->a_unfocused_unpressed_close); - RrAppearanceFree(theme->a_unfocused_pressed_close); - RrAppearanceFree(theme->a_disabled_focused_desk); - RrAppearanceFree(theme->a_disabled_unfocused_desk); - RrAppearanceFree(theme->a_hover_focused_desk); - RrAppearanceFree(theme->a_hover_unfocused_desk); - RrAppearanceFree(theme->a_toggled_hover_focused_desk); - RrAppearanceFree(theme->a_toggled_hover_unfocused_desk); - RrAppearanceFree(theme->a_toggled_focused_unpressed_desk); - RrAppearanceFree(theme->a_toggled_focused_pressed_desk); - RrAppearanceFree(theme->a_toggled_unfocused_unpressed_desk); - RrAppearanceFree(theme->a_toggled_unfocused_pressed_desk); - RrAppearanceFree(theme->a_focused_unpressed_desk); - RrAppearanceFree(theme->a_focused_pressed_desk); - RrAppearanceFree(theme->a_unfocused_unpressed_desk); - RrAppearanceFree(theme->a_unfocused_pressed_desk); - RrAppearanceFree(theme->a_disabled_focused_shade); - RrAppearanceFree(theme->a_disabled_unfocused_shade); - RrAppearanceFree(theme->a_hover_focused_shade); - RrAppearanceFree(theme->a_hover_unfocused_shade); - RrAppearanceFree(theme->a_toggled_hover_focused_shade); - RrAppearanceFree(theme->a_toggled_hover_unfocused_shade); - RrAppearanceFree(theme->a_toggled_focused_unpressed_shade); - RrAppearanceFree(theme->a_toggled_focused_pressed_shade); - RrAppearanceFree(theme->a_toggled_unfocused_unpressed_shade); - RrAppearanceFree(theme->a_toggled_unfocused_pressed_shade); - RrAppearanceFree(theme->a_focused_unpressed_shade); - RrAppearanceFree(theme->a_focused_pressed_shade); - RrAppearanceFree(theme->a_unfocused_unpressed_shade); - RrAppearanceFree(theme->a_unfocused_pressed_shade); - RrAppearanceFree(theme->a_disabled_focused_iconify); - RrAppearanceFree(theme->a_disabled_unfocused_iconify); - RrAppearanceFree(theme->a_hover_focused_iconify); - RrAppearanceFree(theme->a_hover_unfocused_iconify); - RrAppearanceFree(theme->a_focused_unpressed_iconify); - RrAppearanceFree(theme->a_focused_pressed_iconify); - RrAppearanceFree(theme->a_unfocused_unpressed_iconify); - RrAppearanceFree(theme->a_unfocused_pressed_iconify); - RrAppearanceFree(theme->a_focused_grip); - RrAppearanceFree(theme->a_unfocused_grip); - RrAppearanceFree(theme->a_focused_title); - RrAppearanceFree(theme->a_unfocused_title); - RrAppearanceFree(theme->a_focused_label); - RrAppearanceFree(theme->a_unfocused_label); - RrAppearanceFree(theme->a_icon); - RrAppearanceFree(theme->a_focused_handle); - RrAppearanceFree(theme->a_unfocused_handle); - RrAppearanceFree(theme->a_menu); - RrAppearanceFree(theme->a_menu_title); - RrAppearanceFree(theme->a_menu_text_title); - RrAppearanceFree(theme->a_menu_normal); - RrAppearanceFree(theme->a_menu_selected); - RrAppearanceFree(theme->a_menu_disabled); - RrAppearanceFree(theme->a_menu_disabled_selected); - RrAppearanceFree(theme->a_menu_text_normal); - RrAppearanceFree(theme->a_menu_text_selected); - RrAppearanceFree(theme->a_menu_text_disabled); - RrAppearanceFree(theme->a_menu_text_disabled_selected); - RrAppearanceFree(theme->a_menu_bullet_normal); - RrAppearanceFree(theme->a_menu_bullet_selected); - RrAppearanceFree(theme->a_clear); - RrAppearanceFree(theme->a_clear_tex); - RrAppearanceFree(theme->osd_bg); - RrAppearanceFree(theme->osd_hilite_bg); - RrAppearanceFree(theme->osd_hilite_label); - RrAppearanceFree(theme->osd_unhilite_bg); - RrAppearanceFree(theme->osd_unhilite_label); - - g_free(theme); - } -} - -static XrmDatabase loaddb(const gchar *name, gchar **path) -{ - GSList *it; - XrmDatabase db = NULL; - gchar *s; - - if (name[0] == '/') { - s = g_build_filename(name, "openbox-3", "themerc", NULL); - if ((db = XrmGetFileDatabase(s))) - *path = g_path_get_dirname(s); - g_free(s); - } else { - ObtPaths *p; - - p = obt_paths_new(); - - /* XXX backwards compatibility, remove me sometime later */ - s = g_build_filename(g_get_home_dir(), ".themes", name, - "openbox-3", "themerc", NULL); - if ((db = XrmGetFileDatabase(s))) - *path = g_path_get_dirname(s); - g_free(s); - - for (it = obt_paths_data_dirs(p); !db && it; it = g_slist_next(it)) - { - s = g_build_filename(it->data, "themes", name, - "openbox-3", "themerc", NULL); - if ((db = XrmGetFileDatabase(s))) - *path = g_path_get_dirname(s); - g_free(s); - } - - obt_paths_unref(p); - } - - if (db == NULL) { - s = g_build_filename(name, "themerc", NULL); - if ((db = XrmGetFileDatabase(s))) - *path = g_path_get_dirname(s); - g_free(s); - } - - return db; -} - -static gchar *create_class_name(const gchar *rname) -{ - gchar *rclass = g_strdup(rname); - gchar *p = rclass; - - while (TRUE) { - *p = toupper(*p); - p = strchr(p+1, '.'); - if (p == NULL) break; - ++p; - if (*p == '\0') break; - } - return rclass; -} - -static gboolean read_int(XrmDatabase db, const gchar *rname, gint *value) -{ - gboolean ret = FALSE; - gchar *rclass = create_class_name(rname); - gchar *rettype, *end; - XrmValue retvalue; - - if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) && - retvalue.addr != NULL) { - *value = (gint)strtol(retvalue.addr, &end, 10); - if (end != retvalue.addr) - ret = TRUE; - } - - g_free(rclass); - return ret; -} - -static gboolean read_string(XrmDatabase db, const gchar *rname, gchar **value) -{ - gboolean ret = FALSE; - gchar *rclass = create_class_name(rname); - gchar *rettype; - XrmValue retvalue; - - if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) && - retvalue.addr != NULL) { - *value = retvalue.addr; - ret = TRUE; - } - - g_free(rclass); - return ret; -} - -static gboolean read_color(XrmDatabase db, const RrInstance *inst, - const gchar *rname, RrColor **value) -{ - gboolean ret = FALSE; - gchar *rclass = create_class_name(rname); - gchar *rettype; - XrmValue retvalue; - - if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) && - retvalue.addr != NULL) { - RrColor *c = RrColorParse(inst, retvalue.addr); - if (c != NULL) { - *value = c; - ret = TRUE; - } - } - - g_free(rclass); - return ret; -} - -static gboolean read_mask(const RrInstance *inst, const gchar *path, - RrTheme *theme, const gchar *maskname, - RrPixmapMask **value) -{ - gboolean ret = FALSE; - gchar *s; - gint hx, hy; /* ignored */ - guint w, h; - guchar *b; - - s = g_build_filename(path, maskname, NULL); - if (XReadBitmapFileData(s, &w, &h, &b, &hx, &hy) == BitmapSuccess) { - ret = TRUE; - *value = RrPixmapMaskNew(inst, w, h, (gchar*)b); - XFree(b); - } - g_free(s); - - return ret; -} - -static void parse_appearance(gchar *tex, RrSurfaceColorType *grad, - RrReliefType *relief, RrBevelType *bevel, - gboolean *interlaced, gboolean *border, - gboolean allow_trans) -{ - gchar *t; - - /* convert to all lowercase */ - for (t = tex; *t != '\0'; ++t) - *t = g_ascii_tolower(*t); - - if (allow_trans && strstr(tex, "parentrelative") != NULL) { - *grad = RR_SURFACE_PARENTREL; - } else { - if (strstr(tex, "gradient") != NULL) { - if (strstr(tex, "crossdiagonal") != NULL) - *grad = RR_SURFACE_CROSS_DIAGONAL; - else if (strstr(tex, "pyramid") != NULL) - *grad = RR_SURFACE_PYRAMID; - else if (strstr(tex, "mirrorhorizontal") != NULL) - *grad = RR_SURFACE_MIRROR_HORIZONTAL; - else if (strstr(tex, "horizontal") != NULL) - *grad = RR_SURFACE_HORIZONTAL; - else if (strstr(tex, "splitvertical") != NULL) - *grad = RR_SURFACE_SPLIT_VERTICAL; - else if (strstr(tex, "vertical") != NULL) - *grad = RR_SURFACE_VERTICAL; - else - *grad = RR_SURFACE_DIAGONAL; - } else { - *grad = RR_SURFACE_SOLID; - } - } - - if (strstr(tex, "sunken") != NULL) - *relief = RR_RELIEF_SUNKEN; - else if (strstr(tex, "flat") != NULL) - *relief = RR_RELIEF_FLAT; - else if (strstr(tex, "raised") != NULL) - *relief = RR_RELIEF_RAISED; - else - *relief = (*grad == RR_SURFACE_PARENTREL) ? - RR_RELIEF_FLAT : RR_RELIEF_RAISED; - - *border = FALSE; - if (*relief == RR_RELIEF_FLAT) { - if (strstr(tex, "border") != NULL) - *border = TRUE; - } else { - if (strstr(tex, "bevel2") != NULL) - *bevel = RR_BEVEL_2; - else - *bevel = RR_BEVEL_1; - } - - if (strstr(tex, "interlaced") != NULL) - *interlaced = TRUE; - else - *interlaced = FALSE; -} - -static gboolean read_appearance(XrmDatabase db, const RrInstance *inst, - const gchar *rname, RrAppearance *value, - gboolean allow_trans) -{ - gboolean ret = FALSE; - gchar *rclass = create_class_name(rname); - gchar *cname, *ctoname, *bcname, *icname, *hname, *sname; - gchar *csplitname, *ctosplitname; - gchar *rettype; - XrmValue retvalue; - gint i; - - cname = g_strconcat(rname, ".color", NULL); - ctoname = g_strconcat(rname, ".colorTo", NULL); - bcname = g_strconcat(rname, ".border.color", NULL); - icname = g_strconcat(rname, ".interlace.color", NULL); - hname = g_strconcat(rname, ".highlight", NULL); - sname = g_strconcat(rname, ".shadow", NULL); - csplitname = g_strconcat(rname, ".color.splitTo", NULL); - ctosplitname = g_strconcat(rname, ".colorTo.splitTo", NULL); - - if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) && - retvalue.addr != NULL) { - parse_appearance(retvalue.addr, - &value->surface.grad, - &value->surface.relief, - &value->surface.bevel, - &value->surface.interlaced, - &value->surface.border, - allow_trans); - if (!read_color(db, inst, cname, &value->surface.primary)) - value->surface.primary = RrColorNew(inst, 0, 0, 0); - if (!read_color(db, inst, ctoname, &value->surface.secondary)) - value->surface.secondary = RrColorNew(inst, 0, 0, 0); - if (value->surface.border) - if (!read_color(db, inst, bcname, - &value->surface.border_color)) - value->surface.border_color = RrColorNew(inst, 0, 0, 0); - if (value->surface.interlaced) - if (!read_color(db, inst, icname, - &value->surface.interlace_color)) - value->surface.interlace_color = RrColorNew(inst, 0, 0, 0); - if (read_int(db, hname, &i) && i >= 0) - value->surface.bevel_light_adjust = i; - if (read_int(db, sname, &i) && i >= 0 && i <= 256) - value->surface.bevel_dark_adjust = i; - - if (value->surface.grad == RR_SURFACE_SPLIT_VERTICAL) { - gint r, g, b; - - if (!read_color(db, inst, csplitname, - &value->surface.split_primary)) - { - r = value->surface.primary->r; - r += r >> 2; - g = value->surface.primary->g; - g += g >> 2; - b = value->surface.primary->b; - b += b >> 2; - if (r > 0xFF) r = 0xFF; - if (g > 0xFF) g = 0xFF; - if (b > 0xFF) b = 0xFF; - value->surface.split_primary = RrColorNew(inst, r, g, b); - } - - if (!read_color(db, inst, ctosplitname, - &value->surface.split_secondary)) - { - r = value->surface.secondary->r; - r += r >> 4; - g = value->surface.secondary->g; - g += g >> 4; - b = value->surface.secondary->b; - b += b >> 4; - if (r > 0xFF) r = 0xFF; - if (g > 0xFF) g = 0xFF; - if (b > 0xFF) b = 0xFF; - value->surface.split_secondary = RrColorNew(inst, r, g, b); - } - } - - ret = TRUE; - } - - g_free(ctosplitname); - g_free(csplitname); - g_free(sname); - g_free(hname); - g_free(icname); - g_free(bcname); - g_free(ctoname); - g_free(cname); - g_free(rclass); - return ret; -} - -static int parse_inline_number(const char *p) -{ - int neg = 1; - int res = 0; - if (*p == '-') { - neg = -1; - ++p; - } - for (; isdigit(*p); ++p) - res = res * 10 + *p - '0'; - res *= neg; - return res; -} - -static void set_default_appearance(RrAppearance *a) -{ - a->surface.grad = RR_SURFACE_SOLID; - a->surface.relief = RR_RELIEF_FLAT; - a->surface.bevel = RR_BEVEL_1; - a->surface.interlaced = FALSE; - a->surface.border = FALSE; - a->surface.primary = RrColorNew(a->inst, 0, 0, 0); - a->surface.secondary = RrColorNew(a->inst, 0, 0, 0); -} - -/* Reads the output from gimp's C-Source file format into valid RGBA data for - an RrTextureRGBA. */ -static RrPixel32* read_c_image(gint width, gint height, const guint8 *data) -{ - RrPixel32 *im, *p; - gint i; - - p = im = g_memdup(data, width * height * sizeof(RrPixel32)); - - for (i = 0; i < width * height; ++i) { - guchar a = ((*p >> 24) & 0xff); - guchar b = ((*p >> 16) & 0xff); - guchar g = ((*p >> 8) & 0xff); - guchar r = ((*p >> 0) & 0xff); - - *p = ((r << RrDefaultRedOffset) + - (g << RrDefaultGreenOffset) + - (b << RrDefaultBlueOffset) + - (a << RrDefaultAlphaOffset)); - p++; - } - - return im; -} diff --git a/render/theme.h b/render/theme.h deleted file mode 100644 index 3f9063e6..00000000 --- a/render/theme.h +++ /dev/null @@ -1,266 +0,0 @@ -/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- - - theme.h for the Openbox window manager - Copyright (c) 2006 Mikael Magnusson - Copyright (c) 2003-2007 Dana Jansens - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - See the COPYING file for a copy of the GNU General Public License. -*/ - -#ifndef __theme_h -#define __theme_h - -#include "render.h" - -G_BEGIN_DECLS - -typedef struct _RrTheme RrTheme; - -struct _RrTheme { - const RrInstance *inst; - - /* style settings - fonts */ - RrFont *win_font_focused; - RrFont *win_font_unfocused; - RrFont *menu_title_font; - RrFont *menu_font; - RrFont *osd_font_hilite; - RrFont *osd_font_unhilite; - - /* style settings - geometry */ - gint paddingx; - gint paddingy; - gint handle_height; - gint fbwidth; /*!< frame border width */ - gint mbwidth; /*!< menu border width */ - gint obwidth; /*!< osd border width */ - gint cbwidthx; - gint cbwidthy; - gint menu_overlap_x; - gint menu_overlap_y; - gint menu_sep_width; - gint menu_sep_paddingx; - gint menu_sep_paddingy; - /* these ones are calculated, not set directly by the theme file */ - gint win_font_height; - gint menu_title_font_height; - gint menu_font_height; - gint label_height; - gint title_height; - gint button_size; - gint grip_width; - gint menu_title_label_height; - gint menu_title_height; - - /* style settings - colors */ - RrColor *menu_border_color; - RrColor *osd_border_color; - RrColor *frame_focused_border_color; - RrColor *frame_unfocused_border_color; - RrColor *title_separator_focused_color; - RrColor *title_separator_unfocused_color; - RrColor *cb_focused_color; - RrColor *cb_unfocused_color; - RrColor *title_focused_color; - RrColor *title_unfocused_color; - RrColor *titlebut_disabled_focused_color; - RrColor *titlebut_disabled_unfocused_color; - RrColor *titlebut_hover_focused_color; - RrColor *titlebut_hover_unfocused_color; - RrColor *titlebut_toggled_hover_focused_color; - RrColor *titlebut_toggled_hover_unfocused_color; - RrColor *titlebut_toggled_focused_pressed_color; - RrColor *titlebut_toggled_unfocused_pressed_color; - RrColor *titlebut_toggled_focused_unpressed_color; - RrColor *titlebut_toggled_unfocused_unpressed_color; - RrColor *titlebut_focused_pressed_color; - RrColor *titlebut_unfocused_pressed_color; - RrColor *titlebut_focused_unpressed_color; - RrColor *titlebut_unfocused_unpressed_color; - RrColor *menu_title_color; - RrColor *menu_sep_color; - RrColor *menu_color; - RrColor *menu_selected_color; - RrColor *menu_disabled_color; - RrColor *menu_disabled_selected_color; - RrColor *title_focused_shadow_color; - gchar title_focused_shadow_alpha; - RrColor *title_unfocused_shadow_color; - gchar title_unfocused_shadow_alpha; - RrColor *osd_text_active_color; - RrColor *osd_text_inactive_color; - RrColor *osd_text_active_shadow_color; - RrColor *osd_text_inactive_shadow_color; - gchar osd_text_active_shadow_alpha; - gchar osd_text_inactive_shadow_alpha; - RrColor *menu_title_shadow_color; - gchar menu_title_shadow_alpha; - RrColor *menu_text_normal_shadow_color; - gchar menu_text_normal_shadow_alpha; - RrColor *menu_text_selected_shadow_color; - gchar menu_text_selected_shadow_alpha; - RrColor *menu_text_disabled_shadow_color; - gchar menu_text_disabled_shadow_alpha; - RrColor *menu_text_disabled_selected_shadow_color; - gchar menu_text_disabled_selected_shadow_alpha; - - /* style settings - pics */ - RrPixel32 *def_win_icon; /* RGBA */ - gint def_win_icon_w; - gint def_win_icon_h; - - /* style settings - masks */ - RrPixmapMask *max_mask; - RrPixmapMask *max_hover_mask; - RrPixmapMask *max_pressed_mask; - RrPixmapMask *max_toggled_mask; - RrPixmapMask *max_toggled_hover_mask; - RrPixmapMask *max_toggled_pressed_mask; - RrPixmapMask *max_disabled_mask; - RrPixmapMask *iconify_mask; - RrPixmapMask *iconify_hover_mask; - RrPixmapMask *iconify_pressed_mask; - RrPixmapMask *iconify_disabled_mask; - RrPixmapMask *desk_mask; - RrPixmapMask *desk_hover_mask; - RrPixmapMask *desk_pressed_mask; - RrPixmapMask *desk_toggled_mask; - RrPixmapMask *desk_toggled_hover_mask; - RrPixmapMask *desk_toggled_pressed_mask; - RrPixmapMask *desk_disabled_mask; - RrPixmapMask *shade_mask; - RrPixmapMask *shade_hover_mask; - RrPixmapMask *shade_pressed_mask; - RrPixmapMask *shade_toggled_mask; - RrPixmapMask *shade_toggled_hover_mask; - RrPixmapMask *shade_toggled_pressed_mask; - RrPixmapMask *shade_disabled_mask; - RrPixmapMask *close_mask; - RrPixmapMask *close_hover_mask; - RrPixmapMask *close_disabled_mask; - RrPixmapMask *close_pressed_mask; - - RrPixmapMask *menu_bullet_mask; /* submenu pointer */ -#if 0 - RrPixmapMask *menu_toggle_mask; /* menu boolean */ -#endif - - RrPixmapMask *down_arrow_mask; - RrPixmapMask *up_arrow_mask; - - /* global appearances */ - RrAppearance *a_disabled_focused_max; - RrAppearance *a_disabled_unfocused_max; - RrAppearance *a_hover_focused_max; - RrAppearance *a_hover_unfocused_max; - RrAppearance *a_focused_unpressed_max; - RrAppearance *a_focused_pressed_max; - RrAppearance *a_unfocused_unpressed_max; - RrAppearance *a_unfocused_pressed_max; - RrAppearance *a_toggled_hover_focused_max; - RrAppearance *a_toggled_hover_unfocused_max; - RrAppearance *a_toggled_focused_unpressed_max; - RrAppearance *a_toggled_focused_pressed_max; - RrAppearance *a_toggled_unfocused_unpressed_max; - RrAppearance *a_toggled_unfocused_pressed_max; - RrAppearance *a_disabled_focused_close; - RrAppearance *a_disabled_unfocused_close; - RrAppearance *a_hover_focused_close; - RrAppearance *a_hover_unfocused_close; - RrAppearance *a_focused_unpressed_close; - RrAppearance *a_focused_pressed_close; - RrAppearance *a_unfocused_unpressed_close; - RrAppearance *a_unfocused_pressed_close; - RrAppearance *a_disabled_focused_desk; - RrAppearance *a_disabled_unfocused_desk; - RrAppearance *a_hover_focused_desk; - RrAppearance *a_hover_unfocused_desk; - RrAppearance *a_focused_unpressed_desk; - RrAppearance *a_focused_pressed_desk; - RrAppearance *a_unfocused_unpressed_desk; - RrAppearance *a_unfocused_pressed_desk; - RrAppearance *a_toggled_hover_focused_desk; - RrAppearance *a_toggled_hover_unfocused_desk; - RrAppearance *a_toggled_focused_unpressed_desk; - RrAppearance *a_toggled_focused_pressed_desk; - RrAppearance *a_toggled_unfocused_unpressed_desk; - RrAppearance *a_toggled_unfocused_pressed_desk; - RrAppearance *a_disabled_focused_shade; - RrAppearance *a_disabled_unfocused_shade; - RrAppearance *a_hover_focused_shade; - RrAppearance *a_hover_unfocused_shade; - RrAppearance *a_focused_unpressed_shade; - RrAppearance *a_focused_pressed_shade; - RrAppearance *a_unfocused_unpressed_shade; - RrAppearance *a_unfocused_pressed_shade; - RrAppearance *a_toggled_hover_focused_shade; - RrAppearance *a_toggled_hover_unfocused_shade; - RrAppearance *a_toggled_focused_unpressed_shade; - RrAppearance *a_toggled_focused_pressed_shade; - RrAppearance *a_toggled_unfocused_unpressed_shade; - RrAppearance *a_toggled_unfocused_pressed_shade; - RrAppearance *a_disabled_focused_iconify; - RrAppearance *a_disabled_unfocused_iconify; - RrAppearance *a_hover_focused_iconify; - RrAppearance *a_hover_unfocused_iconify; - RrAppearance *a_focused_unpressed_iconify; - RrAppearance *a_focused_pressed_iconify; - RrAppearance *a_unfocused_unpressed_iconify; - RrAppearance *a_unfocused_pressed_iconify; - RrAppearance *a_focused_grip; - RrAppearance *a_unfocused_grip; - RrAppearance *a_focused_title; - RrAppearance *a_unfocused_title; - RrAppearance *a_focused_label; - RrAppearance *a_unfocused_label; - /* always parentrelative, so no focused/unfocused */ - RrAppearance *a_icon; - RrAppearance *a_focused_handle; - RrAppearance *a_unfocused_handle; - RrAppearance *a_menu_text_title; - RrAppearance *a_menu_title; - RrAppearance *a_menu; - RrAppearance *a_menu_normal; - RrAppearance *a_menu_selected; - RrAppearance *a_menu_disabled; - RrAppearance *a_menu_disabled_selected; - RrAppearance *a_menu_text_normal; - RrAppearance *a_menu_text_disabled; - RrAppearance *a_menu_text_disabled_selected; - RrAppearance *a_menu_text_selected; - RrAppearance *a_menu_bullet_normal; - RrAppearance *a_menu_bullet_selected; - RrAppearance *a_clear; /* clear with no texture */ - RrAppearance *a_clear_tex; /* clear with a texture */ - - RrAppearance *osd_bg; /* can never be parent relative */ - RrAppearance *osd_hilite_bg; /* can never be parent relative */ - RrAppearance *osd_hilite_label; /* can be parent relative */ - RrAppearance *osd_unhilite_bg; /* can never be parent relative */ - RrAppearance *osd_unhilite_label; /* can be parent relative */ - - gchar *name; -}; - -/*! The font values are all optional. If a NULL is used for any of them, then - the default font will be used. */ -RrTheme* RrThemeNew(const RrInstance *inst, const gchar *theme, - gboolean allow_fallback, - RrFont *active_window_font, RrFont *inactive_window_font, - RrFont *menu_title_font, RrFont *menu_item_font, - RrFont *active_osd_font, RrFont *inactive_osd_font); -void RrThemeFree(RrTheme *theme); - -G_END_DECLS - -#endif diff --git a/render/version.h.in b/render/version.h.in deleted file mode 100644 index 0ff30b57..00000000 --- a/render/version.h.in +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef rr__version_h -#define rr__version_h - -#define RR_MAJOR_VERSION @RR_MAJOR_VERSION@ -#define RR_MINOR_VERSION @RR_MINOR_VERSION@ -#define RR_MICRO_VERSION @RR_MICRO_VERSION@ -#define RR_VERSION RR_MAJOR_VERSION.RR_MINOR_VERSION.RR_MICRO_VERSION - -#define RR_CHECK_VERSION(major,minor,micro) \ - (RR_MAJOR_VERSION > (major) || \ - (RR_MAJOR_VERSION == (major) && RR_MINOR_VERSION > (minor)) || \ - (RR_MAJOR_VERSION == (major) && RR_MINOR_VERSION == (minor) && \ - RR_MICRO_VERSION >= (micro))) - -#endif -- cgit v1.2.3