mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 14:16:07 -06:00
RichText: Diagram: Fixed rotated text
This commit is contained in:
parent
38e25e80e9
commit
bc6e527eb1
5 changed files with 442 additions and 395 deletions
|
|
@ -1,370 +1,370 @@
|
|||
#include "Painter.h"
|
||||
|
||||
namespace Upp {
|
||||
|
||||
struct PaintCharPath : FontGlyphConsumer {
|
||||
Painter *sw;
|
||||
|
||||
virtual void Move(Pointf p) {
|
||||
sw->Move(p);
|
||||
}
|
||||
virtual void Line(Pointf p) {
|
||||
sw->Line(p);
|
||||
}
|
||||
virtual void Quadratic(Pointf p1, Pointf p2) {
|
||||
sw->Quadratic(p1, p2);
|
||||
}
|
||||
virtual void Cubic(Pointf p1, Pointf p2, Pointf p3) {
|
||||
sw->Cubic(p1, p2, p3);
|
||||
}
|
||||
virtual void Close() {
|
||||
sw->Close();
|
||||
}
|
||||
};
|
||||
|
||||
void PaintCharacter(Painter& sw, const Pointf& p, int chr, Font font)
|
||||
{
|
||||
GlyphInfo gi = GetGlyphInfo(font, chr);
|
||||
PaintCharPath pw;
|
||||
pw.sw = &sw;
|
||||
if(gi.IsNormal())
|
||||
font.Render(pw, p.x, p.y, chr);
|
||||
else
|
||||
if(gi.IsReplaced()) {
|
||||
Font fnt = font;
|
||||
fnt.Face(gi.lspc);
|
||||
fnt.Height(gi.rspc);
|
||||
fnt.Render(pw, p.x, p.y + font.GetAscent() - fnt.GetAscent(), chr);
|
||||
}
|
||||
else
|
||||
if(gi.IsComposed()) {
|
||||
ComposedGlyph cg;
|
||||
Compose(font, chr, cg);
|
||||
font.Render(pw, p.x, p.y, cg.basic_char);
|
||||
sw.Div();
|
||||
cg.mark_font.Render(pw, p.x + cg.mark_pos.x, p.y + cg.mark_pos.y, cg.mark_char);
|
||||
}
|
||||
sw.EvenOdd(true);
|
||||
}
|
||||
|
||||
Xform2D GetLineSzXform(const Pointf& p1, const Pointf& p2, const Sizef& sz)
|
||||
{
|
||||
Xform2D m = Xform2D::Scale(Distance(p1, p2) / sz.cx);
|
||||
if(p1.y != p2.y)
|
||||
m = m * Xform2D::Rotation(Bearing(p2 - p1));
|
||||
m = m * Xform2D::Translation(p1.x, p1.y);
|
||||
return m;
|
||||
}
|
||||
|
||||
Painter& Painter::Fill(const Image& image, Pointf p1, Pointf p2, dword flags)
|
||||
{
|
||||
return Fill(image, GetLineSzXform(p1, p2, image.GetSize()), flags);
|
||||
}
|
||||
|
||||
Painter& Painter::Fill(const Image& image, double x1, double y1,
|
||||
double x2, double y2, dword flags)
|
||||
{
|
||||
return Fill(image, Pointf(x1, y1), Pointf(x2, y2), flags);
|
||||
}
|
||||
|
||||
Painter& Painter::Fill(double x1, double y1, const RGBA& color1, double x2, double y2, const RGBA& color2, int style)
|
||||
{
|
||||
return Fill(Pointf(x1, y1), color1, Pointf(x2, y2), color2, style);
|
||||
}
|
||||
|
||||
Painter& Painter::Fill(const RGBA& color1, const RGBA& color2, const Xform2D& transsrc, dword flags)
|
||||
{
|
||||
FillOp(color1, color2, transsrc, flags);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Painter& Painter::Fill(double fx, double fy, const RGBA& color1, double cx, double cy, double r, const RGBA& color2, int style)
|
||||
{
|
||||
return Fill(Pointf(fx, fy), color1, Pointf(cx, cy), r, color2, style);
|
||||
}
|
||||
|
||||
Painter& Painter::Fill(const Pointf& c, const RGBA& color1, double r, const RGBA& color2, int style)
|
||||
{
|
||||
return Fill(c, color1, c, r, color2, style);
|
||||
}
|
||||
|
||||
Painter& Painter::Fill(double x, double y, const RGBA& color1, double r, const RGBA& color2, int style)
|
||||
{
|
||||
return Fill(Pointf(x, y), color1, r, color2, style);
|
||||
}
|
||||
|
||||
Painter& Painter::Fill(const Pointf& f, const RGBA& color1, const RGBA& color2, const Xform2D& transsrc, int style)
|
||||
{
|
||||
FillOp(f, color1, color2, transsrc, style);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Painter& Painter::Stroke(double width, const Pointf& f, const RGBA& color1, const RGBA& color2, const Xform2D& transsrc, int style)
|
||||
{
|
||||
StrokeOp(width, f, color1, color2, transsrc, style);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Painter& Painter::Translate(double x, double y)
|
||||
{
|
||||
Transform(Xform2D::Translation(x, y));
|
||||
return *this;
|
||||
}
|
||||
|
||||
Painter& Painter::Translate(const Pointf& p)
|
||||
{
|
||||
return Translate(p.x, p.y);
|
||||
}
|
||||
|
||||
Painter& Painter::Stroke(double width, const Image& image, const Pointf& p1, const Pointf& p2, dword flags)
|
||||
{
|
||||
return Stroke(width, image, GetLineSzXform(p1, p2, image.GetSize()), flags);
|
||||
}
|
||||
|
||||
Painter& Painter::Stroke(double width, const Image& image, double x1, double y1, double x2, double y2, dword flags)
|
||||
{
|
||||
return Stroke(width, image, Pointf(x1, y1), Pointf(x2, y2), flags);
|
||||
}
|
||||
|
||||
Painter& Painter::Stroke(double width, double x1, double y1, const RGBA& color1, double x2, double y2, const RGBA& color2, int style)
|
||||
{
|
||||
return Stroke(width, Pointf(x1, y1), color1, Pointf(x2, y2), color2, style);
|
||||
}
|
||||
|
||||
Painter& Painter::Stroke(double width, const RGBA& color1, const RGBA& color2, const Xform2D& transsrc, dword flags)
|
||||
{
|
||||
StrokeOp(width, color1, color2, transsrc, flags);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Painter& Painter::Stroke(double width, double fx, double fy, const RGBA& color1, double cx, double cy, double r, const RGBA& color2, int style)
|
||||
{
|
||||
return Stroke(width, Pointf(fx, fy), color1, Pointf(cx, cy), r, color2, style);
|
||||
}
|
||||
|
||||
Painter& Painter::Stroke(double width, const Pointf& c, const RGBA& color1, double r, const RGBA& color2, int style)
|
||||
{
|
||||
return Stroke(width, c, color1, c, r, color2, style);
|
||||
}
|
||||
|
||||
Painter& Painter::Stroke(double width, double x, double y, const RGBA& color1, double r, const RGBA& color2, int style)
|
||||
{
|
||||
return Stroke(width, Pointf(x, y), color1, r, color2, style);
|
||||
}
|
||||
|
||||
Painter& Painter::Rotate(double a)
|
||||
{
|
||||
Transform(Xform2D::Rotation(a));
|
||||
return *this;
|
||||
}
|
||||
|
||||
Painter& Painter::Scale(double scalex, double scaley)
|
||||
{
|
||||
Transform(Xform2D::Scale(scalex, scaley));
|
||||
return *this;
|
||||
}
|
||||
|
||||
Painter& Painter::Scale(double scale)
|
||||
{
|
||||
Scale(scale, scale);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector<double> StringToDash(const String& dash, double& start)
|
||||
{
|
||||
Vector<double> d;
|
||||
CParser p(dash);
|
||||
try {
|
||||
while(!p.IsEof())
|
||||
if(p.Char(':'))
|
||||
start = p.ReadDouble();
|
||||
else
|
||||
d.Add(p.ReadDouble());
|
||||
}
|
||||
catch(CParser::Error) {}
|
||||
if(d.GetCount() & 1) {
|
||||
Vector<double> dash1;
|
||||
dash1.Append(d);
|
||||
dash1.Append(d);
|
||||
return dash1;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
void Painter::DashOp(const String& dash, double start)
|
||||
{
|
||||
Vector<double> h = StringToDash(dash, start);
|
||||
DashOp(h, start);
|
||||
}
|
||||
|
||||
Painter& Painter::Character(double x, double y, int ch, Font fnt)
|
||||
{
|
||||
return Character(Pointf(x, y), ch, fnt);
|
||||
}
|
||||
|
||||
void Painter::TextOp(const Pointf& p, const wchar *text, Font fnt, int n, const double *dx)
|
||||
{
|
||||
if(n == 0) {
|
||||
Move(0, 0);
|
||||
return;
|
||||
}
|
||||
Font fi = fnt;
|
||||
double m = 1;
|
||||
if(fnt.GetHeight() < 50) {
|
||||
fi.Height(100 * fnt.GetHeight());
|
||||
m = 0.01;
|
||||
}
|
||||
else
|
||||
if(fnt.GetHeight() < 500) {
|
||||
fi.Height(10 * fnt.GetHeight());
|
||||
m = 0.1;
|
||||
}
|
||||
double x = p.x;
|
||||
while(n) {
|
||||
int ch = *text++;
|
||||
Character(x, p.y, ch, fnt);
|
||||
Div();
|
||||
if(dx)
|
||||
x += *dx++;
|
||||
else
|
||||
x += fi[ch] * m;
|
||||
n--;
|
||||
}
|
||||
if(fnt.IsUnderline() || fnt.IsStrikeout()) {
|
||||
double a = fnt.GetAscent();
|
||||
double cy = max(a / 16, 1.0);
|
||||
double cx = x - p.x;
|
||||
if(fnt.IsUnderline())
|
||||
Rectangle(p.x, p.y + a + cy, cx, cy);
|
||||
if(fnt.IsStrikeout())
|
||||
Rectangle(p.x, p.y + 2 * a / 3, cx, cy);
|
||||
}
|
||||
}
|
||||
|
||||
Painter& Painter::Text(double x, double y, const wchar *text, Font fnt, int n, const double *dx)
|
||||
{
|
||||
return Text(Pointf(x, y), text, fnt, n < 0 ? strlen__(text) : n, dx);
|
||||
}
|
||||
|
||||
Painter& Painter::Text(const Pointf& p, const WString& s, Font fnt, const double *dx)
|
||||
{
|
||||
return Text(p, ~s, fnt, s.GetLength(), dx);
|
||||
}
|
||||
|
||||
Painter& Painter::Text(double x, double y, const WString& s, Font fnt, const double *dx)
|
||||
{
|
||||
return Text(Pointf(x, y), s, fnt, dx);
|
||||
}
|
||||
|
||||
Painter& Painter::Text(const Pointf& p, const String& s, Font fnt, const double *dx)
|
||||
{
|
||||
return Text(p, s.ToWString(), fnt, dx);
|
||||
}
|
||||
|
||||
Painter& Painter::Text(double x, double y, const String& s, Font fnt, const double *dx)
|
||||
{
|
||||
return Text(Pointf(x, y), s, fnt, dx);
|
||||
}
|
||||
|
||||
Painter& Painter::Text(const Pointf& p, const char *text, Font fnt, int n, const double *dx)
|
||||
{
|
||||
WString s = ToUtf32(text, n < 0 ? (int)strlen(text) : n);
|
||||
return Text(p, s, fnt, s.GetCount(), dx);
|
||||
}
|
||||
|
||||
Painter& Painter::Text(double x, double y, const char *text, Font fnt, int n, const double *dx)
|
||||
{
|
||||
return Text(Pointf(x, y), text, fnt, n, dx);
|
||||
}
|
||||
|
||||
Painter& Painter::Rectangle(double x, double y, double cx, double cy)
|
||||
{
|
||||
if (cx < 0) { x += cx; cx = -cx;}
|
||||
if (cy < 0) { y += cy; cy = -cy;}
|
||||
return Move(x, y).RelLine(cx, 0).RelLine(0, cy).RelLine(-cx, 0).Close();
|
||||
}
|
||||
|
||||
Painter& Painter::RoundedRectangle(double x, double y, double cx, double cy, double rx, double ry)
|
||||
{
|
||||
ASSERT(rx >= 0 && ry >= 0);
|
||||
if (cx < 0) { x += cx; cx = -cx;}
|
||||
if (cy < 0) { y += cy; cy = -cy;}
|
||||
Move(x + rx, y).Arc(x + rx, y + ry, rx, ry, -M_PI / 2, -M_PI / 2)
|
||||
.Line(x, y + cy - ry).Arc(x + rx, y + cy - ry, rx, ry, M_PI, -M_PI / 2)
|
||||
.Line(x + cx - rx, y + cy).Arc(x + cx - rx, y + cy - ry, rx, ry, M_PI / 2, -M_PI / 2)
|
||||
.Line(x + cx, y + ry).Arc(x + cx - rx, y + ry, rx, ry, 0, -M_PI / 2).Line(x + rx, y);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Painter& Painter::Ellipse(double x, double y, double rx, double ry)
|
||||
{
|
||||
return Move(x + rx, y).Arc(x, y, rx, ry, 0, 2 * M_PI).Close();
|
||||
}
|
||||
|
||||
Painter& Painter::Circle(double x, double y, double r)
|
||||
{
|
||||
return Ellipse(x, y, r, r);
|
||||
}
|
||||
|
||||
void NilPainter::ClearOp(const RGBA& color) {}
|
||||
void NilPainter::MoveOp(const Pointf& p, bool rel) {}
|
||||
void NilPainter::LineOp(const Pointf& p, bool rel) {}
|
||||
void NilPainter::QuadraticOp(const Pointf& p1, const Pointf& p, bool rel) {}
|
||||
void NilPainter::QuadraticOp(const Pointf& p, bool rel) {}
|
||||
void NilPainter::CubicOp(const Pointf& p1, const Pointf& p2, const Pointf& p, bool rel) {}
|
||||
void NilPainter::CubicOp(const Pointf& p2, const Pointf& p, bool rel) {}
|
||||
void NilPainter::ArcOp(const Pointf& c, const Pointf& r, double angle, double sweep, bool rel) {}
|
||||
void NilPainter::SvgArcOp(const Pointf& r, double xangle, bool large, bool sweep, const Pointf& p, bool rel) {}
|
||||
void NilPainter::CloseOp() {}
|
||||
void NilPainter::DivOp() {}
|
||||
void NilPainter::FillOp(const RGBA& color) {}
|
||||
void NilPainter::FillOp(const Image& image, const Xform2D& transsrc, dword flags) {}
|
||||
void NilPainter::FillOp(const RGBA& color1, const RGBA& color2, const Xform2D& transsrc, int style) {}
|
||||
void NilPainter::FillOp(const Pointf& p1, const RGBA& color1, const Pointf& p2, const RGBA& color2, int style) {}
|
||||
void NilPainter::FillOp(const Pointf& f, const RGBA& color1, const Pointf& c, double r, const RGBA& color2, int style) {}
|
||||
void NilPainter::FillOp(const Pointf& f, const RGBA& color1, const RGBA& color2, const Xform2D& transsrc, int style) {}
|
||||
void NilPainter::StrokeOp(double width, const RGBA& rgba) {}
|
||||
void NilPainter::StrokeOp(double width, const Image& image, const Xform2D& transsrc, dword flags) {}
|
||||
void NilPainter::StrokeOp(double width, const RGBA& color1, const RGBA& color2, const Xform2D& transsrc, int style) {}
|
||||
void NilPainter::StrokeOp(double width, const Pointf& p1, const RGBA& color1, const Pointf& p2, const RGBA& color2, int style) {}
|
||||
void NilPainter::StrokeOp(double width, const Pointf& f, const RGBA& color1, const Pointf& c, double r, const RGBA& color2, int style) {}
|
||||
void NilPainter::StrokeOp(double width, const Pointf& f, const RGBA& color1, const RGBA& color2, const Xform2D& transsrc, int style) {}
|
||||
void NilPainter::ClipOp() {}
|
||||
void NilPainter::CharacterOp(const Pointf& p, int ch, Font fnt) {}
|
||||
void NilPainter::TextOp(const Pointf& p, const wchar *text, Font fnt, int n, const double *dx) {}
|
||||
void NilPainter::ColorStopOp(double pos, const RGBA& color) {}
|
||||
void NilPainter::ClearStopsOp() {}
|
||||
void NilPainter::OpacityOp(double o) {}
|
||||
void NilPainter::LineCapOp(int linecap) {}
|
||||
void NilPainter::LineJoinOp(int linejoin) {}
|
||||
void NilPainter::MiterLimitOp(double l) {}
|
||||
void NilPainter::EvenOddOp(bool evenodd) {}
|
||||
void NilPainter::InvertOp(bool invert) {}
|
||||
void NilPainter::ImageFilterOp(int filter) {}
|
||||
void NilPainter::DashOp(const Vector<double>& dash, double start) {}
|
||||
void NilPainter::TransformOp(const Xform2D& m) {}
|
||||
void NilPainter::BeginOp() {}
|
||||
void NilPainter::EndOp() {}
|
||||
void NilPainter::BeginMaskOp() {}
|
||||
void NilPainter::BeginOnPathOp(double, bool) {}
|
||||
|
||||
ImagePainter::ImagePainter(Size sz, int mode)
|
||||
: ImageBuffer__(sz), BufferPainter(ImageBuffer__::ib, mode)
|
||||
{}
|
||||
|
||||
ImagePainter::ImagePainter(int cx, int cy, int mode)
|
||||
: ImageBuffer__(Size(cx, cy)), BufferPainter(ImageBuffer__::ib, mode)
|
||||
{}
|
||||
|
||||
DrawPainter::DrawPainter(Draw& w, Size sz, int mode)
|
||||
: ImagePainter(sz, mode), w(w)
|
||||
{}
|
||||
|
||||
DrawPainter::~DrawPainter()
|
||||
{
|
||||
Finish();
|
||||
GetBuffer().PaintOnceHint();
|
||||
w.DrawImage(0, 0, *this);
|
||||
}
|
||||
|
||||
}
|
||||
#include "Painter.h"
|
||||
|
||||
namespace Upp {
|
||||
|
||||
struct PaintCharPath : FontGlyphConsumer {
|
||||
Painter *sw;
|
||||
|
||||
virtual void Move(Pointf p) {
|
||||
sw->Move(p);
|
||||
}
|
||||
virtual void Line(Pointf p) {
|
||||
sw->Line(p);
|
||||
}
|
||||
virtual void Quadratic(Pointf p1, Pointf p2) {
|
||||
sw->Quadratic(p1, p2);
|
||||
}
|
||||
virtual void Cubic(Pointf p1, Pointf p2, Pointf p3) {
|
||||
sw->Cubic(p1, p2, p3);
|
||||
}
|
||||
virtual void Close() {
|
||||
sw->Close();
|
||||
}
|
||||
};
|
||||
|
||||
void PaintCharacter(Painter& sw, const Pointf& p, int chr, Font font)
|
||||
{
|
||||
GlyphInfo gi = GetGlyphInfo(font, chr);
|
||||
PaintCharPath pw;
|
||||
pw.sw = &sw;
|
||||
if(gi.IsNormal())
|
||||
font.Render(pw, p.x, p.y, chr);
|
||||
else
|
||||
if(gi.IsReplaced()) {
|
||||
Font fnt = font;
|
||||
fnt.Face(gi.lspc);
|
||||
fnt.Height(gi.rspc);
|
||||
fnt.Render(pw, p.x, p.y + font.GetAscent() - fnt.GetAscent(), chr);
|
||||
}
|
||||
else
|
||||
if(gi.IsComposed()) {
|
||||
ComposedGlyph cg;
|
||||
Compose(font, chr, cg);
|
||||
font.Render(pw, p.x, p.y, cg.basic_char);
|
||||
sw.Div();
|
||||
cg.mark_font.Render(pw, p.x + cg.mark_pos.x, p.y + cg.mark_pos.y, cg.mark_char);
|
||||
}
|
||||
sw.EvenOdd(true);
|
||||
}
|
||||
|
||||
Xform2D GetLineSzXform(const Pointf& p1, const Pointf& p2, const Sizef& sz)
|
||||
{
|
||||
Xform2D m = Xform2D::Scale(Distance(p1, p2) / sz.cx);
|
||||
if(p1.y != p2.y)
|
||||
m = m * Xform2D::Rotation(Bearing(p2 - p1));
|
||||
m = m * Xform2D::Translation(p1.x, p1.y);
|
||||
return m;
|
||||
}
|
||||
|
||||
Painter& Painter::Fill(const Image& image, Pointf p1, Pointf p2, dword flags)
|
||||
{
|
||||
return Fill(image, GetLineSzXform(p1, p2, image.GetSize()), flags);
|
||||
}
|
||||
|
||||
Painter& Painter::Fill(const Image& image, double x1, double y1,
|
||||
double x2, double y2, dword flags)
|
||||
{
|
||||
return Fill(image, Pointf(x1, y1), Pointf(x2, y2), flags);
|
||||
}
|
||||
|
||||
Painter& Painter::Fill(double x1, double y1, const RGBA& color1, double x2, double y2, const RGBA& color2, int style)
|
||||
{
|
||||
return Fill(Pointf(x1, y1), color1, Pointf(x2, y2), color2, style);
|
||||
}
|
||||
|
||||
Painter& Painter::Fill(const RGBA& color1, const RGBA& color2, const Xform2D& transsrc, dword flags)
|
||||
{
|
||||
FillOp(color1, color2, transsrc, flags);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Painter& Painter::Fill(double fx, double fy, const RGBA& color1, double cx, double cy, double r, const RGBA& color2, int style)
|
||||
{
|
||||
return Fill(Pointf(fx, fy), color1, Pointf(cx, cy), r, color2, style);
|
||||
}
|
||||
|
||||
Painter& Painter::Fill(const Pointf& c, const RGBA& color1, double r, const RGBA& color2, int style)
|
||||
{
|
||||
return Fill(c, color1, c, r, color2, style);
|
||||
}
|
||||
|
||||
Painter& Painter::Fill(double x, double y, const RGBA& color1, double r, const RGBA& color2, int style)
|
||||
{
|
||||
return Fill(Pointf(x, y), color1, r, color2, style);
|
||||
}
|
||||
|
||||
Painter& Painter::Fill(const Pointf& f, const RGBA& color1, const RGBA& color2, const Xform2D& transsrc, int style)
|
||||
{
|
||||
FillOp(f, color1, color2, transsrc, style);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Painter& Painter::Stroke(double width, const Pointf& f, const RGBA& color1, const RGBA& color2, const Xform2D& transsrc, int style)
|
||||
{
|
||||
StrokeOp(width, f, color1, color2, transsrc, style);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Painter& Painter::Translate(double x, double y)
|
||||
{
|
||||
Transform(Xform2D::Translation(x, y));
|
||||
return *this;
|
||||
}
|
||||
|
||||
Painter& Painter::Translate(const Pointf& p)
|
||||
{
|
||||
return Translate(p.x, p.y);
|
||||
}
|
||||
|
||||
Painter& Painter::Stroke(double width, const Image& image, const Pointf& p1, const Pointf& p2, dword flags)
|
||||
{
|
||||
return Stroke(width, image, GetLineSzXform(p1, p2, image.GetSize()), flags);
|
||||
}
|
||||
|
||||
Painter& Painter::Stroke(double width, const Image& image, double x1, double y1, double x2, double y2, dword flags)
|
||||
{
|
||||
return Stroke(width, image, Pointf(x1, y1), Pointf(x2, y2), flags);
|
||||
}
|
||||
|
||||
Painter& Painter::Stroke(double width, double x1, double y1, const RGBA& color1, double x2, double y2, const RGBA& color2, int style)
|
||||
{
|
||||
return Stroke(width, Pointf(x1, y1), color1, Pointf(x2, y2), color2, style);
|
||||
}
|
||||
|
||||
Painter& Painter::Stroke(double width, const RGBA& color1, const RGBA& color2, const Xform2D& transsrc, dword flags)
|
||||
{
|
||||
StrokeOp(width, color1, color2, transsrc, flags);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Painter& Painter::Stroke(double width, double fx, double fy, const RGBA& color1, double cx, double cy, double r, const RGBA& color2, int style)
|
||||
{
|
||||
return Stroke(width, Pointf(fx, fy), color1, Pointf(cx, cy), r, color2, style);
|
||||
}
|
||||
|
||||
Painter& Painter::Stroke(double width, const Pointf& c, const RGBA& color1, double r, const RGBA& color2, int style)
|
||||
{
|
||||
return Stroke(width, c, color1, c, r, color2, style);
|
||||
}
|
||||
|
||||
Painter& Painter::Stroke(double width, double x, double y, const RGBA& color1, double r, const RGBA& color2, int style)
|
||||
{
|
||||
return Stroke(width, Pointf(x, y), color1, r, color2, style);
|
||||
}
|
||||
|
||||
Painter& Painter::Rotate(double a)
|
||||
{
|
||||
Transform(Xform2D::Rotation(a));
|
||||
return *this;
|
||||
}
|
||||
|
||||
Painter& Painter::Scale(double scalex, double scaley)
|
||||
{
|
||||
Transform(Xform2D::Scale(scalex, scaley));
|
||||
return *this;
|
||||
}
|
||||
|
||||
Painter& Painter::Scale(double scale)
|
||||
{
|
||||
Scale(scale, scale);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector<double> StringToDash(const String& dash, double& start)
|
||||
{
|
||||
Vector<double> d;
|
||||
CParser p(dash);
|
||||
try {
|
||||
while(!p.IsEof())
|
||||
if(p.Char(':'))
|
||||
start = p.ReadDouble();
|
||||
else
|
||||
d.Add(p.ReadDouble());
|
||||
}
|
||||
catch(CParser::Error) {}
|
||||
if(d.GetCount() & 1) {
|
||||
Vector<double> dash1;
|
||||
dash1.Append(d);
|
||||
dash1.Append(d);
|
||||
return dash1;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
void Painter::DashOp(const String& dash, double start)
|
||||
{
|
||||
Vector<double> h = StringToDash(dash, start);
|
||||
DashOp(h, start);
|
||||
}
|
||||
|
||||
Painter& Painter::Character(double x, double y, int ch, Font fnt)
|
||||
{
|
||||
return Character(Pointf(x, y), ch, fnt);
|
||||
}
|
||||
|
||||
void Painter::TextOp(const Pointf& p, const wchar *text, Font fnt, int n, const double *dx)
|
||||
{
|
||||
if(n == 0) {
|
||||
Move(0, 0);
|
||||
return;
|
||||
}
|
||||
Font fi = fnt;
|
||||
double m = 1;
|
||||
if(fnt.GetHeight() < 50) {
|
||||
fi.Height(100 * fnt.GetHeight());
|
||||
m = 0.01;
|
||||
}
|
||||
else
|
||||
if(fnt.GetHeight() < 500) {
|
||||
fi.Height(10 * fnt.GetHeight());
|
||||
m = 0.1;
|
||||
}
|
||||
double x = p.x;
|
||||
while(n) {
|
||||
int ch = *text++;
|
||||
Character(x, p.y, ch, fnt);
|
||||
Div();
|
||||
if(dx)
|
||||
x += *dx++;
|
||||
else
|
||||
x += fi[ch] * m;
|
||||
n--;
|
||||
}
|
||||
if(fnt.IsUnderline() || fnt.IsStrikeout()) {
|
||||
double a = fnt.GetAscent();
|
||||
double cy = max(a / 16, 1.0);
|
||||
double cx = x - p.x;
|
||||
if(fnt.IsUnderline())
|
||||
Rectangle(p.x, p.y + a + cy, cx, cy);
|
||||
if(fnt.IsStrikeout())
|
||||
Rectangle(p.x, p.y + 2 * a / 3, cx, cy);
|
||||
}
|
||||
}
|
||||
|
||||
Painter& Painter::Text(double x, double y, const wchar *text, Font fnt, int n, const double *dx)
|
||||
{
|
||||
return Text(Pointf(x, y), text, fnt, n < 0 ? strlen__(text) : n, dx);
|
||||
}
|
||||
|
||||
Painter& Painter::Text(const Pointf& p, const WString& s, Font fnt, const double *dx)
|
||||
{
|
||||
return Text(p, ~s, fnt, s.GetLength(), dx);
|
||||
}
|
||||
|
||||
Painter& Painter::Text(double x, double y, const WString& s, Font fnt, const double *dx)
|
||||
{
|
||||
return Text(Pointf(x, y), s, fnt, dx);
|
||||
}
|
||||
|
||||
Painter& Painter::Text(const Pointf& p, const String& s, Font fnt, const double *dx)
|
||||
{
|
||||
return Text(p, s.ToWString(), fnt, dx);
|
||||
}
|
||||
|
||||
Painter& Painter::Text(double x, double y, const String& s, Font fnt, const double *dx)
|
||||
{
|
||||
return Text(Pointf(x, y), s, fnt, dx);
|
||||
}
|
||||
|
||||
Painter& Painter::Text(const Pointf& p, const char *text, Font fnt, int n, const double *dx)
|
||||
{
|
||||
WString s = ToUtf32(text, n < 0 ? (int)strlen(text) : n);
|
||||
return Text(p, s, fnt, s.GetCount(), dx);
|
||||
}
|
||||
|
||||
Painter& Painter::Text(double x, double y, const char *text, Font fnt, int n, const double *dx)
|
||||
{
|
||||
return Text(Pointf(x, y), text, fnt, n, dx);
|
||||
}
|
||||
|
||||
Painter& Painter::Rectangle(double x, double y, double cx, double cy)
|
||||
{
|
||||
if (cx < 0) { x += cx; cx = -cx;}
|
||||
if (cy < 0) { y += cy; cy = -cy;}
|
||||
return Move(x, y).RelLine(cx, 0).RelLine(0, cy).RelLine(-cx, 0).Close();
|
||||
}
|
||||
|
||||
Painter& Painter::RoundedRectangle(double x, double y, double cx, double cy, double rx, double ry)
|
||||
{
|
||||
ASSERT(rx >= 0 && ry >= 0);
|
||||
if (cx < 0) { x += cx; cx = -cx;}
|
||||
if (cy < 0) { y += cy; cy = -cy;}
|
||||
Move(x + rx, y).Arc(x + rx, y + ry, rx, ry, -M_PI / 2, -M_PI / 2)
|
||||
.Line(x, y + cy - ry).Arc(x + rx, y + cy - ry, rx, ry, M_PI, -M_PI / 2)
|
||||
.Line(x + cx - rx, y + cy).Arc(x + cx - rx, y + cy - ry, rx, ry, M_PI / 2, -M_PI / 2)
|
||||
.Line(x + cx, y + ry).Arc(x + cx - rx, y + ry, rx, ry, 0, -M_PI / 2).Line(x + rx, y);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Painter& Painter::Ellipse(double x, double y, double rx, double ry)
|
||||
{
|
||||
return Move(x + rx, y).Arc(x, y, rx, ry, 0, 2 * M_PI).Close();
|
||||
}
|
||||
|
||||
Painter& Painter::Circle(double x, double y, double r)
|
||||
{
|
||||
return Ellipse(x, y, r, r);
|
||||
}
|
||||
|
||||
void NilPainter::ClearOp(const RGBA& color) {}
|
||||
void NilPainter::MoveOp(const Pointf& p, bool rel) {}
|
||||
void NilPainter::LineOp(const Pointf& p, bool rel) {}
|
||||
void NilPainter::QuadraticOp(const Pointf& p1, const Pointf& p, bool rel) {}
|
||||
void NilPainter::QuadraticOp(const Pointf& p, bool rel) {}
|
||||
void NilPainter::CubicOp(const Pointf& p1, const Pointf& p2, const Pointf& p, bool rel) {}
|
||||
void NilPainter::CubicOp(const Pointf& p2, const Pointf& p, bool rel) {}
|
||||
void NilPainter::ArcOp(const Pointf& c, const Pointf& r, double angle, double sweep, bool rel) {}
|
||||
void NilPainter::SvgArcOp(const Pointf& r, double xangle, bool large, bool sweep, const Pointf& p, bool rel) {}
|
||||
void NilPainter::CloseOp() {}
|
||||
void NilPainter::DivOp() {}
|
||||
void NilPainter::FillOp(const RGBA& color) {}
|
||||
void NilPainter::FillOp(const Image& image, const Xform2D& transsrc, dword flags) {}
|
||||
void NilPainter::FillOp(const RGBA& color1, const RGBA& color2, const Xform2D& transsrc, int style) {}
|
||||
void NilPainter::FillOp(const Pointf& p1, const RGBA& color1, const Pointf& p2, const RGBA& color2, int style) {}
|
||||
void NilPainter::FillOp(const Pointf& f, const RGBA& color1, const Pointf& c, double r, const RGBA& color2, int style) {}
|
||||
void NilPainter::FillOp(const Pointf& f, const RGBA& color1, const RGBA& color2, const Xform2D& transsrc, int style) {}
|
||||
void NilPainter::StrokeOp(double width, const RGBA& rgba) {}
|
||||
void NilPainter::StrokeOp(double width, const Image& image, const Xform2D& transsrc, dword flags) {}
|
||||
void NilPainter::StrokeOp(double width, const RGBA& color1, const RGBA& color2, const Xform2D& transsrc, int style) {}
|
||||
void NilPainter::StrokeOp(double width, const Pointf& p1, const RGBA& color1, const Pointf& p2, const RGBA& color2, int style) {}
|
||||
void NilPainter::StrokeOp(double width, const Pointf& f, const RGBA& color1, const Pointf& c, double r, const RGBA& color2, int style) {}
|
||||
void NilPainter::StrokeOp(double width, const Pointf& f, const RGBA& color1, const RGBA& color2, const Xform2D& transsrc, int style) {}
|
||||
void NilPainter::ClipOp() {}
|
||||
void NilPainter::CharacterOp(const Pointf& p, int ch, Font fnt) {}
|
||||
void NilPainter::TextOp(const Pointf& p, const wchar *text, Font fnt, int n, const double *dx) {}
|
||||
void NilPainter::ColorStopOp(double pos, const RGBA& color) {}
|
||||
void NilPainter::ClearStopsOp() {}
|
||||
void NilPainter::OpacityOp(double o) {}
|
||||
void NilPainter::LineCapOp(int linecap) {}
|
||||
void NilPainter::LineJoinOp(int linejoin) {}
|
||||
void NilPainter::MiterLimitOp(double l) {}
|
||||
void NilPainter::EvenOddOp(bool evenodd) {}
|
||||
void NilPainter::InvertOp(bool invert) {}
|
||||
void NilPainter::ImageFilterOp(int filter) {}
|
||||
void NilPainter::DashOp(const Vector<double>& dash, double start) {}
|
||||
void NilPainter::TransformOp(const Xform2D& m) {}
|
||||
void NilPainter::BeginOp() {}
|
||||
void NilPainter::EndOp() {}
|
||||
void NilPainter::BeginMaskOp() {}
|
||||
void NilPainter::BeginOnPathOp(double, bool) {}
|
||||
|
||||
ImagePainter::ImagePainter(Size sz, int mode)
|
||||
: ImageBuffer__(sz), BufferPainter(ImageBuffer__::ib, mode)
|
||||
{}
|
||||
|
||||
ImagePainter::ImagePainter(int cx, int cy, int mode)
|
||||
: ImageBuffer__(Size(cx, cy)), BufferPainter(ImageBuffer__::ib, mode)
|
||||
{}
|
||||
|
||||
DrawPainter::DrawPainter(Draw& w, Size sz, int mode)
|
||||
: ImagePainter(sz, mode), w(w)
|
||||
{}
|
||||
|
||||
DrawPainter::~DrawPainter()
|
||||
{
|
||||
Finish();
|
||||
GetBuffer().PaintOnceHint();
|
||||
w.DrawImage(0, 0, *this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -316,28 +316,46 @@ void DiagramEditor::MouseMove(Point p, dword keyflags)
|
|||
if(h)
|
||||
(h < 0 ? a1 : a2) = a;
|
||||
};
|
||||
Do(draghandle.x, m.pt[0].x, m.pt[1].x, p.x);
|
||||
Do(draghandle.y, m.pt[0].y, m.pt[1].y, p.y);
|
||||
if(m.aspect_ratio && !m.IsLine()) {
|
||||
m.Normalize();
|
||||
Sizef sz1, sz2;
|
||||
ComputeAspectSize(m, sz1, sz2);
|
||||
Sizef sz;
|
||||
if(draghandle.y == 0)
|
||||
sz = sz1;
|
||||
else
|
||||
if(draghandle.x == 0)
|
||||
sz = sz2;
|
||||
else
|
||||
sz = sz1.cx < sz2.cx ? sz1 : sz2;
|
||||
if(draghandle.x < 0)
|
||||
m.pt[0].x = m.pt[1].x - sz.cx;
|
||||
else
|
||||
m.pt[1].x = m.pt[0].x + sz.cx;
|
||||
if(draghandle.y < 0)
|
||||
m.pt[0].y = m.pt[1].y - sz.cy;
|
||||
else
|
||||
m.pt[1].y = m.pt[0].y + sz.cy;
|
||||
if(m.IsLine()) {
|
||||
Do(draghandle.x, m.pt[0].x, m.pt[1].x, p.x);
|
||||
Do(draghandle.y, m.pt[0].y, m.pt[1].y, p.y);
|
||||
}
|
||||
else {
|
||||
bool rotated = m.rotate && !m.IsLine();
|
||||
Rectf r = m.GetRect();
|
||||
Pointf cp(draghandle.x < 0 ? r.right : r.left, draghandle.y < 0 ? r.bottom : r.top);
|
||||
if(rotated) {
|
||||
p -= cp;
|
||||
r -= cp;
|
||||
p = Xform2D::Rotation(-M_2PI * m.rotate / 360).Transform(p);
|
||||
}
|
||||
Do(draghandle.x, r.left, r.right, p.x);
|
||||
Do(draghandle.y, r.top, r.bottom, p.y);
|
||||
if(m.aspect_ratio && !m.IsLine() && 0) {
|
||||
m.Normalize();
|
||||
Sizef sz1, sz2;
|
||||
ComputeAspectSize(m, sz1, sz2);
|
||||
Sizef sz;
|
||||
if(draghandle.y == 0)
|
||||
sz = sz1;
|
||||
else
|
||||
if(draghandle.x == 0)
|
||||
sz = sz2;
|
||||
else
|
||||
sz = sz1.cx < sz2.cx ? sz1 : sz2;
|
||||
if(draghandle.x < 0)
|
||||
m.pt[0].x = m.pt[1].x - sz.cx;
|
||||
else
|
||||
m.pt[1].x = m.pt[0].x + sz.cx;
|
||||
if(draghandle.y < 0)
|
||||
m.pt[0].y = m.pt[1].y - sz.cy;
|
||||
else
|
||||
m.pt[1].y = m.pt[0].y + sz.cy;
|
||||
}
|
||||
if(rotated)
|
||||
r += cp;
|
||||
m.pt[0] = r.TopLeft();
|
||||
m.pt[1] = r.BottomRight();
|
||||
}
|
||||
}
|
||||
UseConns();
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ void DiagramItem::Paint(Painter& w, const Diagram& diagram, dword style, const I
|
|||
double cx = r.GetWidth();
|
||||
double cy = r.GetHeight();
|
||||
|
||||
Rectf text_rect = r.Deflated(width + 2, 0);
|
||||
Rectf text_rect = r.Deflated(width + 2, 0).Offseted(-r.TopLeft());
|
||||
|
||||
double sz = min(cx, cy);
|
||||
double arrow_width = min(cx / 3, cy / 3);
|
||||
|
|
@ -394,8 +394,6 @@ void DiagramItem::Paint(Painter& w, const Diagram& diagram, dword style, const I
|
|||
break;
|
||||
}
|
||||
|
||||
w.End();
|
||||
|
||||
Rect tr = text_rect;
|
||||
int txt_cy = txt.GetHeight(pi.zoom, tr.GetWidth());
|
||||
txt.Paint(w, tr.left, tr.top + (tr.GetHeight() - txt_cy) / 2, tr.GetWidth(), pi);
|
||||
|
|
@ -407,6 +405,8 @@ void DiagramItem::Paint(Painter& w, const Diagram& diagram, dword style, const I
|
|||
w.Fill(128 * SYellow());
|
||||
w.Stroke(1, 190 * SColorHighlight());
|
||||
}
|
||||
|
||||
w.End();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
9
upptst/RoundRect/RoundRect.upp
Normal file
9
upptst/RoundRect/RoundRect.upp
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
uses
|
||||
CtrlLib;
|
||||
|
||||
file
|
||||
main.cpp;
|
||||
|
||||
mainconfig
|
||||
"" = "GUI";
|
||||
|
||||
20
upptst/RoundRect/main.cpp
Normal file
20
upptst/RoundRect/main.cpp
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
#include <CtrlLib/CtrlLib.h>
|
||||
|
||||
using namespace Upp;
|
||||
|
||||
struct MyApp : public TopWindow {
|
||||
void Paint(Draw& w) override {
|
||||
DrawPainter p(w, GetSize());
|
||||
p.Clear(White());
|
||||
p.Scale(22);
|
||||
p.Translate(5, 5);
|
||||
DLOG("===============");
|
||||
p.LineJoin(LINEJOIN_ROUND);
|
||||
p.RoundedRectangle(-2, -2, 100, 100, 5).Stroke(5, Blue());
|
||||
}
|
||||
};
|
||||
|
||||
GUI_APP_MAIN
|
||||
{
|
||||
MyApp().Run();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue