aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2012-10-02 20:33:35 +0200
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2012-10-02 20:33:35 +0200
commitb224aef050b4f75b6325cb3b46b70e31d9116fa2 (patch)
treed920da5679925bc3124112e45f7307bde4e38729
parentf025c0def98fd72f7e3180a208d896414c451e63 (diff)
downloadosc-graphics-b224aef050b4f75b6325cb3b46b70e31d9116fa2.tar.gz
added text layers based on SDL_ttf
-rw-r--r--configure.ac7
-rw-r--r--src/Makefile.am1
-rw-r--r--src/layer_box.h2
-rw-r--r--src/layer_image.cpp47
-rw-r--r--src/layer_text.cpp173
-rw-r--r--src/layer_text.h101
-rw-r--r--src/main.cpp48
-rw-r--r--src/osc_graphics.h3
-rw-r--r--src/osc_server.h2
9 files changed, 336 insertions, 48 deletions
diff --git a/configure.ac b/configure.ac
index 5b728e0..3597213 100644
--- a/configure.ac
+++ b/configure.ac
@@ -71,6 +71,13 @@ PKG_CHECK_MODULES(SDL_GFX, [SDL_gfx], [
])
])
+AC_CHECK_LIB(SDL_ttf, TTF_Init, , [
+ AC_MSG_ERROR([Required libSDL_ttf missing!])
+])
+AC_CHECK_HEADERS([SDL_ttf.h], , [
+ AC_MSG_ERROR([Required libSDL_ttf header missing!])
+])
+
PKG_CHECK_MODULES(LIBVLC, [libvlc >= 1.1.10], [
CFLAGS="$CFLAGS $LIBVLC_CFLAGS"
CPPFLAGS="$CPPFLAGS $LIBVLC_CFLAGS"
diff --git a/src/Makefile.am b/src/Makefile.am
index bee1c2d..5c1a23c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -13,5 +13,6 @@ osc_graphics_SOURCES = main.cpp osc_graphics.h \
osc_server.cpp osc_server.h \
layer.cpp layer.h \
layer_box.cpp layer_box.h \
+ layer_text.cpp layer_text.h \
layer_image.cpp layer_image.h \
layer_video.cpp layer_video.h
diff --git a/src/layer_box.h b/src/layer_box.h
index 1e4e5e3..157bb29 100644
--- a/src/layer_box.h
+++ b/src/layer_box.h
@@ -7,8 +7,6 @@
#include "osc_server.h"
#include "layer.h"
-#define COLOR_TYPES "iii" /* r, g, b */
-
class LayerBox : public Layer {
Sint16 x1, y1, x2, y2;
Uint8 r, g, b, a;
diff --git a/src/layer_image.cpp b/src/layer_image.cpp
index 89eb795..7f338b2 100644
--- a/src/layer_image.cpp
+++ b/src/layer_image.cpp
@@ -8,50 +8,11 @@
#include <SDL_image.h>
#include <SDL_rotozoom.h>
-/* HACK: older SDL_gfx versions define GFX_ALPHA_ADJUST in the header */
-#define GFX_ALPHA_ADJUST \
- static __attribute__((unused)) GFX_ALPHA_ADJUST
-#include <SDL_gfxBlitFunc.h>
-#undef GFX_ALPHA_ADJUST
-
#include "osc_graphics.h"
#include "layer_image.h"
Layer::CtorInfo LayerImage::ctor_info = {"image", "s" /* file */};
-static inline void
-rgba_blit_with_alpha(SDL_Surface *src_surf, SDL_Surface *dst_surf, Uint8 alpha)
-{
- Uint8 *src = (Uint8 *)src_surf->pixels;
- Uint8 *dst = (Uint8 *)dst_surf->pixels;
- SDL_PixelFormat *fmt = src_surf->format;
-
- int inc = fmt->BytesPerPixel;
- int len = src_surf->w * src_surf->h;
-
- SDL_MAYBE_LOCK(src_surf);
- SDL_MAYBE_LOCK(dst_surf);
-
- GFX_DUFFS_LOOP4({
- register Uint32 pixel;
- register int a;
-
- pixel = *(Uint32 *)src;
- a = ((pixel & fmt->Amask) >> fmt->Ashift) << fmt->Aloss;
- a = (a*alpha)/SDL_ALPHA_OPAQUE;
- a = (a << fmt->Aloss) << fmt->Ashift;
- pixel &= ~fmt->Amask;
- pixel |= a;
- *(Uint32 *)dst = pixel;
-
- src += inc;
- dst += inc;
- }, len)
-
- SDL_MAYBE_UNLOCK(dst_surf);
- SDL_MAYBE_UNLOCK(src_surf);
-}
-
LayerImage::LayerImage(const char *name, SDL_Rect geo, float opacity,
const char *file) :
Layer(name),
@@ -128,13 +89,7 @@ LayerImage::alpha(float opacity)
use_surf->format->Amask);
}
- if (alpha == SDL_ALPHA_TRANSPARENT) {
- SDL_FillRect(surf_alpha, NULL,
- SDL_MapRGBA(surf_alpha->format,
- 0, 0, 0, SDL_ALPHA_TRANSPARENT));
- } else {
- rgba_blit_with_alpha(use_surf, surf_alpha, alpha);
- }
+ rgba_blit_with_alpha(use_surf, surf_alpha, alpha);
}
void
diff --git a/src/layer_text.cpp b/src/layer_text.cpp
new file mode 100644
index 0000000..32b4963
--- /dev/null
+++ b/src/layer_text.cpp
@@ -0,0 +1,173 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <math.h>
+
+#include <SDL.h>
+#include <SDL_ttf.h>
+#include <SDL_rotozoom.h>
+
+#include "osc_graphics.h"
+#include "layer_text.h"
+
+Layer::CtorInfo LayerText::ctor_info = {
+ "text",
+ COLOR_TYPES "ss" /* r, g, b, text, font file */
+};
+
+#define TTF_CLOSEFONT_SAFE(FONT) do { \
+ if (FONT) { \
+ TTF_CloseFont(FONT); \
+ FONT = NULL; \
+ } \
+} while (0)
+
+LayerText::LayerText(const char *name, SDL_Rect geo, float opacity,
+ SDL_Color color, const char *text, const char *file)
+ : Layer(name), ttf_font(NULL), surf_alpha(NULL), surf(NULL),
+ textv(NULL), filev(NULL)
+{
+ color_osc_id = register_method("color", COLOR_TYPES,
+ (OSCServer::MethodHandlerCb)color_osc);
+ text_osc_id = register_method("test", "s",
+ (OSCServer::MethodHandlerCb)text_osc);
+ font_osc_id = register_method("font", "s",
+ (OSCServer::MethodHandlerCb)font_osc);
+ style_osc_id = register_method("style", "s",
+ (OSCServer::MethodHandlerCb)style_osc);
+
+ if (TTF_Init()) {
+ SDL_ERROR("TTF_Init");
+ exit(EXIT_FAILURE);
+ }
+
+ LayerText::geo(geo);
+ LayerText::alpha(opacity);
+ LayerText::color(color);
+ LayerText::text(text);
+ LayerText::font(file);
+}
+
+void
+LayerText::geo(SDL_Rect geo)
+{
+ int style = TTF_STYLE_NORMAL;
+
+ geov = geo;
+ if (!geov.h)
+ geov.h = screen->h;
+
+ if (!filev)
+ return;
+
+ if (surf && (!geov.w || geov.w == surf->w) && geov.h == surf->h)
+ return;
+
+ if (ttf_font) {
+ style = TTF_GetFontStyle(ttf_font);
+ TTF_CloseFont(ttf_font);
+ }
+ ttf_font = TTF_OpenFont(filev, geov.h);
+
+ LayerText::style(style);
+}
+
+void
+LayerText::alpha(float opacity)
+{
+ Uint8 alpha = (Uint8)ceilf(opacity*SDL_ALPHA_OPAQUE);
+
+ alphav = opacity;
+
+ if (!surf)
+ return;
+
+ if (alpha == SDL_ALPHA_OPAQUE) {
+ SDL_FREESURFACE_SAFE(surf_alpha);
+ return;
+ }
+
+ if (!surf_alpha) {
+ surf_alpha = SDL_CreateRGBSurface(surf->flags,
+ surf->w, surf->h,
+ surf->format->BitsPerPixel,
+ surf->format->Rmask,
+ surf->format->Gmask,
+ surf->format->Bmask,
+ surf->format->Amask);
+ }
+
+ rgba_blit_with_alpha(surf, surf_alpha, alpha);
+}
+
+void
+LayerText::color(SDL_Color color)
+{
+ colorv = color;
+
+ if (!ttf_font)
+ return;
+
+ SDL_FREESURFACE_SAFE(surf_alpha);
+ SDL_FREESURFACE_SAFE(surf);
+
+ surf = TTF_RenderText_Blended(ttf_font, textv, colorv);
+
+ if (geov.w && surf->w != geov.w) {
+ SDL_Surface *new_surf;
+
+ new_surf = zoomSurface(surf, (double)geov.w/surf->w, 1.0,
+ SMOOTHING_ON);
+ SDL_FreeSurface(surf);
+ surf = new_surf;
+ }
+
+ alpha(alphav);
+}
+
+void
+LayerText::style_osc(LayerText *obj, lo_arg **argv)
+{
+ int style = TTF_STYLE_NORMAL;
+
+ for (char *p = &argv[0]->s; *p; p++) {
+ switch (*p) {
+ case 'b':
+ style |= TTF_STYLE_BOLD;
+ break;
+ case 'i':
+ style |= TTF_STYLE_ITALIC;
+ break;
+ case 'u':
+ style |= TTF_STYLE_UNDERLINE;
+ break;
+ default:
+ break;
+ }
+ }
+
+ obj->style(style);
+}
+
+void
+LayerText::frame(SDL_Surface *target)
+{
+ SDL_Surface *use_surf = surf_alpha ? : surf;
+ SDL_Rect dst_rect = {geov.x, geov.y, use_surf->w, use_surf->h};
+
+ SDL_BlitSurface(use_surf, NULL, target, &dst_rect);
+}
+
+LayerText::~LayerText()
+{
+ unregister_method(style_osc_id);
+ unregister_method(font_osc_id);
+ unregister_method(text_osc_id);
+ unregister_method(color_osc_id);
+
+ SDL_FREESURFACE_SAFE(surf);
+ SDL_FREESURFACE_SAFE(surf_alpha);
+
+ TTF_CLOSEFONT_SAFE(ttf_font);
+}
diff --git a/src/layer_text.h b/src/layer_text.h
new file mode 100644
index 0000000..745f54f
--- /dev/null
+++ b/src/layer_text.h
@@ -0,0 +1,101 @@
+#ifndef __LAYER_TEXT_H
+#define __LAYER_TEXT_H
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <SDL.h>
+#include <SDL_ttf.h>
+
+#include "osc_graphics.h"
+#include "osc_server.h"
+#include "layer.h"
+
+class LayerText : public Layer {
+ TTF_Font *ttf_font;
+
+ SDL_Surface *surf_alpha; /* with per-surface alpha */
+ SDL_Surface *surf; /* original text (possibly scaled) */
+
+ char *textv;
+ char *filev;
+ SDL_Color colorv;
+ SDL_Rect geov;
+ float alphav;
+
+public:
+ LayerText(const char *name, SDL_Rect geo, float opacity,
+ SDL_Color color, const char *text, const char *file);
+
+ static CtorInfo ctor_info;
+ static Layer *
+ ctor_osc(const char *name, SDL_Rect geo, float opacity, lo_arg **argv)
+ {
+ SDL_Color color = {
+ (Uint8)argv[0]->i, (Uint8)argv[1]->i, (Uint8)argv[2]->i
+ };
+ return new LayerText(name, geo, opacity, color,
+ &argv[3]->s, &argv[4]->s);
+ }
+
+ ~LayerText();
+
+ void frame(SDL_Surface *target);
+
+private:
+ void geo(SDL_Rect geo);
+ void alpha(float opacity);
+
+ void color(SDL_Color color);
+ OSCServer::MethodHandlerId *color_osc_id;
+ static void
+ color_osc(LayerText *obj, lo_arg **argv)
+ {
+ SDL_Color color = {
+ (Uint8)argv[0]->i, (Uint8)argv[1]->i, (Uint8)argv[2]->i
+ };
+ obj->color(color);
+ }
+
+ inline void
+ text(const char *text)
+ {
+ free(textv);
+ textv = strdup(text);
+
+ color(colorv);
+ }
+ OSCServer::MethodHandlerId *text_osc_id;
+ static void
+ text_osc(LayerText *obj, lo_arg **argv)
+ {
+ obj->text(&argv[0]->s);
+ }
+
+ inline void
+ font(const char *file)
+ {
+ free(filev);
+ filev = strdup(file);
+
+ geo(geov);
+ }
+ OSCServer::MethodHandlerId *font_osc_id;
+ static void
+ font_osc(LayerText *obj, lo_arg **argv)
+ {
+ obj->font(&argv[0]->s);
+ }
+
+ inline void
+ style(int style)
+ {
+ TTF_SetFontStyle(ttf_font, style);
+
+ color(colorv);
+ }
+ OSCServer::MethodHandlerId *style_osc_id;
+ static void style_osc(LayerText *obj, lo_arg **argv);
+};
+
+#endif \ No newline at end of file
diff --git a/src/main.cpp b/src/main.cpp
index f055db5..f9c3eb8 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -9,11 +9,18 @@
#include <SDL.h>
#include <SDL_framerate.h>
+/* HACK: older SDL_gfx versions define GFX_ALPHA_ADJUST in the header */
+#define GFX_ALPHA_ADJUST \
+ static __attribute__((unused)) GFX_ALPHA_ADJUST
+#include <SDL_gfxBlitFunc.h>
+#undef GFX_ALPHA_ADJUST
+
#include "osc_graphics.h"
#include "osc_server.h"
#include "layer.h"
#include "layer_box.h"
+#include "layer_text.h"
#include "layer_image.h"
#include "layer_video.h"
@@ -48,6 +55,46 @@ LayerList layers;
int config_dump_osc = 0;
+void
+rgba_blit_with_alpha(SDL_Surface *src_surf, SDL_Surface *dst_surf, Uint8 alpha)
+{
+ if (alpha == SDL_ALPHA_TRANSPARENT) {
+ SDL_FillRect(dst_surf, NULL,
+ SDL_MapRGBA(dst_surf->format,
+ 0, 0, 0, SDL_ALPHA_TRANSPARENT));
+ return;
+ }
+
+ Uint8 *src = (Uint8 *)src_surf->pixels;
+ Uint8 *dst = (Uint8 *)dst_surf->pixels;
+ SDL_PixelFormat *fmt = src_surf->format;
+
+ int inc = fmt->BytesPerPixel;
+ int len = src_surf->w * src_surf->h;
+
+ SDL_MAYBE_LOCK(src_surf);
+ SDL_MAYBE_LOCK(dst_surf);
+
+ GFX_DUFFS_LOOP4({
+ register Uint32 pixel;
+ register int a;
+
+ pixel = *(Uint32 *)src;
+ a = ((pixel & fmt->Amask) >> fmt->Ashift) << fmt->Aloss;
+ a = (a*alpha)/SDL_ALPHA_OPAQUE;
+ a = (a << fmt->Aloss) << fmt->Ashift;
+ pixel &= ~fmt->Amask;
+ pixel |= a;
+ *(Uint32 *)dst = pixel;
+
+ src += inc;
+ dst += inc;
+ }, len)
+
+ SDL_MAYBE_UNLOCK(dst_surf);
+ SDL_MAYBE_UNLOCK(src_surf);
+}
+
static inline void
sdl_process_events(void)
{
@@ -223,6 +270,7 @@ main(int argc, char **argv)
REGISTER_LAYER(LayerImage);
REGISTER_LAYER(LayerVideo);
REGISTER_LAYER(LayerBox);
+ REGISTER_LAYER(LayerText);
osc_server.start();
diff --git a/src/osc_graphics.h b/src/osc_graphics.h
index 2a08678..c36ef54 100644
--- a/src/osc_graphics.h
+++ b/src/osc_graphics.h
@@ -43,4 +43,7 @@ extern SDL_Surface *screen;
extern int config_dump_osc;
+void rgba_blit_with_alpha(SDL_Surface *src_surf, SDL_Surface *dst_surf,
+ Uint8 alpha = SDL_ALPHA_TRANSPARENT);
+
#endif
diff --git a/src/osc_server.h b/src/osc_server.h
index f6d0c51..0687d1c 100644
--- a/src/osc_server.h
+++ b/src/osc_server.h
@@ -102,4 +102,6 @@ public:
#define GEO_TYPES "iiii" /* x, y, width, height */
#define NEW_LAYER_TYPES "is" GEO_TYPES "f" /* position, name, GEO, alpha */
+#define COLOR_TYPES "iii" /* r, g, b */
+
#endif