TextToSvgPath
GUI application that converts text to SVG path
TextToSvgPath.h
#ifndef _TextToSvgPath_TextToSvgPath_h
#define _TextToSvgPath_TextToSvgPath_h
#include <CtrlLib/CtrlLib.h>
#include <RichEdit/RichEdit.h>
using namespace Upp;
#define LAYOUTFILE <TextToSvgPath/TextToSvgPath.lay>
#include <CtrlCore/lay.h>
String TextToSvgPath(double x, double y, const char *text, Font fnt, bool singleline);
struct Preview : Ctrl {
String svgpath;
virtual void Paint(Draw& w);
};
struct TextToSvgPathDlg : public WithTextToSvgPathLayout<TopWindow> {
Preview preview;
TextToSvgPathDlg();
};
#endif
main.cpp
#include "TextToSvgPath.h"
void Preview::Paint(Draw& w)
{
DrawPainter sw(w, GetSize());
sw.Clear(SWhite());
sw.Path(svgpath).Fill(SBlack());
}
TextToSvgPathDlg::TextToSvgPathDlg()
{
CtrlLayout(*this, "Text to SVG path converter");
for(int i = 1; i < Font::GetFaceCount(); i++)
if(Font::GetFaceInfo(i) & Font::SCALEABLE)
face.Add(i, Font::GetFaceName(i));
face <<= Font::SANSSERIF;
height.MinMax(6, 500);
for(int i = 4; i < 500; i += i < 16 ? 1 : i < 32 ? 4 : i < 48 ? 8 : 16)
height.AddList(i);
height <<= 128;
svgpath.SetReadOnly();
preview.SetFrame(ViewFrame());
for(Ctrl *q = GetFirstChild(); q; q = q->GetNext())
if(!dynamic_cast<Button *>(q))
*q << [=] {
Font fnt(~face, ~height);
fnt.Bold(~bold);
fnt.Italic(~italic);
svgpath <<= preview.svgpath = TextToSvgPath(0, 0, (String)~text, fnt, ~singleline);
preview.Refresh();
};
copy.SetImage(CtrlImg::copy());
copy << [=] {
WriteClipboardText(preview.svgpath);
};
Sizeable().Zoomable();
}
GUI_APP_MAIN
{
TextToSvgPathDlg().Run();
}
ToSvg.cpp
#include "TextToSvgPath.h"
struct TextToSvg : FontGlyphConsumer {
String t; // here we accumulate the SVG path text
void Put(Pointf p);
virtual void Move(Pointf p);
virtual void Line(Pointf p);
virtual void Quadratic(Pointf p1, Pointf p2);
virtual void Cubic(Pointf p1, Pointf p2, Pointf p3);
virtual void Close();
};
void TextToSvg::Put(Pointf p)
{
t << Format("%.2f %.2f ", p.x, p.y);
}
void TextToSvg::Move(Pointf p)
{
t << 'M';
Put(p);
}
void TextToSvg::Line(Pointf p)
{
t << 'L';
Put(p);
}
void TextToSvg::Quadratic(Pointf p1, Pointf p)
{
t << 'Q';
Put(p1);
Put(p);
}
void TextToSvg::Cubic(Pointf p1, Pointf p2, Pointf p)
{
t << 'C';
Put(p1);
Put(p2);
Put(p);
}
void TextToSvg::Close()
{
t << 'Z';
}
String TextToSvgPath(double x, double y, const char *text, Font fnt, bool singleline)
{
WString ws = ToUnicode(text, CHARSET_DEFAULT);
TextToSvg t;
for(const wchar *s = ~ws; *s; s++) {
fnt.Render(t, x, y, *s);
x += fnt[*s]; // move the reference point
if(!singleline)
t.t << "\n";
}
return t.t;
}
TextToSvgPath.lay
LAYOUT(TextToSvgPathLayout, 704, 588)
ITEM(Label, dv___0, SetLabel(t_("Text")).LeftPosZ(8, 33).TopPosZ(28, 19))
ITEM(EditString, text, HSizePosZ(44, 8).TopPosZ(28, 19))
ITEM(Label, dv___2, SetLabel(t_("Font")).LeftPosZ(8, 33).TopPosZ(4, 19))
ITEM(DropList, face, LeftPosZ(44, 188).TopPosZ(4, 19))
ITEM(Label, dv___4, SetLabel(t_("Height")).LeftPosZ(252, 39).TopPosZ(4, 19))
ITEM(WithDropChoice<EditInt>, height, LeftPosZ(292, 56).TopPosZ(4, 19))
ITEM(Option, bold, SetLabel(t_("Bold")).LeftPosZ(356, 52).TopPosZ(4, 20))
ITEM(Option, italic, SetLabel(t_("Italic")).LeftPosZ(408, 52).TopPosZ(4, 20))
ITEM(LineEdit, svgpath, HSizePosZ(8, 8).VSizePosZ(52, 268))
UNTYPED(preview, HSizePosZ(8, 8).BottomPosZ(4, 260))
ITEM(Button, copy, SetLabel(t_("Copy path to clipboard")).RightPosZ(8, 128).TopPosZ(4, 20))
ITEM(Option, singleline, SetLabel(t_("Single line")).LeftPosZ(484, 80).TopPosZ(4, 20))
END_LAYOUT
|