Browse Source

write text

isundil 7 years ago
parent
commit
734fd70d0a
9 changed files with 328 additions and 117 deletions
  1. 3 0
      .gitmodules
  2. 22 9
      Makefile
  3. 0 0
      conf/instaserv.example.conf
  4. BIN
      conf/monoid.ttf
  5. 1 0
      dependencies/pngwriter
  6. 2 0
      include/instaserv.h
  7. 0 97
      is_create.cpp
  8. 292 0
      src/commands/is_create.cpp
  9. 8 11
      src/instaserv.cpp

+ 3 - 0
.gitmodules

@@ -0,0 +1,3 @@
+[submodule "dependencies/pngwriter"]
+	path = dependencies/pngwriter
+	url = https://github.com/pngwriter/pngwriter.git

+ 22 - 9
Makefile

@@ -5,21 +5,34 @@ ANOPE_INSTALL=../anope/testinstall/
 
 CP=	cp
 
-all:	instaserv.so is_create.so
+CXX=	g++
 
-instaserv.so:
-	g++ -fPIC -shared -o instaserv.so instaserv.cpp -I ${ANOPE_SRC}/include -I ${ANOPE_SRC}/build/include
+CXXFLAGS=	-g3 \
+			-I${ANOPE_SRC}/include -I${ANOPE_SRC}/build/include \
+			-I dependencies/pngwriter/ \
+			-I /usr/include/freetype2/ \
+			-I include/
+
+all:	build/instaserv.so build/is_create.so
+
+build/instaserv.so: src/instaserv.cpp include/instaserv.h
+	mkdir -p build
+	$(CXX) -fPIC -shared -o build/instaserv.so src/instaserv.cpp $(CXXFLAGS)
 	
-is_create.so:
-	g++ -fPIC -shared -o is_create.so is_create.cpp -I ${ANOPE_SRC}/include -I ${ANOPE_SRC}/build/include
+build/is_create.so: src/commands/is_create.cpp include/instaserv.h dependencies/pngwriter/pngwriter.cc
+	mkdir -p build
+	$(CXX) -fPIC -shared -o build/is_create.so \
+		src/commands/is_create.cpp dependencies/pngwriter/pngwriter.cc \
+		-lpng -lfreetype -lz \
+		$(CXXFLAGS)
 
 clean:
-	$(RM) instaserv.so is_create.so
+	$(RM) build/instaserv.so build/is_create.so
 
 install: all
-	$(CP) instaserv.so ${ANOPE_INSTALL}/lib/
-	$(CP) is_create.so ${ANOPE_INSTALL}/lib/
-	$(CP) instaserv.example.conf ${ANOPE_INSTALL}/conf/instaserv.example.conf
+	$(CP) build/instaserv.so ${ANOPE_INSTALL}/lib/modules/
+	$(CP) build/is_create.so ${ANOPE_INSTALL}/lib/modules/
+	$(CP) conf/instaserv.example.conf ${ANOPE_INSTALL}/conf/instaserv.example.conf
 
 re:	clean all
 

+ 0 - 0
instaserv.example.conf → conf/instaserv.example.conf


BIN
conf/monoid.ttf


+ 1 - 0
dependencies/pngwriter

@@ -0,0 +1 @@
+Subproject commit 79bb3ef5ebd91996bc4cd02cdc031c5cd560b897

+ 2 - 0
instaserv.h → include/instaserv.h

@@ -2,6 +2,8 @@
 #ifndef INSTASERV_H_
 #define INSTASERV_H_
 
+#include <module.h>
+
 class InstaServCore;
 
 class InstaMessageBuffer

+ 0 - 97
is_create.cpp

@@ -1,97 +0,0 @@
-
-#include "module.h"
-#include "instaserv.h"
-
-static ServiceReference<InstaServCore> instaServ("InstaServService", "InstaServ");
-
-class ISCreate;
-
-class InstaMessageBufferImpl: public InstaMessageBuffer, public Timer
-{
-	std::vector<Anope::string> lines;
-	User *u;
-	ISCreate *module;
-
-public:
-	InstaMessageBufferImpl(ISCreate *m, User *user);
-
-	void Tick(time_t t) anope_override;
-	void Add(Anope::string &msg) anope_override;
-	size_t LineCount() const anope_override;
-	void OnEndBuffer() anope_override;
-};
-
-class CommandISCreate : public Command
-{
-	ISCreate *creator;
-public:
-	CommandISCreate(ISCreate *c, const Anope::string &sname = "instaserv/create") : Command((Module*) c, sname, 0, 0), creator(c)
-	{
-		this->SetDesc(_("Create a new quote"));
-		this->SetSyntax("");
-	}
-
-	void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
-	{
-		if (!source.GetUser())
-			return;
-		source.Reply("Type in your quote, end with a line only containing `EOF'");
-		instaServ->SetBuffer(source.GetUser(), new InstaMessageBufferImpl(creator, source.GetUser()));
-	}
-
-	bool OnHelp(CommandSource &source, const Anope::string &) anope_override
-	{
-		this->SendSyntax(source);
-		source.Reply(_(" \n"
-			"Create a new quote image"));
-		return true;
-	}
-};
-
-class ISCreate : public Module
-{
-	CommandISCreate commandiscreate;
-
- public:
-	ISCreate(const Anope::string &modname, const Anope::string &creator);
-	size_t GetMaxLines()
-	{
-		return 5;
-	}
-};
-
-ISCreate::ISCreate(const Anope::string &modname, const Anope::string &creator): Module(modname, creator, VENDOR), commandiscreate(this)
-{}
-
-InstaMessageBufferImpl::InstaMessageBufferImpl(ISCreate *m, User *user) :Timer(*instaServ, Config->GetModule("instaserv")->Get<time_t>("typingtimeout", "1m")), u(user), module(m)
-{}
-
-void InstaMessageBufferImpl::Tick(time_t t)
-{
-	(*instaServ)->OnExpire(u);
-}
-
-void InstaMessageBufferImpl::Add(Anope::string &msg)
-{
-	if (LineCount() < module->GetMaxLines())
-		lines.push_back(msg);
-	else
-	{
-		std::stringstream ss;
-		ss << "Cannot paste more than " << module->GetMaxLines() << " lines";
-		u->SendMessage((*instaServ)->GetBotInfo(), ss.str());
-	}
-}
-
-size_t InstaMessageBufferImpl::LineCount() const
-{
-	return lines.size();
-}
-
-void InstaMessageBufferImpl::OnEndBuffer()
-{
-	Log(LOG_DEBUG) << "::: received END";
-	(*instaServ)->OnExpire(u);
-}
-
-MODULE_INIT(ISCreate)

+ 292 - 0
src/commands/is_create.cpp

@@ -0,0 +1,292 @@
+
+#include <pngwriter.h>
+#include "instaserv.h"
+
+static ServiceReference<InstaServCore> instaServ("InstaServService", "InstaServ");
+
+class ISCreate;
+
+struct RGB
+{
+    RGB();
+    RGB(long value);
+
+    int r, g, b;
+};
+
+struct ARGB: public RGB
+{
+    ARGB();
+    ARGB(long value);
+
+    double a;
+};
+
+RGB::RGB()
+{
+    r = g = b = 0;
+}
+
+RGB::RGB(long value)
+{
+	const double factor = 65535.d / 255.d;
+    r = ((unsigned char)(value >> 16)) * factor;
+    g = ((unsigned char) (value >> 8)) * factor;
+    b = ((unsigned char) value) * factor;
+}
+
+ARGB::ARGB()
+{
+    a = r = g = b = 0;
+}
+
+ARGB::ARGB(long value): RGB(value)
+{
+	a = ((unsigned char)(value >> 24) / 255.d);
+}
+
+class ImageWriter
+{
+public:
+	ImageWriter& SetBackground(const Anope::string& path);
+	ImageWriter& SetText(const std::vector<Anope::string>& text);
+	ImageWriter& SetQuotePosition(size_t top, size_t left, size_t bottom, size_t right);
+	ImageWriter& SetOutputPath(const Anope::string& filename);
+	ImageWriter& SetBgColor(long);
+	ImageWriter& SetFgColor(long);
+	ImageWriter& SetFontSize(char);
+	ImageWriter& SetFontPath(const Anope::string &);
+
+	bool Build(User* u);
+
+protected:
+	Anope::string background;
+	std::vector<Anope::string> text;
+	Anope::string outputName;
+	ARGB bgColor;
+	RGB fgColor;
+	size_t top;
+	size_t left;
+	size_t bottom;
+	size_t right;
+	char fontSize;
+	Anope::string fontPath;
+
+	void WriteText(pngwriter &writer, pngwriterfont &font, char fontSize, char *str, int strFrom, int strTo, int px, int py, const RGB &rgb) const;
+	int WriteText(pngwriter &writer, pngwriterfont &font, char fontSize, const Anope::string &str, int lineIndex, const RGB &rgb);
+	int GetTextLength(pngwriter &writer, pngwriterfont &font, char fontSize, char *str, int maxWidth) const;
+};
+
+ImageWriter& ImageWriter::SetFontSize(char value)
+{
+	fontSize = value;
+	return *this;
+}
+
+ImageWriter& ImageWriter::SetFontPath(const Anope::string& value)
+{
+	fontPath = value;
+	return *this;
+}
+
+ImageWriter& ImageWriter::SetBackground(const Anope::string& path)
+{
+	background = path;
+	return *this;
+}
+
+ImageWriter& ImageWriter::SetText(const std::vector<Anope::string>& txt)
+{
+	text = txt;
+	return *this;
+}
+
+ImageWriter& ImageWriter::SetOutputPath(const Anope::string& path)
+{
+	outputName = path;
+	return *this;
+}
+
+ImageWriter& ImageWriter::SetBgColor(long value)
+{
+	bgColor = ARGB(value);
+	return *this;
+}
+
+ImageWriter& ImageWriter::SetFgColor(long value)
+{
+	fgColor = RGB(value);
+	return *this;
+}
+
+ImageWriter& ImageWriter::SetQuotePosition(size_t top, size_t left, size_t right, size_t bottom)
+{
+	this->top = top;
+	this->left = left;
+	this->bottom = bottom;
+	this->right = right;
+	return *this;
+}
+
+int ImageWriter::GetTextLength(pngwriter &writer, pngwriterfont &font, char fontSize, char *str, int maxWidth) const
+{
+	int w = writer.get_text_width(font, fontSize, str);
+	if (w <= maxWidth)
+		return strlen(str);
+	return (int) (strlen(str) * ((double) maxWidth / (double) w));
+}
+
+void ImageWriter::WriteText(pngwriter &writer, pngwriterfont &font, char fontSize,
+		char *str, int strFrom, int strTo,
+		int px, int py, const RGB &rgb) const
+{
+	char tmp = str[strTo];
+	str[strTo] = 0;
+	writer.plot_text(font, fontSize, px, py, 0, str +strFrom, rgb.r, rgb.g, rgb.b);
+	str[strTo] = tmp;
+}
+
+int ImageWriter::WriteText(pngwriter &writer, pngwriterfont& font, char fontSize, const Anope::string &str, int lineIndex, const RGB &rgb)
+{
+	const char lineHeight = fontSize +6,
+		  marginSize = 10;
+	char *cstrFull = strdup(str.c_str());
+	int maxLen = GetTextLength(writer, font, fontSize, cstrFull, right -left -2*marginSize);
+	int written = 0;
+
+	do {
+		WriteText(writer, font, fontSize, cstrFull, written, written +maxLen, left +marginSize, top -marginSize -(lineHeight * lineIndex) -(fontSize), rgb);
+		written += maxLen;
+		++lineIndex;
+	} while (written < str.length());
+
+	free(cstrFull);
+	return lineIndex;
+}
+
+bool ImageWriter::Build(User *u)
+{
+    std::string err;
+    pngwriterfont font(fontPath.c_str(), err);
+    if (!font.ready())
+    {
+        if (u)
+            u->SendMessage((*instaServ)->GetBotInfo(), "Error: Cannot load font (" +err +")");
+        return false;
+    }
+	pngwriter writer(1, 1, 0, outputName.c_str());
+	if (!writer.readfromfile(background.c_str()))
+    {
+        if (u)
+            u->SendMessage((*instaServ)->GetBotInfo(), "Error: Cannot load background image");
+        return false;
+    }
+
+	writer.filledsquare_blend(left, top, right, bottom,
+			bgColor.a, bgColor.r, bgColor.g, bgColor.b);
+
+	size_t i =0;
+	for (const Anope::string& str: text)
+		i = WriteText(writer, font, fontSize, str, i, fgColor);
+	writer.close();
+	return true;
+}
+
+class InstaMessageBufferImpl: public InstaMessageBuffer, public Timer
+{
+	std::vector<Anope::string> lines;
+	User *u;
+	ISCreate *module;
+
+public:
+	InstaMessageBufferImpl(ISCreate *m, User *user);
+
+	void Tick(time_t t) anope_override;
+	void Add(Anope::string &msg) anope_override;
+	size_t LineCount() const anope_override;
+	void OnEndBuffer() anope_override;
+};
+
+class CommandISCreate : public Command
+{
+	ISCreate *creator;
+public:
+	CommandISCreate(ISCreate *c, const Anope::string &sname = "instaserv/create") : Command((Module*) c, sname, 0, 0), creator(c)
+	{
+		this->SetDesc(_("Create a new quote"));
+		this->SetSyntax("");
+	}
+
+	void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+	{
+		if (!source.GetUser())
+			return;
+		source.Reply("Type in your quote, end with a line only containing `EOF'");
+		instaServ->SetBuffer(source.GetUser(), new InstaMessageBufferImpl(creator, source.GetUser()));
+	}
+
+	bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+	{
+		this->SendSyntax(source);
+		source.Reply(_(" \n"
+			"Create a new quote image"));
+		return true;
+	}
+};
+
+class ISCreate : public Module
+{
+	CommandISCreate commandiscreate;
+
+ public:
+	ISCreate(const Anope::string &modname, const Anope::string &creator);
+	size_t GetMaxLines()
+	{
+		return 5;
+	}
+};
+
+ISCreate::ISCreate(const Anope::string &modname, const Anope::string &creator): Module(modname, creator, VENDOR), commandiscreate(this)
+{}
+
+InstaMessageBufferImpl::InstaMessageBufferImpl(ISCreate *m, User *user) :Timer(*instaServ, Config->GetModule("instaserv")->Get<time_t>("typingtimeout", "1m")), u(user), module(m)
+{}
+
+void InstaMessageBufferImpl::Tick(time_t t)
+{
+	(*instaServ)->OnExpire(u);
+}
+
+void InstaMessageBufferImpl::Add(Anope::string &msg)
+{
+	if (LineCount() < module->GetMaxLines())
+		lines.emplace_back(msg);
+	else
+	{
+		std::stringstream ss;
+		ss << "Cannot paste more than " << module->GetMaxLines() << " lines";
+		u->SendMessage((*instaServ)->GetBotInfo(), ss.str());
+	}
+}
+
+size_t InstaMessageBufferImpl::LineCount() const
+{
+	return lines.size();
+}
+
+void InstaMessageBufferImpl::OnEndBuffer()
+{
+	ImageWriter builder;
+	builder.SetBackground("/tmp/riz_carbo.png")
+		.SetText(lines)
+		.SetOutputPath("/srv/http/instaserv/out.png")
+		.SetQuotePosition(458, 10, 614, 10)
+		.SetBgColor(0xAAA3A5A7)
+		.SetFgColor(0x474255)
+		.SetFontPath("/home/isundil/projects/anope/testinstall/data/monoid.ttf")
+		.SetFontSize(16);
+	builder.Build(u);
+	(*instaServ)->OnExpire(u);
+}
+
+MODULE_INIT(ISCreate)

+ 8 - 11
instaserv.cpp → src/instaserv.cpp

@@ -1,7 +1,6 @@
 /* QuoteServ core functions
  */
 
-#include "module.h"
 #include "instaserv.h"
 
 class InstaServService: public InstaServCore
@@ -83,17 +82,15 @@ void InstaServService::SetBuffer(User *u, InstaMessageBuffer *buffer)
 
 EventReturn InstaServService::OnBotPrivmsg(User *u, BotInfo *bi, Anope::string &msg)
 {
-	if (bi == InstaServ)
+    InstaMessageBuffer *buffer;
+
+	if (bi == InstaServ && (buffer = GetBuffer(u)) != NULL)
 	{
-		InstaMessageBuffer *buffer = GetBuffer(u);
-		if (buffer)
-		{
-			if (msg == "EOF")
-				buffer->OnEndBuffer();
-			else
-				buffer->Add(msg);
-			return EVENT_STOP;
-		}
+        if (msg == "EOF")
+            buffer->OnEndBuffer();
+        else
+            buffer->Add(msg);
+        return EVENT_STOP;
 	}
 	return EVENT_CONTINUE;
 }