diff src/aosd/aosd_style.c @ 569:d401f87f89f7 trunk

[svn] - added Audacious OSD, yet-another-written-from-scratch plugin to display OSD, based on Ghosd library; currently untied from configure, to compile it you have to run make in its directory; will be added to configure after some testing
author giacomo
date Mon, 29 Jan 2007 06:40:04 -0800
parents
children 7ad870f10241
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/aosd/aosd_style.c	Mon Jan 29 06:40:04 2007 -0800
@@ -0,0 +1,332 @@
+/*
+*
+* Author: Giacomo Lozito <james@develia.org>, (C) 2005-2007
+*
+* 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.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+*
+*/
+
+#include "aosd_style.h"
+#include "aosd_style_private.h"
+#include "aosd_cfg.h"
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <X11/Xlib.h>
+#include <cairo/cairo.h>
+#include <pango/pangocairo.h>
+#include "ghosd.h"
+#include "ghosd-text.h"
+
+
+/* HOW TO ADD A NEW DECORATION STYLE
+   --------------------------------------------------------------------------
+   First, add a new decoration style code; then, provide the decoration style
+   information by adding a new entry in the aosd_deco_styles[] array (name,
+   render function, etc.); add the new decoration style code in the array
+   of decoration style codes, and update the define containing the array size.
+   The render function uses three parameters; the Ghosd instance, the cairo
+   object you use to draw, and a aosd_deco_style_data_t object that contains
+   user-defined options (look into aosd_style.h and aosd_cfg.h for details).
+   Have fun! :)
+*/
+
+
+/* decoration style codes ( the code values do not need to be sequential ) */
+enum
+{
+  AOSD_DECO_STYLE_RECT = 0,
+  AOSD_DECO_STYLE_ROUNDRECT = 1,
+  AOSD_DECO_STYLE_CONCAVERECT = 2
+};
+
+/* decoration style codes array size */
+#define AOSD_DECO_STYLE_CODES_ARRAY_SIZE 3
+
+/* decoration style codes array */
+gint aosd_deco_style_codes[] =
+{
+  AOSD_DECO_STYLE_RECT,
+  AOSD_DECO_STYLE_ROUNDRECT,
+  AOSD_DECO_STYLE_CONCAVERECT
+};
+
+/* prototypes of render functions */
+static void aosd_deco_rfunc_rect ( Ghosd * , cairo_t * , aosd_deco_style_data_t * );
+static void aosd_deco_rfunc_roundrect ( Ghosd * , cairo_t * , aosd_deco_style_data_t * );
+static void aosd_deco_rfunc_concaverect ( Ghosd * , cairo_t * , aosd_deco_style_data_t * );
+
+/* map decoration style codes to decoration objects */
+aosd_deco_style_t aosd_deco_styles[] =
+{
+  [AOSD_DECO_STYLE_RECT] = { N_("Rectangle") ,
+                             aosd_deco_rfunc_rect ,
+                             2 , { 10 , 10 , 10 , 10 } },
+
+  [AOSD_DECO_STYLE_ROUNDRECT] = { N_("Rounded Rectangle") ,
+                                  aosd_deco_rfunc_roundrect ,
+                                  2 , { 10 , 10 , 10 , 10 } },
+
+  [AOSD_DECO_STYLE_CONCAVERECT] = { N_("Concave Rectangle") ,
+                                    aosd_deco_rfunc_concaverect ,
+                                    2 , { 10 , 10 , 10 , 10 } }
+};
+
+
+
+/* DECORATION STYLE API */
+
+
+void
+aosd_deco_style_get_codes_array ( gint ** array , gint * array_size )
+{
+  *array = aosd_deco_style_codes;
+  *array_size = AOSD_DECO_STYLE_CODES_ARRAY_SIZE;
+  return;
+}
+
+
+void
+aosd_deco_style_get_padding ( gint deco_code ,
+                              gint * ptop , gint * pbottom ,
+                              gint * pleft , gint * pright )
+{
+  if ( ptop != NULL ) *ptop = aosd_deco_styles[deco_code].padding.top;
+  if ( pbottom != NULL ) *pbottom = aosd_deco_styles[deco_code].padding.bottom;
+  if ( pleft != NULL ) *pleft = aosd_deco_styles[deco_code].padding.left;
+  if ( pright != NULL ) *pright = aosd_deco_styles[deco_code].padding.right;
+  return;
+}
+
+
+const gchar *
+aosd_deco_style_get_desc ( gint deco_code )
+{
+  return aosd_deco_styles[deco_code].desc;
+}
+
+
+gint
+aosd_deco_style_get_numcol ( gint deco_code )
+{
+  return aosd_deco_styles[deco_code].colors_num;
+}
+
+
+void
+aosd_deco_style_render ( gint deco_code , gpointer ghosd , gpointer cr , gpointer user_data )
+{
+  aosd_deco_styles[deco_code].render_func( (Ghosd*)ghosd , (cairo_t*)cr , user_data );
+}
+
+
+gint
+aosd_deco_style_get_first_code ( void )
+{
+  return AOSD_DECO_STYLE_RECT;
+}
+
+
+gint
+aosd_deco_style_get_max_numcol ( void )
+{
+  gint i = 0;
+  gint max_numcol = 0;
+
+  for ( i = 0 ; i < AOSD_DECO_STYLE_CODES_ARRAY_SIZE ; i++ )
+  {
+    gint numcol = aosd_deco_style_get_numcol( aosd_deco_style_codes[i] );
+    if ( numcol > max_numcol )
+      max_numcol = numcol;
+  }
+
+  return max_numcol;
+}
+
+
+
+/* RENDER FUNCTIONS */
+
+static void
+aosd_deco_rfunc_rect( Ghosd * osd , cairo_t * cr , aosd_deco_style_data_t * data )
+{
+  /* decoration information
+     ----------------------
+     draws a simple rectangular decoration; uses 2 colors
+     (user color 1 and 2) and 1 font (user font 1), with optional shadow
+  */
+  PangoLayout *osd_layout = data->layout;
+  aosd_color_t color0 = g_array_index( data->decoration->colors , aosd_color_t , 0 );
+  aosd_color_t color1 = g_array_index( data->decoration->colors , aosd_color_t , 1 );
+  aosd_color_t textcolor0 = data->text->fonts_color[0];
+  aosd_color_t shadowcolor0 = data->text->fonts_shadow_color[0];
+  gboolean draw_shadow = data->text->fonts_draw_shadow[0];
+  gint width = 0, height = 0;
+
+  pango_layout_get_pixel_size( osd_layout , &width , &height );
+
+  /* draw rectangle container */
+  cairo_set_source_rgba( cr , (gdouble)color0.red / 65535 , (gdouble)color0.green / 65535 ,
+    (gdouble)color0.blue / 65535 , (gdouble)color0.alpha / 65535 );
+  cairo_rectangle( cr , 0 , 0 ,
+    aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.left + width +
+    aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.right,
+    aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.top + height +
+    aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.bottom );
+  cairo_fill_preserve( cr );
+  cairo_set_source_rgba( cr , (gdouble)color1.red / 65535 , (gdouble)color1.green / 65535 ,
+    (gdouble)color1.blue / 65535 , (gdouble)color1.alpha / 65535 );
+  cairo_stroke( cr );
+
+  if ( draw_shadow == TRUE )
+  {
+    /* draw text shadow */
+    cairo_set_source_rgba( cr , (gdouble)shadowcolor0.red / 65535 , (gdouble)shadowcolor0.green / 65535 ,
+      (gdouble)shadowcolor0.blue / 65535 , (gdouble)shadowcolor0.alpha / 65535 );
+    cairo_move_to( cr,
+      aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.left + 2 ,
+      aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.top + 2 );
+    pango_cairo_show_layout( cr , osd_layout );
+  }
+
+  /* draw text */
+  cairo_set_source_rgba( cr , (gdouble)textcolor0.red / 65535 , (gdouble)textcolor0.green / 65535 ,
+    (gdouble)textcolor0.blue / 65535 , (gdouble)textcolor0.alpha / 65535 );
+  cairo_move_to( cr,
+    aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.left ,
+    aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.top );
+  pango_cairo_show_layout( cr , osd_layout );
+}
+
+
+static void
+aosd_deco_rfunc_roundrect ( Ghosd * osd , cairo_t * cr , aosd_deco_style_data_t * data )
+{
+  /* decoration information
+     ----------------------
+     draws a rectangular decoration with rounded angles; uses 2 colors
+     (user color 1 and 2) and 1 font (user font 1), with optional shadow
+  */
+  PangoLayout *osd_layout = data->layout;
+  aosd_color_t color0 = g_array_index( data->decoration->colors , aosd_color_t , 0 );
+  aosd_color_t color1 = g_array_index( data->decoration->colors , aosd_color_t , 1 );
+  aosd_color_t textcolor0 = data->text->fonts_color[0];
+  aosd_color_t shadowcolor0 = data->text->fonts_shadow_color[0];
+  gboolean draw_shadow = data->text->fonts_draw_shadow[0];
+  gint width = 0, height = 0;
+
+  pango_layout_get_pixel_size( osd_layout , &width , &height );
+
+  /* draw rounded-rectangle container */
+  cairo_set_source_rgba( cr , (gdouble)color0.red / 65535 , (gdouble)color0.green / 65535 ,
+    (gdouble)color0.blue / 65535 , (gdouble)color0.alpha / 65535 );
+  cairo_move_to( cr , aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.left , 0 );
+  cairo_arc( cr , width + aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.left ,
+    aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.top ,
+    10. , -G_PI_2 , 0. );
+  cairo_arc( cr , width + aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.left ,
+    aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.top + height ,
+    10. , -4. * G_PI_2 , -3. * G_PI_2 );
+  cairo_arc( cr , aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.left ,
+    aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.top + height ,
+    10. , -3. * G_PI_2 , -2. * G_PI_2 );
+  cairo_arc( cr , aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.left ,
+    aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.top ,
+    10. , -2. * G_PI_2 , -G_PI_2 );
+  cairo_close_path( cr );
+  cairo_fill_preserve( cr );
+  cairo_set_source_rgba( cr , (gdouble)color1.red / 65535 , (gdouble)color1.green / 65535 ,
+    (gdouble)color1.blue / 65535 , (gdouble)color1.alpha / 65535 );
+  cairo_stroke( cr );
+
+  if ( draw_shadow == TRUE )
+  {
+    /* draw text shadow */
+    cairo_set_source_rgba( cr , (gdouble)shadowcolor0.red / 65535 , (gdouble)shadowcolor0.green / 65535 ,
+      (gdouble)shadowcolor0.blue / 65535 , (gdouble)shadowcolor0.alpha / 65535 );
+    cairo_move_to( cr ,
+      aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.left + 2 ,
+      aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.top + 2 );
+    pango_cairo_show_layout( cr , osd_layout );
+  }
+
+  /* draw text */
+  cairo_set_source_rgba( cr , (gdouble)textcolor0.red / 65535 , (gdouble)textcolor0.green / 65535 ,
+    (gdouble)textcolor0.blue / 65535 , (gdouble)textcolor0.alpha / 65535 );
+  cairo_move_to( cr ,
+    aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.left ,
+    aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.top );
+  pango_cairo_show_layout( cr , osd_layout );
+}
+
+
+static void
+aosd_deco_rfunc_concaverect ( Ghosd * osd , cairo_t * cr , aosd_deco_style_data_t * data )
+{
+  /* decoration information
+     ----------------------
+     draws a rectangle with concave angles; uses 2 colors
+     (user color 1 and 2) and 1 font (user font 1), with optional shadow
+  */
+  PangoLayout *osd_layout = data->layout;
+  aosd_color_t color0 = g_array_index( data->decoration->colors , aosd_color_t , 0 );
+  aosd_color_t color1 = g_array_index( data->decoration->colors , aosd_color_t , 1 );
+  aosd_color_t textcolor0 = data->text->fonts_color[0];
+  aosd_color_t shadowcolor0 = data->text->fonts_shadow_color[0];
+  gboolean draw_shadow = data->text->fonts_draw_shadow[0];
+  gint width = 0, height = 0;
+
+  pango_layout_get_pixel_size( osd_layout , &width , &height );
+
+  /* draw jigsaw-piece-like container */
+  cairo_set_source_rgba( cr , (gdouble)color0.red / 65535 , (gdouble)color0.green / 65535 ,
+    (gdouble)color0.blue / 65535 , (gdouble)color0.alpha / 65535 );
+  cairo_move_to( cr , aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.left , 0 );
+  cairo_arc_negative( cr , width + aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.left + 2 ,
+    aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.top - 2 ,
+    8. , -G_PI_2 , 0. );
+  cairo_arc_negative( cr , width + aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.left + 2 ,
+    aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.top + height + 2 ,
+    8. , -4. * G_PI_2 , -3. * G_PI_2 );
+  cairo_arc_negative( cr , aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.left - 2 ,
+    aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.top + height + 2 ,
+    8. , -3. * G_PI_2 , -2. * G_PI_2 );
+  cairo_arc_negative( cr , aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.left - 2 ,
+    aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.top - 2 ,
+    8. , -2. * G_PI_2 , -G_PI_2 );
+  cairo_close_path( cr );
+  cairo_fill_preserve( cr );
+  cairo_set_source_rgba( cr , (gdouble)color1.red / 65535 , (gdouble)color1.green / 65535 ,
+    (gdouble)color1.blue / 65535 , (gdouble)color1.alpha / 65535 );
+  cairo_stroke( cr );
+
+  if ( draw_shadow == TRUE )
+  {
+    /* draw text shadow */
+    cairo_set_source_rgba( cr , (gdouble)shadowcolor0.red / 65535 , (gdouble)shadowcolor0.green / 65535 ,
+      (gdouble)shadowcolor0.blue / 65535 , (gdouble)shadowcolor0.alpha / 65535 );
+    cairo_move_to( cr ,
+      aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.left + 2 ,
+      aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.top + 2 );
+    pango_cairo_show_layout( cr , osd_layout );
+  }
+
+  /* draw text */
+  cairo_set_source_rgba( cr , (gdouble)textcolor0.red / 65535 , (gdouble)textcolor0.green / 65535 ,
+    (gdouble)textcolor0.blue / 65535 , (gdouble)textcolor0.alpha / 65535 );
+  cairo_move_to( cr ,
+    aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.left ,
+    aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.top );
+  pango_cairo_show_layout( cr , osd_layout );
+}