CPP_SRCS = $(shell find src -name \*.cpp)
CPP_DEPS = $(shell find src -name \*.h)
-LIBS = cairo freetype2 jsoncpp libavformat libavcodec libavutil libswresample libswscale libuv libwebsockets
+LIBS = cairo freetype2 jsoncpp libavformat libavcodec libavutil libswresample libswscale libuv libwebsockets pangocairo
main: $(CPP_SRCS) $(CPP_DEPS)
clang++ -g $(shell pkg-config --cflags --libs $(LIBS)) $(CPP_SRCS) -o $@
#include "cairo.h"
}
-#include "../freetype/Face.h"
-#include "../freetype/Library.h"
#include "../cairo/Context.h"
-#include "../cairo/Face.h"
#include "../cairo/Surface.h"
+#include "../pango/Layout.h"
namespace app {
public:
Renderer(uint8_t *plane, int linesize, int width, int height)
- : ft()
- , face(ft.NewFace("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 0))
- , font(face)
+ : font("DejaVu Sans 32px")
, surface(plane, linesize, CAIRO_FORMAT_ARGB32, width, height)
, ctx(surface.CreateContext())
, width(width)
, height(height)
- , text("Hello") {
+ , text()
+ , text_layout(ctx.CreateLayout()) {
+ text_layout.SetFont(font);
+ text_layout.SetWidth(width / 2);
+ SetText("Hello, I am a long text that should wrap eventually when it gets long enough to cross the halfway point of the total width available (not including the offset which is added afterwards).");
}
~Renderer() {
}
ctx.Paint();
ctx.MoveTo(50, 50);
- ctx.SetFontFace(font);
- ctx.SetFontSize(16);
ctx.SetSourceRGB(1, 1, 1);
- ctx.ShowText(text.c_str());
+ text_layout.Render();
surface.Flush();
}
void SetText(const std::string &t) {
text = t;
+ text_layout.SetText(text);
+ text_layout.Update();
}
private:
- freetype::Library ft;
- freetype::Face face;
- cairo::Face font;
+ pango::Font font;
cairo::Surface surface;
cairo::Context ctx;
int height;
std::string text;
+ pango::Layout text_layout;
};
#include "Error.h"
#include "Face.h"
+#include "../pango/Layout.h"
namespace cairo {
Context &operator =(const Context &) = delete;
public:
+ pango::Layout CreateLayout() {
+ return pango::Layout(ctx);
+ }
+
void DebugPrint() {
cairo_status_t status = cairo_status(ctx);
std::cout << "cairo status: " << cairo_status_to_string(status) << std::endl;
Json::Value data;
Json::Reader json_reader;
json_reader.parse(data_string, data);
+ const std::string text = data["model"]["text"].asString();
app::Renderer *renderer = static_cast<app::Renderer *>(user);
- renderer->SetText(data["model"]["text"].asString());
+ if (text.length() > 0) {
+ renderer->SetText(text);
+ }
}
}
const int WIDTH = 1280;
const int HEIGHT = 720;
const int FPS = 60;
+ //const char *URL = "rtmp://localhost/horstiebot";
const char *URL = "rtmp://localhost/localhorsttv";
uv::Loop loop;
--- /dev/null
+#ifndef TEST_PANGO_FONT_H_
+#define TEST_PANGO_FONT_H_
+
+#include <pango/pango.h>
+#include <stdexcept>
+
+namespace pango {
+
+class Font {
+
+public:
+ explicit Font(const char *name): fd(pango_font_description_from_string(name)) {
+ if (!fd) {
+ throw std::runtime_error("failed to create font description");
+ }
+ }
+ ~Font() {
+ pango_font_description_free(fd);
+ }
+
+ Font(const Font &) = delete;
+ Font &operator =(const Font &) = delete;
+
+public:
+ void Apply(PangoLayout *l) const {
+ pango_layout_set_font_description(l, fd);
+ }
+
+ void SetSize(int size) {
+ pango_font_description_set_size(fd, size);
+ }
+
+private:
+ PangoFontDescription *fd;
+
+};
+
+}
+
+#endif
--- /dev/null
+#ifndef TEST_PANGO_LAYOUT_H_
+#define TEST_PANGO_LAYOUT_H_
+
+#include <cairo.h>
+#include <glib-object.h>
+#include <pango/pangocairo.h>
+#include <stdexcept>
+#include <string>
+#include <utility>
+
+#include "Font.h"
+
+namespace pango {
+
+class Layout {
+
+public:
+ explicit Layout(cairo_t *c): c(c), l(pango_cairo_create_layout(c)) {
+ if (!l) {
+ throw std::runtime_error("failed to create layout");
+ }
+ cairo_reference(c);
+ }
+ ~Layout() {
+ cairo_destroy(c);
+ g_object_unref(l);
+ }
+ Layout(const Layout &other): c(other.c), l(other.l) {
+ cairo_reference(c);
+ g_object_ref(l);
+ }
+ Layout &operator =(const Layout &other) {
+ Layout temp(other);
+ Swap(temp);
+ return *this;
+ }
+ void Swap(Layout &other) {
+ std::swap(c, other.c);
+ std::swap(l, other.l);
+ }
+
+public:
+ void Render() {
+ pango_cairo_show_layout(c, l);
+ }
+
+ void SetFont(const Font &font) {
+ font.Apply(l);
+ }
+
+ void SetText(const std::string &text) {
+ pango_layout_set_text(l, text.c_str(), text.length());
+ }
+
+ void SetWidth(int w) {
+ pango_layout_set_width(l, w * 1024);
+ }
+
+ void Update() {
+ pango_cairo_update_layout(c, l);
+ }
+
+private:
+ cairo_t *c;
+ PangoLayout *l;
+
+};
+
+}
+
+namespace std {
+
+template<>
+inline void swap<pango::Layout>(pango::Layout &a, pango::Layout &b) {
+ a.Swap(b);
+}
+
+}
+
+#endif