mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-08-22 06:12:32 -06:00
CtrlCore,Draw, POSIX: Fixed font metrics issue, fixed editfield frame issue, fixed PdfDraw
git-svn-id: svn://ultimatepp.org/upp/trunk@1480 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
d89a0903b9
commit
3ecde91bb5
13 changed files with 2081 additions and 2012 deletions
|
|
@ -7,11 +7,10 @@ NAMESPACE_UPP
|
|||
#define LTIMING(x)
|
||||
#define LLOG(x)
|
||||
|
||||
int gtk_antialias = -1;
|
||||
int gtk_hinting = -1;
|
||||
String gtk_hintstyle;
|
||||
String gtk_rgba;
|
||||
|
||||
extern int gtk_antialias;
|
||||
extern int gtk_hinting;
|
||||
extern String gtk_hintstyle;
|
||||
extern String gtk_rgba;
|
||||
extern int gtk_dpi;
|
||||
|
||||
XftFont *CreateXftFont(Font font, int angle)
|
||||
|
|
@ -22,15 +21,11 @@ XftFont *CreateXftFont(Font font, int angle)
|
|||
Std(font);
|
||||
int hg = abs(font.GetHeight());
|
||||
if(hg == 0) hg = 10;
|
||||
int i = font.GetFace();
|
||||
if(i < 0 || i >= Font::GetFaceCount())
|
||||
i = 0;
|
||||
String face = font.GetFaceName();
|
||||
FcPattern *p = FcPatternCreate();
|
||||
FcPatternAddString(p, FC_FAMILY, (FcChar8*)~face);
|
||||
FcPatternAddInteger(p, FC_SLANT, font.IsItalic() ? 110 : 0);
|
||||
FcPatternAddInteger(p, FC_PIXEL_SIZE, hg);
|
||||
FcPatternAddInteger(p, FC_DPI, gtk_dpi);
|
||||
FcPatternAddInteger(p, FC_WEIGHT, font.IsBold() ? 200 : 100);
|
||||
FcPatternAddBool(p, FC_MINSPACE, 1);
|
||||
if(angle) {
|
||||
|
|
@ -108,6 +103,53 @@ XftFont *GetXftFont(Font fnt, int angle)
|
|||
return be.xftfont;
|
||||
}
|
||||
|
||||
CommonFontInfo XftGetFontInfoSys(Font font)
|
||||
{
|
||||
CommonFontInfo fi;
|
||||
String path;
|
||||
XftFont *xftfont = GetXftFont(font, 0);
|
||||
if(xftfont) {
|
||||
fi.ascent = (int16)xftfont->ascent;
|
||||
fi.descent = (int16)xftfont->descent;
|
||||
fi.height = fi.ascent + fi.descent;
|
||||
fi.lineheight = (int16)xftfont->height;
|
||||
fi.external = 0;
|
||||
fi.internal = 0;
|
||||
fi.overhang = 0;
|
||||
fi.maxwidth = (int16)xftfont->max_advance_width;
|
||||
fi.avewidth = fi.maxwidth;
|
||||
fi.default_char = '?';
|
||||
fi.fixedpitch = font.GetFaceInfo() & Font::FIXEDPITCH;
|
||||
|
||||
char *fn = NULL;
|
||||
XftPatternGetString(xftfont->pattern, XFT_FILE, 0, &fn);
|
||||
if(fn && strlen(fn) < 250)
|
||||
strcpy(fi.path, fn);
|
||||
}
|
||||
return fi;
|
||||
}
|
||||
|
||||
GlyphInfo XftGetGlyphInfoSys(Font font, int chr)
|
||||
{
|
||||
wchar h = chr;
|
||||
XGlyphInfo info;
|
||||
XftTextExtents16(Xdisplay, GetXftFont(font, 0), &h, 1, &info);
|
||||
GlyphInfo gi;
|
||||
gi.width = info.xOff;
|
||||
gi.lspc = -info.x;
|
||||
gi.rspc = info.xOff - info.width + info.x;
|
||||
return gi;
|
||||
}
|
||||
|
||||
INITBLOCK {
|
||||
// extern FT_Face (*FTFaceXft)(Font fnt, String *rpath);
|
||||
extern CommonFontInfo (*GetFontInfoSysXft)(Font font);
|
||||
extern GlyphInfo (*GetGlyphInfoSysXft)(Font font, int chr);
|
||||
// FTFaceXft = XftFTFace;
|
||||
GetFontInfoSysXft = XftGetFontInfoSys;
|
||||
GetGlyphInfoSysXft = XftGetGlyphInfoSys;
|
||||
}
|
||||
|
||||
void SystemDraw::DrawTextOp(int x, int y, int angle, const wchar *text, Font font,
|
||||
Color ink, int n, const int *dx) {
|
||||
GuiLock __;
|
||||
|
|
|
|||
|
|
@ -577,11 +577,12 @@ String GtkStyleString(const char *name)
|
|||
return h;
|
||||
}
|
||||
|
||||
extern int gtk_dpi;
|
||||
extern int gtk_antialias;
|
||||
extern int gtk_hinting;
|
||||
extern String gtk_hintstyle;
|
||||
extern String gtk_rgba;
|
||||
int gtk_antialias = -1;
|
||||
int gtk_hinting;
|
||||
String gtk_hintstyle;
|
||||
String gtk_rgba;
|
||||
|
||||
extern void ClearFtFaceCache();
|
||||
|
||||
void ChHostSkin()
|
||||
{
|
||||
|
|
@ -623,7 +624,6 @@ void ChHostSkin()
|
|||
|
||||
String font_name = GtkStyleString("gtk-font-name");
|
||||
int xdpi = Nvl(GtkStyleInt("gtk-xft-dpi"), 72 * 1024);
|
||||
gtk_dpi = xdpi / 1024;
|
||||
gtk_antialias = Nvl(GtkStyleInt("gtk-xft-antialias"), -1);
|
||||
gtk_hinting = Nvl(GtkStyleInt("gtk-xft-hinting"), -1);
|
||||
// gtk_hintstyle = GtkStyleString("gtk-xft-hintstyle");
|
||||
|
|
@ -670,6 +670,8 @@ void ChHostSkin()
|
|||
Draw::SetStdFont(Font(fontname, (fontheight * xdpi + 512*72) / (1024*72))
|
||||
.Bold(bold).Italic(italic));
|
||||
|
||||
ClearFtFaceCache();
|
||||
|
||||
ColoredOverride(CtrlsImg::Iml(), CtrlsImg::Iml());
|
||||
|
||||
Color fc = Blend(SColorHighlight, SColorShadow);
|
||||
|
|
@ -1255,6 +1257,8 @@ void ChHostSkin()
|
|||
GUI_DropShadows_Write(1);
|
||||
GUI_AltAccessKeys_Write(1);
|
||||
GUI_AKD_Conservative_Write(0);
|
||||
|
||||
ClearFtFaceCache();
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ public:
|
|||
Color selected, selectedtext;
|
||||
Value edge[4];
|
||||
bool activeedge;
|
||||
int vfm;
|
||||
};
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -67,9 +67,18 @@ int TextArrayOps::GetPrevWord(int cursor)
|
|||
return c;
|
||||
}
|
||||
|
||||
Rect LookMargins(const Rect& r, const Value& ch)
|
||||
{
|
||||
Rect m = ChMargins(ch);
|
||||
int fcy = GetStdFontCy();
|
||||
if(m.top + m.bottom + fcy > r.GetHeight())
|
||||
m.top = m.bottom = max((r.GetHeight() - fcy) / 2, 0);
|
||||
return m;
|
||||
}
|
||||
|
||||
void LookFrame::FrameLayout(Rect& r)
|
||||
{
|
||||
Rect m = ChMargins(Get());
|
||||
Rect m = LookMargins(r, Get());
|
||||
r.left += m.left;
|
||||
r.right -= m.right;
|
||||
r.top += m.top;
|
||||
|
|
@ -90,7 +99,7 @@ void LookFrame::FrameAddSize(Size& sz)
|
|||
|
||||
void ActiveEdgeFrame::FrameLayout(Rect& r)
|
||||
{
|
||||
Rect m = ChMargins(edge[0]);
|
||||
Rect m = LookMargins(r, edge[0]);
|
||||
r.left += m.left;
|
||||
r.right -= m.right;
|
||||
r.top += m.top;
|
||||
|
|
@ -135,6 +144,7 @@ CH_STYLE(EditField, Style, StyleDefault)
|
|||
for(int i = 0; i < 4; i++)
|
||||
edge[i] = CtrlsImg::EFE();
|
||||
activeedge = false;
|
||||
vfm = 2;
|
||||
}
|
||||
|
||||
bool EditField::FrameIsEdge()
|
||||
|
|
|
|||
|
|
@ -1,321 +1,321 @@
|
|||
#include "Draw.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
#define IMAGECLASS DrawImg
|
||||
#define IMAGEFILE <Draw/DrawImg.iml>
|
||||
#include <Draw/iml.h>
|
||||
|
||||
#define LLOG(x) // RLOG(x)
|
||||
|
||||
AttrText::operator Value() const
|
||||
{
|
||||
return RawToValue(*this);
|
||||
}
|
||||
|
||||
void AttrText::Init()
|
||||
{
|
||||
ink = Null;
|
||||
paper = Null;
|
||||
font = Null;
|
||||
align = Null;
|
||||
}
|
||||
|
||||
AttrText::AttrText(const char *_text)
|
||||
{
|
||||
text = _text;
|
||||
Init();
|
||||
}
|
||||
|
||||
AttrText::AttrText(const wchar *_text)
|
||||
{
|
||||
text = _text;
|
||||
Init();
|
||||
}
|
||||
|
||||
AttrText::AttrText(const WString& _text)
|
||||
{
|
||||
text = _text;
|
||||
Init();
|
||||
}
|
||||
|
||||
class StdDisplayClass : public Display
|
||||
{
|
||||
public:
|
||||
StdDisplayClass(int align = ALIGN_LEFT) : align(align) {}
|
||||
|
||||
virtual void Paint0(Draw& draw, const Rect& rc, const Value& v, Color ink, Color paper, dword style) const;
|
||||
virtual void Paint(Draw& draw, const Rect& rc, const Value& v, Color ink, Color paper, dword style) const;
|
||||
virtual Size GetStdSize(const Value& q) const;
|
||||
|
||||
private:
|
||||
int align;
|
||||
};
|
||||
|
||||
void Display::PaintBackground(Draw& w, const Rect& r, const Value& q,
|
||||
Color ink, Color paper, dword style) const
|
||||
{
|
||||
if(IsType<AttrText>(q)) {
|
||||
const AttrText& t = ValueTo<AttrText>(q);
|
||||
if(!IsNull(t.paper))
|
||||
paper = t.paper;
|
||||
}
|
||||
w.DrawRect(r, paper);
|
||||
}
|
||||
|
||||
void Display::Paint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const
|
||||
{
|
||||
StdDisplay().Paint(w, r, q, ink, paper, style);
|
||||
}
|
||||
|
||||
Size Display::RatioSize(const Value& q, int cx, int cy) const {
|
||||
return Size(cx, cy);
|
||||
}
|
||||
|
||||
Size Display::GetStdSize(const Value& q) const
|
||||
{
|
||||
return Size(8, 8);
|
||||
}
|
||||
|
||||
void StdDisplayClass::Paint0(Draw& w, const Rect& r, const Value& q,
|
||||
Color ink, Color paper, dword s) const {
|
||||
LLOG("Display::Paint0: " << q << " ink:" << ink << " paper:" << paper);
|
||||
WString txt;
|
||||
Font font = StdFont();
|
||||
int a = align;
|
||||
if(IsType<AttrText>(q)) {
|
||||
const AttrText& t = ValueTo<AttrText>(q);
|
||||
txt = t.text;
|
||||
if(!IsNull(t.paper))
|
||||
paper = t.paper;
|
||||
if(!IsNull(t.ink))
|
||||
ink = t.ink;
|
||||
if(!IsNull(t.font))
|
||||
font = t.font;
|
||||
if(!IsNull(t.align))
|
||||
a = t.align;
|
||||
}
|
||||
else
|
||||
txt = IsString(q) ? q : StdConvert().Format(q);
|
||||
int x = r.left;
|
||||
Size tsz = GetTLTextSize(txt, font);
|
||||
if(a == ALIGN_RIGHT)
|
||||
x = r.right - tsz.cx;
|
||||
if(a == ALIGN_CENTER)
|
||||
x += (r.Width() - tsz.cx) / 2;
|
||||
int tcy = GetTLTextHeight(txt, font);
|
||||
int tt = r.top + max((r.Height() - tcy) / 2, 0);
|
||||
if(tsz.cx > r.GetWidth()) {
|
||||
Size isz = DrawImg::threedots().GetSize();
|
||||
int wd = r.GetWidth() - isz.cx;
|
||||
w.Clip(r.left, r.top, wd, r.GetHeight());
|
||||
DrawTLText(w, x, tt, r.Width(), txt, font, ink);
|
||||
w.End();
|
||||
w.DrawImage(r.left + wd, tt + font.Info().GetAscent() - isz.cy, DrawImg::threedots(), ink);
|
||||
}
|
||||
else
|
||||
DrawTLText(w, x, tt, r.Width(), txt, font, ink);
|
||||
}
|
||||
|
||||
void StdDisplayClass::Paint(Draw& w, const Rect& r, const Value& q,
|
||||
Color ink, Color paper, dword s) const {
|
||||
LLOG("Display::Paint: " << q << " ink:" << ink << " paper:" << paper);
|
||||
PaintBackground(w, r, q, ink, paper, s);
|
||||
Paint0(w, r, q, ink, paper, s);
|
||||
}
|
||||
|
||||
Size StdDisplayClass::GetStdSize(const Value& q) const
|
||||
{
|
||||
Font font = StdFont();
|
||||
WString txt;
|
||||
if(IsType<AttrText>(q)) {
|
||||
const AttrText& t = ValueTo<AttrText>(q);
|
||||
txt = t.text;
|
||||
if(!IsNull(t.font))
|
||||
font = t.font;
|
||||
}
|
||||
else
|
||||
txt = IsString(q) ? q : StdConvert().Format(q);
|
||||
return GetTLTextSize(txt, font);
|
||||
}
|
||||
|
||||
#ifdef flagSO
|
||||
Display::Display() {}
|
||||
#endif
|
||||
|
||||
Display::~Display() {}
|
||||
|
||||
const Display& GLOBAL_V_INIT(StdDisplayClass, StdDisplay)
|
||||
const Display& GLOBAL_VP_INIT(StdDisplayClass, StdCenterDisplay, (ALIGN_CENTER))
|
||||
const Display& GLOBAL_VP_INIT(StdDisplayClass, StdRightDisplay, (ALIGN_RIGHT))
|
||||
|
||||
#ifdef flagSO
|
||||
ColorDisplayNull::ColorDisplayNull(String nulltext) : nulltext(nulltext) {}
|
||||
ColorDisplayNull::~ColorDisplayNull() {}
|
||||
#endif
|
||||
|
||||
void ColorDisplayNull::Paint(Draw& w, const Rect& r, const Value& q,
|
||||
Color ink, Color paper, dword style) const
|
||||
{
|
||||
if(IsNull(q))
|
||||
StdDisplay().Paint(w, r, nulltext, ink, paper, style);
|
||||
else
|
||||
w.DrawRect(r, Color(q));
|
||||
}
|
||||
|
||||
const Display& ColorDisplay() { return Single<ColorDisplayNull>(); }
|
||||
|
||||
class SizeTextDisplayCls : public Display {
|
||||
public:
|
||||
virtual void Paint(Draw& w, const Rect& r, const Value& q,
|
||||
Color ink, Color paper, dword style) const;
|
||||
};
|
||||
|
||||
void SizeTextDisplayCls::Paint(Draw& w, const Rect& r, const Value& q,
|
||||
Color ink, Color, dword) const {
|
||||
w.DrawText(r.left, r.top, r.Width(), (String)q, Arial(-r.Height()), ink);
|
||||
}
|
||||
|
||||
const Display& SizeTextDisplay() { return Single<SizeTextDisplayCls>(); }
|
||||
|
||||
static inline int NScale(int sz, int r) {
|
||||
return sz ? sz < r ? r / sz * sz : r : 0;
|
||||
}
|
||||
|
||||
class CenteredImageDisplayCls : public Display {
|
||||
public:
|
||||
virtual void Paint(Draw& w, const Rect& r, const Value& q,
|
||||
Color ink, Color paper, dword style) const
|
||||
{
|
||||
w.DrawRect(r, paper);
|
||||
Image m = q;
|
||||
Size sz = m.GetSize();
|
||||
if(!IsNull(m))
|
||||
w.DrawImage(r.left + (r.Width() - sz.cx) / 2, r.top + (r.Height() - sz.cy) / 2, m);
|
||||
}
|
||||
virtual Size GetStdSize(const Value& q) const
|
||||
{
|
||||
return Image(q).GetSize();
|
||||
}
|
||||
};
|
||||
|
||||
const Display& CenteredImageDisplay() { return Single<CenteredImageDisplayCls>(); }
|
||||
|
||||
class CenteredHighlightImageDisplayCls : public Display {
|
||||
public:
|
||||
virtual void Paint(Draw& w, const Rect& r, const Value& q,
|
||||
Color ink, Color paper, dword style) const
|
||||
{
|
||||
w.DrawRect(r, paper);
|
||||
Image m = q;
|
||||
Size sz = m.GetSize();
|
||||
if(!IsNull(m))
|
||||
DrawHighlightImage(w, r.left + (r.Width() - sz.cx) / 2,
|
||||
r.top + (r.Height() - sz.cy) / 2, m);
|
||||
}
|
||||
virtual Size GetStdSize(const Value& q) const
|
||||
{
|
||||
return Image(q).GetSize();
|
||||
}
|
||||
};
|
||||
|
||||
const Display& CenteredHighlightImageDisplay()
|
||||
{
|
||||
return Single<CenteredHighlightImageDisplayCls>();
|
||||
}
|
||||
|
||||
class ImageDisplayCls : public Display {
|
||||
public:
|
||||
virtual void Paint(Draw& w, const Rect& r, const Value& q,
|
||||
Color ink, Color paper, dword style) const
|
||||
{
|
||||
w.DrawRect(r, paper);
|
||||
Image m = q;
|
||||
if(!IsNull(m))
|
||||
w.DrawImage(r.left, r.top, Rescale(m, r.GetSize()));
|
||||
}
|
||||
virtual Size GetStdSize(const Value& q) const
|
||||
{
|
||||
return Image(q).GetSize();
|
||||
}
|
||||
};
|
||||
|
||||
const Display& ImageDisplay() { return Single<ImageDisplayCls>(); }
|
||||
|
||||
class FittedImageDisplayCls : public Display {
|
||||
public:
|
||||
virtual void Paint(Draw& w, const Rect& r, const Value& q,
|
||||
Color ink, Color paper, dword style) const
|
||||
{
|
||||
w.DrawRect(r, paper);
|
||||
Image m = q;
|
||||
if(!IsNull(m)) {
|
||||
Size sz = GetFitSize(m.GetSize(), r.Size());
|
||||
Point p = r.CenterPos(sz);
|
||||
w.DrawImage(p.x, p.y, m);
|
||||
}
|
||||
}
|
||||
virtual Size GetStdSize(const Value& q) const
|
||||
{
|
||||
return Image(q).GetSize();
|
||||
}
|
||||
};
|
||||
|
||||
const Display& FittedImageDisplay() { return Single<FittedImageDisplayCls>(); }
|
||||
|
||||
class DrawingDisplayCls : public Display {
|
||||
public:
|
||||
virtual void Paint(Draw& w, const Rect& r, const Value& q,
|
||||
Color ink, Color paper, dword style) const;
|
||||
virtual Size GetStdSize(const Value& q) const;
|
||||
virtual Size RatioSize(const Value& q, int cx, int cy) const;
|
||||
};
|
||||
|
||||
void DrawingDisplayCls::Paint(Draw& w, const Rect& r, const Value& q,
|
||||
Color, Color, dword) const {
|
||||
w.DrawDrawing(r, q);
|
||||
}
|
||||
|
||||
Size DrawingDisplayCls::GetStdSize(const Value& q) const {
|
||||
return ((const Drawing&) q).GetSize();
|
||||
}
|
||||
|
||||
Size DrawingDisplayCls::RatioSize(const Value& q, int cx, int cy) const {
|
||||
return ((const Drawing&) q).RatioSize(cx, cy);
|
||||
}
|
||||
|
||||
const Display& DrawingDisplay() { return Single<DrawingDisplayCls>(); }
|
||||
|
||||
Size PaintRect::GetStdSize() const {
|
||||
return display ? display->GetStdSize(value) : Size(0, 0);
|
||||
}
|
||||
|
||||
Size PaintRect::RatioSize(int cx, int cy) const {
|
||||
return display ? display->RatioSize(value, cx, cy) : Size(0, 0);
|
||||
}
|
||||
|
||||
void PaintRect::Paint(Draw& w, const Rect& r,
|
||||
Color ink, Color paper, dword style) const {
|
||||
if(display)
|
||||
display->Paint(w, r, value, ink, paper, style);
|
||||
}
|
||||
|
||||
void PaintRect::Paint(Draw& w, int x, int y, int cx, int cy,
|
||||
Color ink, Color paper, dword style) const {
|
||||
Paint(w, RectC(x, y, cx, cy), ink, paper, style);
|
||||
}
|
||||
|
||||
PaintRect::PaintRect() {
|
||||
display = NULL;
|
||||
}
|
||||
|
||||
PaintRect::PaintRect(const Display& _display) {
|
||||
display = &_display;
|
||||
}
|
||||
|
||||
PaintRect::PaintRect(const Display& _display, const Value& _val) {
|
||||
display = &_display;
|
||||
value = _val;
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
#include "Draw.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
#define IMAGECLASS DrawImg
|
||||
#define IMAGEFILE <Draw/DrawImg.iml>
|
||||
#include <Draw/iml.h>
|
||||
|
||||
#define LLOG(x) // RLOG(x)
|
||||
|
||||
AttrText::operator Value() const
|
||||
{
|
||||
return RawToValue(*this);
|
||||
}
|
||||
|
||||
void AttrText::Init()
|
||||
{
|
||||
ink = Null;
|
||||
paper = Null;
|
||||
font = Null;
|
||||
align = Null;
|
||||
}
|
||||
|
||||
AttrText::AttrText(const char *_text)
|
||||
{
|
||||
text = _text;
|
||||
Init();
|
||||
}
|
||||
|
||||
AttrText::AttrText(const wchar *_text)
|
||||
{
|
||||
text = _text;
|
||||
Init();
|
||||
}
|
||||
|
||||
AttrText::AttrText(const WString& _text)
|
||||
{
|
||||
text = _text;
|
||||
Init();
|
||||
}
|
||||
|
||||
class StdDisplayClass : public Display
|
||||
{
|
||||
public:
|
||||
StdDisplayClass(int align = ALIGN_LEFT) : align(align) {}
|
||||
|
||||
virtual void Paint0(Draw& draw, const Rect& rc, const Value& v, Color ink, Color paper, dword style) const;
|
||||
virtual void Paint(Draw& draw, const Rect& rc, const Value& v, Color ink, Color paper, dword style) const;
|
||||
virtual Size GetStdSize(const Value& q) const;
|
||||
|
||||
private:
|
||||
int align;
|
||||
};
|
||||
|
||||
void Display::PaintBackground(Draw& w, const Rect& r, const Value& q,
|
||||
Color ink, Color paper, dword style) const
|
||||
{
|
||||
if(IsType<AttrText>(q)) {
|
||||
const AttrText& t = ValueTo<AttrText>(q);
|
||||
if(!IsNull(t.paper))
|
||||
paper = t.paper;
|
||||
}
|
||||
w.DrawRect(r, paper);
|
||||
}
|
||||
|
||||
void Display::Paint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const
|
||||
{
|
||||
StdDisplay().Paint(w, r, q, ink, paper, style);
|
||||
}
|
||||
|
||||
Size Display::RatioSize(const Value& q, int cx, int cy) const {
|
||||
return Size(cx, cy);
|
||||
}
|
||||
|
||||
Size Display::GetStdSize(const Value& q) const
|
||||
{
|
||||
return Size(8, 8);
|
||||
}
|
||||
|
||||
void StdDisplayClass::Paint0(Draw& w, const Rect& r, const Value& q,
|
||||
Color ink, Color paper, dword s) const {
|
||||
LLOG("Display::Paint0: " << q << " ink:" << ink << " paper:" << paper);
|
||||
WString txt;
|
||||
Font font = StdFont();
|
||||
int a = align;
|
||||
if(IsType<AttrText>(q)) {
|
||||
const AttrText& t = ValueTo<AttrText>(q);
|
||||
txt = t.text;
|
||||
if(!IsNull(t.paper))
|
||||
paper = t.paper;
|
||||
if(!IsNull(t.ink))
|
||||
ink = t.ink;
|
||||
if(!IsNull(t.font))
|
||||
font = t.font;
|
||||
if(!IsNull(t.align))
|
||||
a = t.align;
|
||||
}
|
||||
else
|
||||
txt = IsString(q) ? q : StdConvert().Format(q);
|
||||
int x = r.left;
|
||||
Size tsz = GetTLTextSize(txt, font);
|
||||
if(a == ALIGN_RIGHT)
|
||||
x = r.right - tsz.cx;
|
||||
if(a == ALIGN_CENTER)
|
||||
x += (r.Width() - tsz.cx) / 2;
|
||||
int tcy = GetTLTextHeight(txt, font);
|
||||
int tt = r.top + max((r.Height() - tcy) / 2, 0);
|
||||
if(tsz.cx > r.GetWidth()) {
|
||||
Size isz = DrawImg::threedots().GetSize();
|
||||
int wd = r.GetWidth() - isz.cx;
|
||||
w.Clip(r.left, r.top, wd, r.GetHeight());
|
||||
DrawTLText(w, x, tt, r.Width(), txt, font, ink);
|
||||
w.End();
|
||||
w.DrawImage(r.left + wd, tt + font.Info().GetAscent() - isz.cy, DrawImg::threedots(), ink);
|
||||
}
|
||||
else
|
||||
DrawTLText(w, x, tt, r.Width(), txt, font, ink);
|
||||
}
|
||||
|
||||
void StdDisplayClass::Paint(Draw& w, const Rect& r, const Value& q,
|
||||
Color ink, Color paper, dword s) const {
|
||||
LLOG("Display::Paint: " << q << " ink:" << ink << " paper:" << paper);
|
||||
PaintBackground(w, r, q, ink, paper, s);
|
||||
Paint0(w, r, q, ink, paper, s);
|
||||
}
|
||||
|
||||
Size StdDisplayClass::GetStdSize(const Value& q) const
|
||||
{
|
||||
Font font = StdFont();
|
||||
WString txt;
|
||||
if(IsType<AttrText>(q)) {
|
||||
const AttrText& t = ValueTo<AttrText>(q);
|
||||
txt = t.text;
|
||||
if(!IsNull(t.font))
|
||||
font = t.font;
|
||||
}
|
||||
else
|
||||
txt = IsString(q) ? q : StdConvert().Format(q);
|
||||
return GetTLTextSize(txt, font);
|
||||
}
|
||||
|
||||
#ifdef flagSO
|
||||
Display::Display() {}
|
||||
#endif
|
||||
|
||||
Display::~Display() {}
|
||||
|
||||
const Display& GLOBAL_V_INIT(StdDisplayClass, StdDisplay)
|
||||
const Display& GLOBAL_VP_INIT(StdDisplayClass, StdCenterDisplay, (ALIGN_CENTER))
|
||||
const Display& GLOBAL_VP_INIT(StdDisplayClass, StdRightDisplay, (ALIGN_RIGHT))
|
||||
|
||||
#ifdef flagSO
|
||||
ColorDisplayNull::ColorDisplayNull(String nulltext) : nulltext(nulltext) {}
|
||||
ColorDisplayNull::~ColorDisplayNull() {}
|
||||
#endif
|
||||
|
||||
void ColorDisplayNull::Paint(Draw& w, const Rect& r, const Value& q,
|
||||
Color ink, Color paper, dword style) const
|
||||
{
|
||||
if(IsNull(q))
|
||||
StdDisplay().Paint(w, r, nulltext, ink, paper, style);
|
||||
else
|
||||
w.DrawRect(r, Color(q));
|
||||
}
|
||||
|
||||
const Display& ColorDisplay() { return Single<ColorDisplayNull>(); }
|
||||
|
||||
class SizeTextDisplayCls : public Display {
|
||||
public:
|
||||
virtual void Paint(Draw& w, const Rect& r, const Value& q,
|
||||
Color ink, Color paper, dword style) const;
|
||||
};
|
||||
|
||||
void SizeTextDisplayCls::Paint(Draw& w, const Rect& r, const Value& q,
|
||||
Color ink, Color, dword) const {
|
||||
w.DrawText(r.left, r.top, r.Width(), (String)q, Arial(-r.Height()), ink);
|
||||
}
|
||||
|
||||
const Display& SizeTextDisplay() { return Single<SizeTextDisplayCls>(); }
|
||||
|
||||
static inline int NScale(int sz, int r) {
|
||||
return sz ? sz < r ? r / sz * sz : r : 0;
|
||||
}
|
||||
|
||||
class CenteredImageDisplayCls : public Display {
|
||||
public:
|
||||
virtual void Paint(Draw& w, const Rect& r, const Value& q,
|
||||
Color ink, Color paper, dword style) const
|
||||
{
|
||||
w.DrawRect(r, paper);
|
||||
Image m = q;
|
||||
Size sz = m.GetSize();
|
||||
if(!IsNull(m))
|
||||
w.DrawImage(r.left + (r.Width() - sz.cx) / 2, r.top + (r.Height() - sz.cy) / 2, m);
|
||||
}
|
||||
virtual Size GetStdSize(const Value& q) const
|
||||
{
|
||||
return Image(q).GetSize();
|
||||
}
|
||||
};
|
||||
|
||||
const Display& CenteredImageDisplay() { return Single<CenteredImageDisplayCls>(); }
|
||||
|
||||
class CenteredHighlightImageDisplayCls : public Display {
|
||||
public:
|
||||
virtual void Paint(Draw& w, const Rect& r, const Value& q,
|
||||
Color ink, Color paper, dword style) const
|
||||
{
|
||||
w.DrawRect(r, paper);
|
||||
Image m = q;
|
||||
Size sz = m.GetSize();
|
||||
if(!IsNull(m))
|
||||
DrawHighlightImage(w, r.left + (r.Width() - sz.cx) / 2,
|
||||
r.top + (r.Height() - sz.cy) / 2, m);
|
||||
}
|
||||
virtual Size GetStdSize(const Value& q) const
|
||||
{
|
||||
return Image(q).GetSize();
|
||||
}
|
||||
};
|
||||
|
||||
const Display& CenteredHighlightImageDisplay()
|
||||
{
|
||||
return Single<CenteredHighlightImageDisplayCls>();
|
||||
}
|
||||
|
||||
class ImageDisplayCls : public Display {
|
||||
public:
|
||||
virtual void Paint(Draw& w, const Rect& r, const Value& q,
|
||||
Color ink, Color paper, dword style) const
|
||||
{
|
||||
w.DrawRect(r, paper);
|
||||
Image m = q;
|
||||
if(!IsNull(m))
|
||||
w.DrawImage(r.left, r.top, Rescale(m, r.GetSize()));
|
||||
}
|
||||
virtual Size GetStdSize(const Value& q) const
|
||||
{
|
||||
return Image(q).GetSize();
|
||||
}
|
||||
};
|
||||
|
||||
const Display& ImageDisplay() { return Single<ImageDisplayCls>(); }
|
||||
|
||||
class FittedImageDisplayCls : public Display {
|
||||
public:
|
||||
virtual void Paint(Draw& w, const Rect& r, const Value& q,
|
||||
Color ink, Color paper, dword style) const
|
||||
{
|
||||
w.DrawRect(r, paper);
|
||||
Image m = q;
|
||||
if(!IsNull(m)) {
|
||||
Size sz = GetFitSize(m.GetSize(), r.Size());
|
||||
Point p = r.CenterPos(sz);
|
||||
w.DrawImage(p.x, p.y, m);
|
||||
}
|
||||
}
|
||||
virtual Size GetStdSize(const Value& q) const
|
||||
{
|
||||
return Image(q).GetSize();
|
||||
}
|
||||
};
|
||||
|
||||
const Display& FittedImageDisplay() { return Single<FittedImageDisplayCls>(); }
|
||||
|
||||
class DrawingDisplayCls : public Display {
|
||||
public:
|
||||
virtual void Paint(Draw& w, const Rect& r, const Value& q,
|
||||
Color ink, Color paper, dword style) const;
|
||||
virtual Size GetStdSize(const Value& q) const;
|
||||
virtual Size RatioSize(const Value& q, int cx, int cy) const;
|
||||
};
|
||||
|
||||
void DrawingDisplayCls::Paint(Draw& w, const Rect& r, const Value& q,
|
||||
Color, Color, dword) const {
|
||||
w.DrawDrawing(r, q);
|
||||
}
|
||||
|
||||
Size DrawingDisplayCls::GetStdSize(const Value& q) const {
|
||||
return ((const Drawing&) q).GetSize();
|
||||
}
|
||||
|
||||
Size DrawingDisplayCls::RatioSize(const Value& q, int cx, int cy) const {
|
||||
return ((const Drawing&) q).RatioSize(cx, cy);
|
||||
}
|
||||
|
||||
const Display& DrawingDisplay() { return Single<DrawingDisplayCls>(); }
|
||||
|
||||
Size PaintRect::GetStdSize() const {
|
||||
return display ? display->GetStdSize(value) : Size(0, 0);
|
||||
}
|
||||
|
||||
Size PaintRect::RatioSize(int cx, int cy) const {
|
||||
return display ? display->RatioSize(value, cx, cy) : Size(0, 0);
|
||||
}
|
||||
|
||||
void PaintRect::Paint(Draw& w, const Rect& r,
|
||||
Color ink, Color paper, dword style) const {
|
||||
if(display)
|
||||
display->Paint(w, r, value, ink, paper, style);
|
||||
}
|
||||
|
||||
void PaintRect::Paint(Draw& w, int x, int y, int cx, int cy,
|
||||
Color ink, Color paper, dword style) const {
|
||||
Paint(w, RectC(x, y, cx, cy), ink, paper, style);
|
||||
}
|
||||
|
||||
PaintRect::PaintRect() {
|
||||
display = NULL;
|
||||
}
|
||||
|
||||
PaintRect::PaintRect(const Display& _display) {
|
||||
display = &_display;
|
||||
}
|
||||
|
||||
PaintRect::PaintRect(const Display& _display, const Value& _val) {
|
||||
display = &_display;
|
||||
value = _val;
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -1,193 +1,193 @@
|
|||
#include "Draw.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
|
||||
#define LLOG(x) // LOG(x)
|
||||
#define LTIMING(x) // TIMING(x)
|
||||
|
||||
WString TextUnicode(const char *s, int n, byte cs, Font font)
|
||||
{
|
||||
if(n < 0)
|
||||
n = (int)strlen(s);
|
||||
#ifdef PLATFORM_WIN32
|
||||
if(font.GetFace() == Font::SYMBOL) {
|
||||
WStringBuffer b(n);
|
||||
wchar *t = b;
|
||||
while(n > 0) {
|
||||
*t++ = *s++;
|
||||
n--;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
#endif
|
||||
return ToUnicode(s, n, cs);
|
||||
}
|
||||
|
||||
void Draw::DrawText(int x, int y, int angle, const wchar *text, Font font,
|
||||
Color ink, int n, const int *dx)
|
||||
{
|
||||
if(IsNull(ink)) return;
|
||||
if(n < 0)
|
||||
n = wstrlen(text);
|
||||
Std(font);
|
||||
double sina;
|
||||
double cosa;
|
||||
int d = 0;
|
||||
if(angle)
|
||||
Draw::SinCos(angle, sina, cosa);
|
||||
for(int i = 0; i < n; i++) {
|
||||
wchar chr = text[i];
|
||||
GlyphInfo gi = GetGlyphInfo(font, chr);
|
||||
if(gi.IsNormal())
|
||||
if(angle)
|
||||
DrawTextOp(int(x + cosa * d), int(y - sina * d), angle, &chr, font, ink, 1, NULL);
|
||||
else {
|
||||
int c = 1;
|
||||
int dd = 0;
|
||||
while(c < n) {
|
||||
GlyphInfo gi2 = GetGlyphInfo(font, text[i + c]);
|
||||
if(!gi2.IsNormal())
|
||||
break;
|
||||
dd += dx ? dx[c] : gi.width;
|
||||
c++;
|
||||
gi = gi2;
|
||||
}
|
||||
DrawTextOp(x + d, y, 0, text + i, font, ink, c, dx);
|
||||
d += dd;
|
||||
i += c - 1;
|
||||
if(dx)
|
||||
dx += c - 1;
|
||||
}
|
||||
else
|
||||
if(gi.IsReplaced()) {
|
||||
Font fnt = font;
|
||||
fnt.Face(gi.lspc);
|
||||
fnt.Height(gi.rspc);
|
||||
if(angle)
|
||||
DrawTextOp(int(x + cosa * d), int(y - sina * (font.GetAscent() - fnt.GetAscent() + d)),
|
||||
angle, &chr, fnt, ink, 1, NULL);
|
||||
else
|
||||
DrawTextOp(x + d, y + font.GetAscent() - fnt.GetAscent(), 0, &chr, fnt, ink, 1, NULL);
|
||||
GlyphMetrics(gi, font, chr);
|
||||
}
|
||||
else
|
||||
if(gi.IsComposed()) {
|
||||
ComposedGlyph cg;
|
||||
Compose(font, chr, cg);
|
||||
if(angle) {
|
||||
DrawTextOp(int(x + cosa * d), int(y - sina * d), angle, &cg.basic_char, font, ink, 1, NULL);
|
||||
DrawTextOp(int(x + cosa * (d + cg.mark_pos.x)), int(y - sina * (cg.mark_pos.y + d)), angle, &cg.mark_char, cg.mark_font, ink, 1, NULL);
|
||||
}
|
||||
else {
|
||||
DrawTextOp(x + d, y, 0, &cg.basic_char, font, ink, 1, NULL);
|
||||
DrawTextOp(x + cg.mark_pos.x + d, y + cg.mark_pos.y, 0, &cg.mark_char, cg.mark_font, ink, 1, NULL);
|
||||
}
|
||||
GlyphMetrics(gi, font, chr);
|
||||
}
|
||||
d += dx ? *dx++ : gi.width;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------
|
||||
|
||||
void Draw::DrawText(int x, int y, const wchar *text, Font font,
|
||||
Color ink, int n, const int *dx)
|
||||
{
|
||||
DrawText(x, y, 0, text, font, ink, n, dx);
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
|
||||
void Draw::DrawText(int x, int y, int angle, const WString& text, Font font,
|
||||
Color ink, const int *dx)
|
||||
{
|
||||
DrawText(x, y, angle, ~text, font, ink, text.GetLength(), dx);
|
||||
}
|
||||
|
||||
void Draw::DrawText(int x, int y, const WString& text, Font font, Color ink, const int *dx)
|
||||
{
|
||||
DrawText(x, y, 0, text, font, ink, dx);
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
|
||||
void Draw::DrawText(int x, int y, int angle, const char *text, byte charset, Font font,
|
||||
Color ink, int n, const int *dx)
|
||||
{
|
||||
DrawText(x, y, angle, TextUnicode(text, n, charset, font), font, ink, dx);
|
||||
}
|
||||
|
||||
void Draw::DrawText(int x, int y, const char *text, byte charset, Font font,
|
||||
Color ink, int n, const int *dx)
|
||||
{
|
||||
DrawText(x, y, 0, text, charset, font, ink, n, dx);
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
|
||||
void Draw::DrawText(int x, int y, int angle, const char *text,
|
||||
Font font, Color ink, int n, const int *dx)
|
||||
{
|
||||
DrawText(x, y, angle, text, CHARSET_DEFAULT, font, ink, n, dx);
|
||||
}
|
||||
|
||||
void Draw::DrawText(int x, int y, const char *text, Font font,
|
||||
Color ink, int n, const int *dx)
|
||||
{
|
||||
DrawText(x, y, text, CHARSET_DEFAULT, font, ink, n, dx);
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
|
||||
void Draw::DrawText(int x, int y, int angle, const String& text, Font font,
|
||||
Color ink, const int *dx)
|
||||
{
|
||||
DrawText(x, y, angle, text, font, ink, text.GetLength(), dx);
|
||||
}
|
||||
|
||||
void Draw::DrawText(int x, int y, const String& text, Font font, Color ink, const int *dx)
|
||||
{
|
||||
WString h = TextUnicode(text, text.GetLength(), CHARSET_DEFAULT, font);
|
||||
DrawText(x, y, h, font, ink, h.GetLength(), dx);
|
||||
}
|
||||
|
||||
// --------------------------
|
||||
|
||||
Size GetTextSize(const wchar *text, Font font, int n)
|
||||
{
|
||||
FontInfo fi = font.Info();
|
||||
if(n < 0)
|
||||
n = wstrlen(text);
|
||||
Size sz;
|
||||
sz.cx = 0;
|
||||
const wchar *wtext = (const wchar *)text;
|
||||
while(n > 0) {
|
||||
sz.cx += fi[*wtext++];
|
||||
n--;
|
||||
}
|
||||
sz.cy = fi.GetHeight();
|
||||
return sz;
|
||||
}
|
||||
|
||||
Size GetTextSize(const WString& text, Font font)
|
||||
{
|
||||
return GetTextSize(text, font, text.GetLength());
|
||||
}
|
||||
|
||||
Size GetTextSize(const char *text, byte charset, Font font, int n)
|
||||
{
|
||||
return GetTextSize(TextUnicode(text, n, charset, font), font);
|
||||
}
|
||||
|
||||
Size GetTextSize(const char *text, Font font, int n)
|
||||
{
|
||||
return GetTextSize(text, CHARSET_DEFAULT, font, n);
|
||||
}
|
||||
|
||||
Size GetTextSize(const String& text, Font font)
|
||||
{
|
||||
return GetTextSize(text, font, text.GetLength());
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
#include "Draw.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
|
||||
#define LLOG(x) // LOG(x)
|
||||
#define LTIMING(x) // TIMING(x)
|
||||
|
||||
WString TextUnicode(const char *s, int n, byte cs, Font font)
|
||||
{
|
||||
if(n < 0)
|
||||
n = (int)strlen(s);
|
||||
#ifdef PLATFORM_WIN32
|
||||
if(font.GetFace() == Font::SYMBOL) {
|
||||
WStringBuffer b(n);
|
||||
wchar *t = b;
|
||||
while(n > 0) {
|
||||
*t++ = *s++;
|
||||
n--;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
#endif
|
||||
return ToUnicode(s, n, cs);
|
||||
}
|
||||
|
||||
void Draw::DrawText(int x, int y, int angle, const wchar *text, Font font,
|
||||
Color ink, int n, const int *dx)
|
||||
{
|
||||
if(IsNull(ink)) return;
|
||||
if(n < 0)
|
||||
n = wstrlen(text);
|
||||
Std(font);
|
||||
double sina;
|
||||
double cosa;
|
||||
int d = 0;
|
||||
if(angle)
|
||||
Draw::SinCos(angle, sina, cosa);
|
||||
for(int i = 0; i < n; i++) {
|
||||
wchar chr = text[i];
|
||||
GlyphInfo gi = GetGlyphInfo(font, chr);
|
||||
if(gi.IsNormal())
|
||||
if(angle)
|
||||
DrawTextOp(int(x + cosa * d), int(y - sina * d), angle, &chr, font, ink, 1, NULL);
|
||||
else {
|
||||
int c = 1;
|
||||
int dd = 0;
|
||||
while(c < n) {
|
||||
GlyphInfo gi2 = GetGlyphInfo(font, text[i + c]);
|
||||
if(!gi2.IsNormal())
|
||||
break;
|
||||
dd += dx ? dx[c] : gi.width;
|
||||
c++;
|
||||
gi = gi2;
|
||||
}
|
||||
DrawTextOp(x + d, y, 0, text + i, font, ink, c, dx);
|
||||
d += dd;
|
||||
i += c - 1;
|
||||
if(dx)
|
||||
dx += c - 1;
|
||||
}
|
||||
else
|
||||
if(gi.IsReplaced()) {
|
||||
Font fnt = font;
|
||||
fnt.Face(gi.lspc);
|
||||
fnt.Height(gi.rspc);
|
||||
if(angle)
|
||||
DrawTextOp(int(x + cosa * d), int(y - sina * (font.GetAscent() - fnt.GetAscent() + d)),
|
||||
angle, &chr, fnt, ink, 1, NULL);
|
||||
else
|
||||
DrawTextOp(x + d, y + font.GetAscent() - fnt.GetAscent(), 0, &chr, fnt, ink, 1, NULL);
|
||||
GlyphMetrics(gi, font, chr);
|
||||
}
|
||||
else
|
||||
if(gi.IsComposed()) {
|
||||
ComposedGlyph cg;
|
||||
Compose(font, chr, cg);
|
||||
if(angle) {
|
||||
DrawTextOp(int(x + cosa * d), int(y - sina * d), angle, &cg.basic_char, font, ink, 1, NULL);
|
||||
DrawTextOp(int(x + cosa * (d + cg.mark_pos.x)), int(y - sina * (cg.mark_pos.y + d)), angle, &cg.mark_char, cg.mark_font, ink, 1, NULL);
|
||||
}
|
||||
else {
|
||||
DrawTextOp(x + d, y, 0, &cg.basic_char, font, ink, 1, NULL);
|
||||
DrawTextOp(x + cg.mark_pos.x + d, y + cg.mark_pos.y, 0, &cg.mark_char, cg.mark_font, ink, 1, NULL);
|
||||
}
|
||||
GlyphMetrics(gi, font, chr);
|
||||
}
|
||||
d += dx ? *dx++ : gi.width;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------
|
||||
|
||||
void Draw::DrawText(int x, int y, const wchar *text, Font font,
|
||||
Color ink, int n, const int *dx)
|
||||
{
|
||||
DrawText(x, y, 0, text, font, ink, n, dx);
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
|
||||
void Draw::DrawText(int x, int y, int angle, const WString& text, Font font,
|
||||
Color ink, const int *dx)
|
||||
{
|
||||
DrawText(x, y, angle, ~text, font, ink, text.GetLength(), dx);
|
||||
}
|
||||
|
||||
void Draw::DrawText(int x, int y, const WString& text, Font font, Color ink, const int *dx)
|
||||
{
|
||||
DrawText(x, y, 0, text, font, ink, dx);
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
|
||||
void Draw::DrawText(int x, int y, int angle, const char *text, byte charset, Font font,
|
||||
Color ink, int n, const int *dx)
|
||||
{
|
||||
DrawText(x, y, angle, TextUnicode(text, n, charset, font), font, ink, dx);
|
||||
}
|
||||
|
||||
void Draw::DrawText(int x, int y, const char *text, byte charset, Font font,
|
||||
Color ink, int n, const int *dx)
|
||||
{
|
||||
DrawText(x, y, 0, text, charset, font, ink, n, dx);
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
|
||||
void Draw::DrawText(int x, int y, int angle, const char *text,
|
||||
Font font, Color ink, int n, const int *dx)
|
||||
{
|
||||
DrawText(x, y, angle, text, CHARSET_DEFAULT, font, ink, n, dx);
|
||||
}
|
||||
|
||||
void Draw::DrawText(int x, int y, const char *text, Font font,
|
||||
Color ink, int n, const int *dx)
|
||||
{
|
||||
DrawText(x, y, text, CHARSET_DEFAULT, font, ink, n, dx);
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
|
||||
void Draw::DrawText(int x, int y, int angle, const String& text, Font font,
|
||||
Color ink, const int *dx)
|
||||
{
|
||||
DrawText(x, y, angle, text, font, ink, text.GetLength(), dx);
|
||||
}
|
||||
|
||||
void Draw::DrawText(int x, int y, const String& text, Font font, Color ink, const int *dx)
|
||||
{
|
||||
WString h = TextUnicode(text, text.GetLength(), CHARSET_DEFAULT, font);
|
||||
DrawText(x, y, h, font, ink, h.GetLength(), dx);
|
||||
}
|
||||
|
||||
// --------------------------
|
||||
|
||||
Size GetTextSize(const wchar *text, Font font, int n)
|
||||
{
|
||||
FontInfo fi = font.Info();
|
||||
if(n < 0)
|
||||
n = wstrlen(text);
|
||||
Size sz;
|
||||
sz.cx = 0;
|
||||
const wchar *wtext = (const wchar *)text;
|
||||
while(n > 0) {
|
||||
sz.cx += fi[*wtext++];
|
||||
n--;
|
||||
}
|
||||
sz.cy = fi.GetHeight();
|
||||
return sz;
|
||||
}
|
||||
|
||||
Size GetTextSize(const WString& text, Font font)
|
||||
{
|
||||
return GetTextSize(text, font, text.GetLength());
|
||||
}
|
||||
|
||||
Size GetTextSize(const char *text, byte charset, Font font, int n)
|
||||
{
|
||||
return GetTextSize(TextUnicode(text, n, charset, font), font);
|
||||
}
|
||||
|
||||
Size GetTextSize(const char *text, Font font, int n)
|
||||
{
|
||||
return GetTextSize(text, CHARSET_DEFAULT, font, n);
|
||||
}
|
||||
|
||||
Size GetTextSize(const String& text, Font font)
|
||||
{
|
||||
return GetTextSize(text, font, text.GetLength());
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -1,379 +1,379 @@
|
|||
#include "Draw.h"
|
||||
|
||||
#define LLOG(x)
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
CommonFontInfo GetFontInfoSys(Font font);
|
||||
GlyphInfo GetGlyphInfoSys(Font font, int chr);
|
||||
void GetStdFontSys(String& name, int& height);
|
||||
Vector<FaceInfo> GetAllFacesSys();
|
||||
|
||||
bool Replace(Font fnt, int chr, Font& rfnt);
|
||||
|
||||
void Std(Font& font)
|
||||
{
|
||||
if(IsNull(font))
|
||||
font = StdFont();
|
||||
if(font.GetFace() == 0)
|
||||
font.Face(GetStdFont().GetFace());
|
||||
if(font.GetHeight() == 0)
|
||||
font.Height(GetStdFont().GetHeight());
|
||||
}
|
||||
|
||||
Size Font::StdFontSize;
|
||||
Font Font::AStdFont;
|
||||
|
||||
INITBLOCK {
|
||||
RichValue<Font>::Register();
|
||||
}
|
||||
|
||||
const Vector<FaceInfo>& Font::List()
|
||||
{
|
||||
static Vector<FaceInfo> *q;
|
||||
ONCELOCK {
|
||||
static Vector<FaceInfo> x;
|
||||
x = GetAllFacesSys();
|
||||
q = &x;
|
||||
}
|
||||
return *q;
|
||||
}
|
||||
|
||||
void sInitFonts()
|
||||
{
|
||||
Font::List();
|
||||
GetStdFont();
|
||||
}
|
||||
|
||||
INITBLOCK {
|
||||
sInitFonts();
|
||||
}
|
||||
|
||||
int Font::GetFaceCount()
|
||||
{
|
||||
return List().GetCount();
|
||||
}
|
||||
|
||||
String Font::GetFaceName(int index)
|
||||
{
|
||||
if(index == 0)
|
||||
return "STDFONT";
|
||||
const Vector<FaceInfo>& l = List();
|
||||
if(index >= 0 && index < l.GetCount())
|
||||
return l[index].name;
|
||||
return Null;
|
||||
}
|
||||
|
||||
dword Font::GetFaceInfo(int index)
|
||||
{
|
||||
const Vector<FaceInfo>& l = List();
|
||||
if(index >= 0 && index < l.GetCount())
|
||||
return l[index].info;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FontFilter(int c)
|
||||
{
|
||||
return c >= 'a' && c <= 'z' || c >= '0' && c <= '9' ? c : c >= 'A' && c <= 'Z' ? ToLower(c) : 0;
|
||||
}
|
||||
|
||||
int Font::FindFaceNameIndex(const String& name) {
|
||||
if(name == "STDFONT")
|
||||
return 0;
|
||||
for(int i = 1; i < GetFaceCount(); i++)
|
||||
if(GetFaceName(i) == name)
|
||||
return i;
|
||||
String n = Filter(name, FontFilter);
|
||||
for(int i = 1; i < GetFaceCount(); i++)
|
||||
if(Filter(GetFaceName(i), FontFilter) == n)
|
||||
return i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Font::SyncStdFont()
|
||||
{
|
||||
DrawLock __;
|
||||
StdFontSize = Size(AStdFont.GetAveWidth(), AStdFont().Bold().GetCy());
|
||||
}
|
||||
|
||||
void Font::SetStdFont(Font font)
|
||||
{
|
||||
DrawLock __;
|
||||
InitStdFont();
|
||||
AStdFont = font;
|
||||
SyncStdFont();
|
||||
}
|
||||
|
||||
void Font::InitStdFont()
|
||||
{
|
||||
ONCELOCK {
|
||||
DrawLock __;
|
||||
List();
|
||||
AStdFont = Arial(12);
|
||||
String name;
|
||||
int height = 0;
|
||||
GetStdFontSys(name, height);
|
||||
int q = FindFaceNameIndex(name);
|
||||
if(q > 0) {
|
||||
AStdFont = Font(q, max(height, 1));
|
||||
SyncStdFont();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Font Font::GetStdFont()
|
||||
{
|
||||
InitStdFont();
|
||||
return AStdFont;
|
||||
}
|
||||
|
||||
Size Font::GetStdFontSize()
|
||||
{
|
||||
InitStdFont();
|
||||
return StdFontSize;
|
||||
}
|
||||
|
||||
Font StdFont()
|
||||
{
|
||||
return Font(0, 0);
|
||||
}
|
||||
|
||||
int Font::GetHeight() const
|
||||
{
|
||||
return v.height || v.face ? v.height : GetStdFont().GetHeight();
|
||||
}
|
||||
|
||||
String Font::GetFaceName() const {
|
||||
if(IsNull()) return String();
|
||||
if(GetFace() == 0)
|
||||
return "STDFONT";
|
||||
return GetFaceName(GetFace());
|
||||
}
|
||||
|
||||
dword Font::GetFaceInfo() const {
|
||||
if(IsNull()) return 0;
|
||||
return GetFaceInfo(GetFace());
|
||||
}
|
||||
|
||||
Font& Font::FaceName(const String& name) {
|
||||
int n = FindFaceNameIndex(name);
|
||||
Face(n < 0 ? 0xffff : n);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Font::Serialize(Stream& s) {
|
||||
int version = 1;
|
||||
s / version;
|
||||
if(version >= 1) {
|
||||
enum {
|
||||
OLD_STDFONT, OLD_SCREEN_SERIF, OLD_SCREEN_SANS, OLD_SCREEN_FIXED,
|
||||
OLD_ROMAN,
|
||||
OLD_ARIAL,
|
||||
OLD_COURIER,
|
||||
};
|
||||
int f = GetFace();
|
||||
if(f > COURIER)
|
||||
f = -1;
|
||||
s / f;
|
||||
String name;
|
||||
if(f == OLD_ROMAN)
|
||||
f = ROMAN;
|
||||
if(f == OLD_ARIAL)
|
||||
f = ARIAL;
|
||||
if(f == OLD_COURIER)
|
||||
f = COURIER;
|
||||
if(f < 0) {
|
||||
name = GetFaceName();
|
||||
s % name;
|
||||
}
|
||||
if(s.IsLoading())
|
||||
if(f >= 0)
|
||||
Face(f);
|
||||
else
|
||||
FaceName(name);
|
||||
}
|
||||
else {
|
||||
String name = GetFaceName();
|
||||
s % name;
|
||||
if(s.IsLoading()) {
|
||||
FaceName(name);
|
||||
if(IsNull())
|
||||
Face(COURIER);
|
||||
}
|
||||
}
|
||||
s % v.flags % v.height % v.width;
|
||||
}
|
||||
|
||||
template<>
|
||||
String AsString(const Font& f) {
|
||||
if(IsNull(f)) return "<null>";
|
||||
String s = "<" + f.GetFaceName() + Format(":%d", f.GetHeight());
|
||||
if(f.IsBold())
|
||||
s += " Bold";
|
||||
if(f.IsItalic())
|
||||
s += " Italic";
|
||||
if(f.IsUnderline())
|
||||
s += " Underline";
|
||||
if(f.IsStrikeout())
|
||||
s += " Strikeout";
|
||||
return s + '>';
|
||||
}
|
||||
|
||||
struct CharEntry {
|
||||
int64 font;
|
||||
GlyphInfo info;
|
||||
word chr;
|
||||
};
|
||||
|
||||
CharEntry fc_cache_global[4093];
|
||||
|
||||
bool IsNormal(Font font, int chr)
|
||||
{
|
||||
DrawLock __;
|
||||
CharEntry& e = fc_cache_global[CombineHash(font.GetHashValue(), chr) % 4093];
|
||||
if(e.font == font.AsInt64() || e.chr == chr)
|
||||
return e.info.IsNormal();
|
||||
return GetGlyphInfoSys(font, chr).IsNormal();
|
||||
}
|
||||
|
||||
CharEntry GetGlyphEntry(Font font, int chr, unsigned hash)
|
||||
{
|
||||
DrawLock __;
|
||||
CharEntry& e = fc_cache_global[hash % 4093];
|
||||
if(e.font != font.AsInt64() || e.chr != chr) {
|
||||
e.font = font.AsInt64();
|
||||
e.chr = chr;
|
||||
e.info = GetGlyphInfoSys(font, chr);
|
||||
if(!e.info.IsNormal()) {
|
||||
ComposedGlyph cg;
|
||||
Font rfnt;
|
||||
if(Compose(font, chr, cg)) {
|
||||
e.info.lspc = -1;
|
||||
e.info.rspc = cg.basic_char;
|
||||
}
|
||||
else
|
||||
if(Replace(font, chr, rfnt)) {
|
||||
e.info.lspc = rfnt.GetFace();
|
||||
e.info.rspc = rfnt.GetHeight();
|
||||
}
|
||||
else
|
||||
e.info.lspc = -2;
|
||||
}
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
thread__ CharEntry fc_cache[512];
|
||||
|
||||
GlyphInfo GetGlyphInfo(Font font, int chr)
|
||||
{
|
||||
Std(font);
|
||||
unsigned hash = CombineHash(font.GetHashValue(), chr);
|
||||
CharEntry& e = fc_cache[hash & 511];
|
||||
if(e.font != font.AsInt64() || e.chr != chr)
|
||||
e = GetGlyphEntry(font, chr, hash);
|
||||
return e.info;
|
||||
}
|
||||
|
||||
bool Font::IsNormal(int ch) const
|
||||
{
|
||||
return GetGlyphInfo(*this, ch).IsNormal();
|
||||
}
|
||||
|
||||
bool Font::IsComposed(int ch) const
|
||||
{
|
||||
return GetGlyphInfo(*this, ch).IsComposed();
|
||||
}
|
||||
|
||||
bool Font::IsReplaced(int ch) const
|
||||
{
|
||||
return GetGlyphInfo(*this, ch).IsReplaced();
|
||||
}
|
||||
|
||||
bool Font::IsMissing(int ch) const
|
||||
{
|
||||
return GetGlyphInfo(*this, ch).IsMissing();
|
||||
}
|
||||
|
||||
int Font::HasChar(int ch) const
|
||||
{
|
||||
return !GetGlyphInfo(*this, ch).IsMissing();
|
||||
}
|
||||
|
||||
void GlyphMetrics(GlyphInfo& f, Font font, int chr)
|
||||
{
|
||||
if(f.IsReplaced())
|
||||
f = GetGlyphInfo(font().Face(f.lspc).Height(f.rspc), chr);
|
||||
if(f.IsComposed()) {
|
||||
f = GetGlyphInfo(font, f.rspc);
|
||||
if(f.IsComposedLM())
|
||||
f.rspc += f.width / 2;
|
||||
}
|
||||
}
|
||||
|
||||
GlyphInfo GetGlyphMetrics(Font font, int chr)
|
||||
{
|
||||
GlyphInfo f = GetGlyphInfo(font, chr);
|
||||
if(f.IsMissing())
|
||||
f = GetGlyphInfo(font, '?');
|
||||
GlyphMetrics(f, font, chr);
|
||||
return f;
|
||||
}
|
||||
|
||||
struct FontEntry {
|
||||
CommonFontInfo info;
|
||||
int64 font;
|
||||
};
|
||||
|
||||
thread__ FontEntry fi_cache[64];
|
||||
|
||||
const CommonFontInfo& GetFontInfo(Font font)
|
||||
{
|
||||
Std(font);
|
||||
unsigned hash = font.GetHashValue() & 63;
|
||||
FontEntry& e = fi_cache[hash];
|
||||
if(e.font != font.AsInt64()) {
|
||||
DrawLock __;
|
||||
e.font = font.AsInt64();
|
||||
e.info = GetFontInfoSys(font);
|
||||
}
|
||||
return e.info;
|
||||
}
|
||||
|
||||
int Font::GetWidth(int c) const {
|
||||
return GetGlyphMetrics(*this, c).width;
|
||||
}
|
||||
|
||||
int Font::GetLeftSpace(int c) const {
|
||||
return GetGlyphMetrics(*this, c).lspc;
|
||||
}
|
||||
|
||||
int Font::GetRightSpace(int c) const {
|
||||
return GetGlyphMetrics(*this, c).rspc;
|
||||
}
|
||||
|
||||
thread__ int64 lastFiFont = INT_MIN;
|
||||
thread__ CommonFontInfo lastFontInfo;
|
||||
thread__ int64 lastStdFont = INT_MIN;
|
||||
|
||||
const CommonFontInfo& Font::Fi() const
|
||||
{
|
||||
if(lastStdFont != AStdFont.AsInt64()) {
|
||||
lastFiFont = INT_MIN;
|
||||
lastStdFont = AStdFont.AsInt64();
|
||||
}
|
||||
if(AsInt64() == lastFiFont)
|
||||
return lastFontInfo;
|
||||
lastFontInfo = GetFontInfo(*this);
|
||||
lastFiFont = AsInt64();
|
||||
return lastFontInfo;
|
||||
}
|
||||
|
||||
FontInfo Font::Info() const
|
||||
{
|
||||
FontInfo h;
|
||||
h.font = *this;
|
||||
return h;
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
#include "Draw.h"
|
||||
|
||||
#define LLOG(x)
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
CommonFontInfo GetFontInfoSys(Font font);
|
||||
GlyphInfo GetGlyphInfoSys(Font font, int chr);
|
||||
void GetStdFontSys(String& name, int& height);
|
||||
Vector<FaceInfo> GetAllFacesSys();
|
||||
|
||||
bool Replace(Font fnt, int chr, Font& rfnt);
|
||||
|
||||
void Std(Font& font)
|
||||
{
|
||||
if(IsNull(font))
|
||||
font = StdFont();
|
||||
if(font.GetFace() == 0)
|
||||
font.Face(GetStdFont().GetFace());
|
||||
if(font.GetHeight() == 0)
|
||||
font.Height(GetStdFont().GetHeight());
|
||||
}
|
||||
|
||||
Size Font::StdFontSize;
|
||||
Font Font::AStdFont;
|
||||
|
||||
INITBLOCK {
|
||||
RichValue<Font>::Register();
|
||||
}
|
||||
|
||||
const Vector<FaceInfo>& Font::List()
|
||||
{
|
||||
static Vector<FaceInfo> *q;
|
||||
ONCELOCK {
|
||||
static Vector<FaceInfo> x;
|
||||
x = GetAllFacesSys();
|
||||
q = &x;
|
||||
}
|
||||
return *q;
|
||||
}
|
||||
|
||||
void sInitFonts()
|
||||
{
|
||||
Font::List();
|
||||
GetStdFont();
|
||||
}
|
||||
|
||||
INITBLOCK {
|
||||
sInitFonts();
|
||||
}
|
||||
|
||||
int Font::GetFaceCount()
|
||||
{
|
||||
return List().GetCount();
|
||||
}
|
||||
|
||||
String Font::GetFaceName(int index)
|
||||
{
|
||||
if(index == 0)
|
||||
return "STDFONT";
|
||||
const Vector<FaceInfo>& l = List();
|
||||
if(index >= 0 && index < l.GetCount())
|
||||
return l[index].name;
|
||||
return Null;
|
||||
}
|
||||
|
||||
dword Font::GetFaceInfo(int index)
|
||||
{
|
||||
const Vector<FaceInfo>& l = List();
|
||||
if(index >= 0 && index < l.GetCount())
|
||||
return l[index].info;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FontFilter(int c)
|
||||
{
|
||||
return c >= 'a' && c <= 'z' || c >= '0' && c <= '9' ? c : c >= 'A' && c <= 'Z' ? ToLower(c) : 0;
|
||||
}
|
||||
|
||||
int Font::FindFaceNameIndex(const String& name) {
|
||||
if(name == "STDFONT")
|
||||
return 0;
|
||||
for(int i = 1; i < GetFaceCount(); i++)
|
||||
if(GetFaceName(i) == name)
|
||||
return i;
|
||||
String n = Filter(name, FontFilter);
|
||||
for(int i = 1; i < GetFaceCount(); i++)
|
||||
if(Filter(GetFaceName(i), FontFilter) == n)
|
||||
return i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Font::SyncStdFont()
|
||||
{
|
||||
DrawLock __;
|
||||
StdFontSize = Size(AStdFont.GetAveWidth(), AStdFont().Bold().GetCy());
|
||||
}
|
||||
|
||||
void Font::SetStdFont(Font font)
|
||||
{
|
||||
DrawLock __;
|
||||
InitStdFont();
|
||||
AStdFont = font;
|
||||
SyncStdFont();
|
||||
}
|
||||
|
||||
void Font::InitStdFont()
|
||||
{
|
||||
ONCELOCK {
|
||||
DrawLock __;
|
||||
List();
|
||||
AStdFont = Arial(12);
|
||||
String name;
|
||||
int height = 0;
|
||||
GetStdFontSys(name, height);
|
||||
int q = FindFaceNameIndex(name);
|
||||
if(q > 0) {
|
||||
AStdFont = Font(q, max(height, 1));
|
||||
SyncStdFont();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Font Font::GetStdFont()
|
||||
{
|
||||
InitStdFont();
|
||||
return AStdFont;
|
||||
}
|
||||
|
||||
Size Font::GetStdFontSize()
|
||||
{
|
||||
InitStdFont();
|
||||
return StdFontSize;
|
||||
}
|
||||
|
||||
Font StdFont()
|
||||
{
|
||||
return Font(0, 0);
|
||||
}
|
||||
|
||||
int Font::GetHeight() const
|
||||
{
|
||||
return v.height || v.face ? v.height : GetStdFont().GetHeight();
|
||||
}
|
||||
|
||||
String Font::GetFaceName() const {
|
||||
if(IsNull()) return String();
|
||||
if(GetFace() == 0)
|
||||
return "STDFONT";
|
||||
return GetFaceName(GetFace());
|
||||
}
|
||||
|
||||
dword Font::GetFaceInfo() const {
|
||||
if(IsNull()) return 0;
|
||||
return GetFaceInfo(GetFace());
|
||||
}
|
||||
|
||||
Font& Font::FaceName(const String& name) {
|
||||
int n = FindFaceNameIndex(name);
|
||||
Face(n < 0 ? 0xffff : n);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Font::Serialize(Stream& s) {
|
||||
int version = 1;
|
||||
s / version;
|
||||
if(version >= 1) {
|
||||
enum {
|
||||
OLD_STDFONT, OLD_SCREEN_SERIF, OLD_SCREEN_SANS, OLD_SCREEN_FIXED,
|
||||
OLD_ROMAN,
|
||||
OLD_ARIAL,
|
||||
OLD_COURIER,
|
||||
};
|
||||
int f = GetFace();
|
||||
if(f > COURIER)
|
||||
f = -1;
|
||||
s / f;
|
||||
String name;
|
||||
if(f == OLD_ROMAN)
|
||||
f = ROMAN;
|
||||
if(f == OLD_ARIAL)
|
||||
f = ARIAL;
|
||||
if(f == OLD_COURIER)
|
||||
f = COURIER;
|
||||
if(f < 0) {
|
||||
name = GetFaceName();
|
||||
s % name;
|
||||
}
|
||||
if(s.IsLoading())
|
||||
if(f >= 0)
|
||||
Face(f);
|
||||
else
|
||||
FaceName(name);
|
||||
}
|
||||
else {
|
||||
String name = GetFaceName();
|
||||
s % name;
|
||||
if(s.IsLoading()) {
|
||||
FaceName(name);
|
||||
if(IsNull())
|
||||
Face(COURIER);
|
||||
}
|
||||
}
|
||||
s % v.flags % v.height % v.width;
|
||||
}
|
||||
|
||||
template<>
|
||||
String AsString(const Font& f) {
|
||||
if(IsNull(f)) return "<null>";
|
||||
String s = "<" + f.GetFaceName() + Format(":%d", f.GetHeight());
|
||||
if(f.IsBold())
|
||||
s += " Bold";
|
||||
if(f.IsItalic())
|
||||
s += " Italic";
|
||||
if(f.IsUnderline())
|
||||
s += " Underline";
|
||||
if(f.IsStrikeout())
|
||||
s += " Strikeout";
|
||||
return s + '>';
|
||||
}
|
||||
|
||||
struct CharEntry {
|
||||
int64 font;
|
||||
GlyphInfo info;
|
||||
word chr;
|
||||
};
|
||||
|
||||
CharEntry fc_cache_global[4093];
|
||||
|
||||
bool IsNormal(Font font, int chr)
|
||||
{
|
||||
DrawLock __;
|
||||
CharEntry& e = fc_cache_global[CombineHash(font.GetHashValue(), chr) % 4093];
|
||||
if(e.font == font.AsInt64() || e.chr == chr)
|
||||
return e.info.IsNormal();
|
||||
return GetGlyphInfoSys(font, chr).IsNormal();
|
||||
}
|
||||
|
||||
CharEntry GetGlyphEntry(Font font, int chr, unsigned hash)
|
||||
{
|
||||
DrawLock __;
|
||||
CharEntry& e = fc_cache_global[hash % 4093];
|
||||
if(e.font != font.AsInt64() || e.chr != chr) {
|
||||
e.font = font.AsInt64();
|
||||
e.chr = chr;
|
||||
e.info = GetGlyphInfoSys(font, chr);
|
||||
if(!e.info.IsNormal()) {
|
||||
ComposedGlyph cg;
|
||||
Font rfnt;
|
||||
if(Compose(font, chr, cg)) {
|
||||
e.info.lspc = -1;
|
||||
e.info.rspc = cg.basic_char;
|
||||
}
|
||||
else
|
||||
if(Replace(font, chr, rfnt)) {
|
||||
e.info.lspc = rfnt.GetFace();
|
||||
e.info.rspc = rfnt.GetHeight();
|
||||
}
|
||||
else
|
||||
e.info.lspc = -2;
|
||||
}
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
thread__ CharEntry fc_cache[512];
|
||||
|
||||
GlyphInfo GetGlyphInfo(Font font, int chr)
|
||||
{
|
||||
Std(font);
|
||||
unsigned hash = CombineHash(font.GetHashValue(), chr);
|
||||
CharEntry& e = fc_cache[hash & 511];
|
||||
if(e.font != font.AsInt64() || e.chr != chr)
|
||||
e = GetGlyphEntry(font, chr, hash);
|
||||
return e.info;
|
||||
}
|
||||
|
||||
bool Font::IsNormal(int ch) const
|
||||
{
|
||||
return GetGlyphInfo(*this, ch).IsNormal();
|
||||
}
|
||||
|
||||
bool Font::IsComposed(int ch) const
|
||||
{
|
||||
return GetGlyphInfo(*this, ch).IsComposed();
|
||||
}
|
||||
|
||||
bool Font::IsReplaced(int ch) const
|
||||
{
|
||||
return GetGlyphInfo(*this, ch).IsReplaced();
|
||||
}
|
||||
|
||||
bool Font::IsMissing(int ch) const
|
||||
{
|
||||
return GetGlyphInfo(*this, ch).IsMissing();
|
||||
}
|
||||
|
||||
int Font::HasChar(int ch) const
|
||||
{
|
||||
return !GetGlyphInfo(*this, ch).IsMissing();
|
||||
}
|
||||
|
||||
void GlyphMetrics(GlyphInfo& f, Font font, int chr)
|
||||
{
|
||||
if(f.IsReplaced())
|
||||
f = GetGlyphInfo(font().Face(f.lspc).Height(f.rspc), chr);
|
||||
if(f.IsComposed()) {
|
||||
f = GetGlyphInfo(font, f.rspc);
|
||||
if(f.IsComposedLM())
|
||||
f.rspc += f.width / 2;
|
||||
}
|
||||
}
|
||||
|
||||
GlyphInfo GetGlyphMetrics(Font font, int chr)
|
||||
{
|
||||
GlyphInfo f = GetGlyphInfo(font, chr);
|
||||
if(f.IsMissing())
|
||||
f = GetGlyphInfo(font, '?');
|
||||
GlyphMetrics(f, font, chr);
|
||||
return f;
|
||||
}
|
||||
|
||||
struct FontEntry {
|
||||
CommonFontInfo info;
|
||||
int64 font;
|
||||
};
|
||||
|
||||
thread__ FontEntry fi_cache[64];
|
||||
|
||||
const CommonFontInfo& GetFontInfo(Font font)
|
||||
{
|
||||
Std(font);
|
||||
unsigned hash = font.GetHashValue() & 63;
|
||||
FontEntry& e = fi_cache[hash];
|
||||
if(e.font != font.AsInt64()) {
|
||||
DrawLock __;
|
||||
e.font = font.AsInt64();
|
||||
e.info = GetFontInfoSys(font);
|
||||
}
|
||||
return e.info;
|
||||
}
|
||||
|
||||
int Font::GetWidth(int c) const {
|
||||
return GetGlyphMetrics(*this, c).width;
|
||||
}
|
||||
|
||||
int Font::GetLeftSpace(int c) const {
|
||||
return GetGlyphMetrics(*this, c).lspc;
|
||||
}
|
||||
|
||||
int Font::GetRightSpace(int c) const {
|
||||
return GetGlyphMetrics(*this, c).rspc;
|
||||
}
|
||||
|
||||
thread__ int64 lastFiFont = INT_MIN;
|
||||
thread__ CommonFontInfo lastFontInfo;
|
||||
thread__ int64 lastStdFont = INT_MIN;
|
||||
|
||||
const CommonFontInfo& Font::Fi() const
|
||||
{
|
||||
if(lastStdFont != AStdFont.AsInt64()) {
|
||||
lastFiFont = INT_MIN;
|
||||
lastStdFont = AStdFont.AsInt64();
|
||||
}
|
||||
if(AsInt64() == lastFiFont)
|
||||
return lastFontInfo;
|
||||
lastFontInfo = GetFontInfo(*this);
|
||||
lastFiFont = AsInt64();
|
||||
return lastFontInfo;
|
||||
}
|
||||
|
||||
FontInfo Font::Info() const
|
||||
{
|
||||
FontInfo h;
|
||||
h.font = *this;
|
||||
return h;
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -26,8 +26,6 @@ bool sInitFt(void)
|
|||
return FT_Init_FreeType(&sFTlib) == 0;
|
||||
}
|
||||
|
||||
int gtk_dpi = 96;
|
||||
|
||||
FcPattern *CreateFcPattern(Font font)
|
||||
{
|
||||
LTIMING("CreateXftFont");
|
||||
|
|
@ -39,12 +37,11 @@ FcPattern *CreateFcPattern(Font font)
|
|||
FcPatternAddString(p, FC_FAMILY, (FcChar8*)~face);
|
||||
FcPatternAddInteger(p, FC_SLANT, font.IsItalic() ? 110 : 0);
|
||||
FcPatternAddInteger(p, FC_PIXEL_SIZE, hg);
|
||||
FcPatternAddInteger(p, FC_DPI, gtk_dpi);
|
||||
FcPatternAddInteger(p, FC_WEIGHT, font.IsBold() ? 200 : 100);
|
||||
FcPatternAddBool(p, FC_MINSPACE, 1);
|
||||
FcResult result;
|
||||
FcConfigSubstitute(0, p, FcMatchPattern);
|
||||
FcDefaultSubstitute(p);
|
||||
FcResult result;
|
||||
FcPattern *m = FcFontMatch(0, p, &result);
|
||||
FcPatternDestroy(p);
|
||||
return m;
|
||||
|
|
@ -75,7 +72,7 @@ FT_Face CreateFTFace(const FcPattern *pattern, String *rpath) {
|
|||
FT_F26Dot6 ysize = (FT_F26Dot6) (dsize * 64.0);
|
||||
FT_F26Dot6 xsize = (FT_F26Dot6) (dsize * aspect * 64.0);
|
||||
|
||||
if(FT_New_Face (sFTlib, (const char *)filename, 0, &face))
|
||||
if(FT_New_Face(sFTlib, (const char *)filename, 0, &face))
|
||||
return NULL;
|
||||
|
||||
FT_Set_Char_Size(face, xsize, ysize, 0, 0);
|
||||
|
|
@ -90,25 +87,35 @@ struct FtFaceEntry {
|
|||
String path;
|
||||
};
|
||||
|
||||
static FtFaceEntry ft_cache[FONTCACHE];
|
||||
|
||||
void ClearFtFaceCache()
|
||||
{
|
||||
for(int i = 0; i < FONTCACHE; i++)
|
||||
ft_cache[i].font.Height(-30000);
|
||||
}
|
||||
|
||||
FT_Face (*FTFaceXft)(Font fnt, String *rpath);
|
||||
|
||||
FT_Face FTFace(Font fnt, String *rpath = NULL)
|
||||
{
|
||||
LTIMING("FTFace");
|
||||
static FtFaceEntry cache[FONTCACHE];
|
||||
if(FTFaceXft)
|
||||
return (*FTFaceXft)(fnt, rpath);
|
||||
ONCELOCK {
|
||||
for(int i = 0; i < FONTCACHE; i++)
|
||||
cache[i].font.Height(-30000);
|
||||
ClearFtFaceCache();
|
||||
}
|
||||
FtFaceEntry be;
|
||||
be = cache[0];
|
||||
be = ft_cache[0];
|
||||
for(int i = 0; i < FONTCACHE; i++) {
|
||||
FtFaceEntry e = cache[i];
|
||||
FtFaceEntry e = ft_cache[i];
|
||||
if(i)
|
||||
cache[i] = be;
|
||||
ft_cache[i] = be;
|
||||
if(e.font == fnt) {
|
||||
if(rpath)
|
||||
*rpath = e.path;
|
||||
if(i)
|
||||
cache[0] = e;
|
||||
ft_cache[0] = e;
|
||||
return e.face;
|
||||
}
|
||||
be = e;
|
||||
|
|
@ -122,16 +129,19 @@ FT_Face FTFace(Font fnt, String *rpath = NULL)
|
|||
FcPattern *p = CreateFcPattern(fnt);
|
||||
be.face = CreateFTFace(p, &be.path);
|
||||
FcPatternDestroy(p);
|
||||
cache[0] = be;
|
||||
ft_cache[0] = be;
|
||||
if(rpath)
|
||||
*rpath = be.path;
|
||||
return be.face;
|
||||
}
|
||||
|
||||
CommonFontInfo (*GetFontInfoSysXft)(Font font);
|
||||
|
||||
CommonFontInfo GetFontInfoSys(Font font)
|
||||
{
|
||||
if(GetFontInfoSysXft)
|
||||
return (*GetFontInfoSysXft)(font);
|
||||
CommonFontInfo fi;
|
||||
|
||||
String path;
|
||||
FT_Face face = FTFace(font, &path);
|
||||
if(face) {
|
||||
|
|
@ -159,9 +169,13 @@ CommonFontInfo GetFontInfoSys(Font font)
|
|||
#define TRUNC(x) ((x) >> 6)
|
||||
#define ROUND(x) (((x)+32) & -64)
|
||||
|
||||
GlyphInfo (*GetGlyphInfoSysXft)(Font font, int chr);
|
||||
|
||||
GlyphInfo GetGlyphInfoSys(Font font, int chr)
|
||||
{
|
||||
LTIMING("GetGlyphInfoSys");
|
||||
if(GetGlyphInfoSysXft)
|
||||
return (*GetGlyphInfoSysXft)(font, chr);
|
||||
GlyphInfo gi;
|
||||
FT_Face face = FTFace(font, NULL);
|
||||
gi.lspc = gi.rspc = 0;
|
||||
|
|
|
|||
|
|
@ -1,156 +1,155 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all coM_PIes.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// Recycled for U++ by Miroslav Fidler 2008
|
||||
|
||||
#include "Painter.h"
|
||||
|
||||
#ifdef PLATFORM_POSIX
|
||||
#include <fontconfig/fontconfig.h>
|
||||
#include <fontconfig/fcfreetype.h>
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
FT_Face FTFace(Font fnt, String *rpath);
|
||||
|
||||
static inline double ft_dbl(int p)
|
||||
{
|
||||
return double(p) / 64.0;
|
||||
}
|
||||
|
||||
bool RenderOutline(const FT_Outline& outline, Painter& path, double xx, double yy)
|
||||
{
|
||||
FT_Vector v_last;
|
||||
FT_Vector v_control;
|
||||
FT_Vector v_start;
|
||||
FT_Vector* point;
|
||||
FT_Vector* limit;
|
||||
char* tags;
|
||||
int n; // index of contour in outline
|
||||
char tag; // current point's state
|
||||
int first = 0; // index of first point in contour
|
||||
for(n = 0; n < outline.n_contours; n++) {
|
||||
int last = outline.contours[n];
|
||||
limit = outline.points + last;
|
||||
v_start = outline.points[first];
|
||||
v_last = outline.points[last];
|
||||
v_control = v_start;
|
||||
point = outline.points + first;
|
||||
tags = outline.tags + first;
|
||||
tag = FT_CURVE_TAG(tags[0]);
|
||||
if(tag == FT_CURVE_TAG_CUBIC) return false;
|
||||
if(tag == FT_CURVE_TAG_CONIC) {
|
||||
if(FT_CURVE_TAG(outline.tags[last]) == FT_CURVE_TAG_ON) {
|
||||
// start at last point if it is on the curve
|
||||
v_start = v_last;
|
||||
limit--;
|
||||
}
|
||||
else {
|
||||
// if both first and last points are conic,
|
||||
// start at their middle and record its position
|
||||
// for closure
|
||||
v_start.x = (v_start.x + v_last.x) / 2;
|
||||
v_start.y = (v_start.y + v_last.y) / 2;
|
||||
v_last = v_start;
|
||||
}
|
||||
point--;
|
||||
tags--;
|
||||
}
|
||||
path.Move(ft_dbl(v_start.x) + xx, -ft_dbl(v_start.y) + yy);
|
||||
while(point < limit) {
|
||||
point++;
|
||||
tags++;
|
||||
|
||||
tag = FT_CURVE_TAG(tags[0]);
|
||||
switch(tag) {
|
||||
case FT_CURVE_TAG_ON:
|
||||
path.Line(ft_dbl(point->x) + xx, -ft_dbl(point->y) + yy);
|
||||
continue;
|
||||
case FT_CURVE_TAG_CONIC:
|
||||
v_control.x = point->x;
|
||||
v_control.y = point->y;
|
||||
Do_Conic:
|
||||
if(point < limit) {
|
||||
FT_Vector vec;
|
||||
FT_Vector v_middle;
|
||||
point++;
|
||||
tags++;
|
||||
tag = FT_CURVE_TAG(tags[0]);
|
||||
vec.x = point->x;
|
||||
vec.y = point->y;
|
||||
if(tag == FT_CURVE_TAG_ON) {
|
||||
path.Quadratic(ft_dbl(v_control.x) + xx, -ft_dbl(v_control.y) + yy,
|
||||
ft_dbl(vec.x) + xx, -ft_dbl(vec.y) + yy);
|
||||
continue;
|
||||
}
|
||||
if(tag != FT_CURVE_TAG_CONIC) return false;
|
||||
v_middle.x = (v_control.x + vec.x) / 2;
|
||||
v_middle.y = (v_control.y + vec.y) / 2;
|
||||
path.Quadratic(ft_dbl(v_control.x) + xx, -ft_dbl(v_control.y) + yy,
|
||||
ft_dbl(v_middle.x) + xx, -ft_dbl(v_middle.y) + yy);
|
||||
v_control = vec;
|
||||
goto Do_Conic;
|
||||
}
|
||||
path.Quadratic(ft_dbl(v_control.x) + xx, -ft_dbl(v_control.y) + yy,
|
||||
ft_dbl(v_start.x) + xx, -ft_dbl(v_start.y) + yy);
|
||||
goto Close;
|
||||
|
||||
default:
|
||||
FT_Vector vec1, vec2;
|
||||
if(point + 1 > limit || FT_CURVE_TAG(tags[1]) != FT_CURVE_TAG_CUBIC)
|
||||
return false;
|
||||
vec1.x = point[0].x;
|
||||
vec1.y = point[0].y;
|
||||
vec2.x = point[1].x;
|
||||
vec2.y = point[1].y;
|
||||
point += 2;
|
||||
tags += 2;
|
||||
if(point <= limit) {
|
||||
FT_Vector vec;
|
||||
vec.x = point->x;
|
||||
vec.y = point->y;
|
||||
path.Cubic(ft_dbl(vec1.x) + xx, -ft_dbl(vec1.y) + yy,
|
||||
ft_dbl(vec2.x) + xx, -ft_dbl(vec2.y) + yy,
|
||||
ft_dbl(vec.x) + xx, -ft_dbl(vec.y) + yy);
|
||||
continue;
|
||||
}
|
||||
path.Cubic(ft_dbl(vec1.x) + xx, -ft_dbl(vec1.y) + yy,
|
||||
ft_dbl(vec2.x) + xx, -ft_dbl(vec2.y) + yy,
|
||||
ft_dbl(v_start.x) + xx, -ft_dbl(v_start.y) + yy);
|
||||
goto Close;
|
||||
}
|
||||
}
|
||||
Close:
|
||||
path.Close();
|
||||
first = last + 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void PaintCharacterSys(Painter& sw, double x, double y, int ch, Font fnt)
|
||||
{
|
||||
DrawLock __;
|
||||
PAINTER_TIMING("CharacterOp");
|
||||
FT_Face face = FTFace(fnt, NULL);
|
||||
int glyph_index = FT_Get_Char_Index(face, ch);
|
||||
if(glyph_index && FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT) == 0)
|
||||
RenderOutline(face->glyph->outline, sw, x, y + fnt.GetAscent());
|
||||
sw.EvenOdd(true);
|
||||
}
|
||||
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
||||
#endif
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all coM_PIes.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// Recycled for U++ by Miroslav Fidler 2008
|
||||
|
||||
#include "Painter.h"
|
||||
|
||||
#ifdef PLATFORM_POSIX
|
||||
#include <fontconfig/fontconfig.h>
|
||||
#include <fontconfig/fcfreetype.h>
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
FT_Face FTFace(Font fnt, String *rpath);
|
||||
|
||||
static inline double ft_dbl(int p)
|
||||
{
|
||||
return double(p) / 64.0;
|
||||
}
|
||||
|
||||
bool RenderOutline(const FT_Outline& outline, Painter& path, double xx, double yy)
|
||||
{
|
||||
FT_Vector v_last;
|
||||
FT_Vector v_control;
|
||||
FT_Vector v_start;
|
||||
FT_Vector* point;
|
||||
FT_Vector* limit;
|
||||
char* tags;
|
||||
int n; // index of contour in outline
|
||||
char tag; // current point's state
|
||||
int first = 0; // index of first point in contour
|
||||
for(n = 0; n < outline.n_contours; n++) {
|
||||
int last = outline.contours[n];
|
||||
limit = outline.points + last;
|
||||
v_start = outline.points[first];
|
||||
v_last = outline.points[last];
|
||||
v_control = v_start;
|
||||
point = outline.points + first;
|
||||
tags = outline.tags + first;
|
||||
tag = FT_CURVE_TAG(tags[0]);
|
||||
if(tag == FT_CURVE_TAG_CUBIC) return false;
|
||||
if(tag == FT_CURVE_TAG_CONIC) {
|
||||
if(FT_CURVE_TAG(outline.tags[last]) == FT_CURVE_TAG_ON) {
|
||||
// start at last point if it is on the curve
|
||||
v_start = v_last;
|
||||
limit--;
|
||||
}
|
||||
else {
|
||||
// if both first and last points are conic,
|
||||
// start at their middle and record its position
|
||||
// for closure
|
||||
v_start.x = (v_start.x + v_last.x) / 2;
|
||||
v_start.y = (v_start.y + v_last.y) / 2;
|
||||
v_last = v_start;
|
||||
}
|
||||
point--;
|
||||
tags--;
|
||||
}
|
||||
path.Move(ft_dbl(v_start.x) + xx, -ft_dbl(v_start.y) + yy);
|
||||
while(point < limit) {
|
||||
point++;
|
||||
tags++;
|
||||
|
||||
tag = FT_CURVE_TAG(tags[0]);
|
||||
switch(tag) {
|
||||
case FT_CURVE_TAG_ON:
|
||||
path.Line(ft_dbl(point->x) + xx, -ft_dbl(point->y) + yy);
|
||||
continue;
|
||||
case FT_CURVE_TAG_CONIC:
|
||||
v_control.x = point->x;
|
||||
v_control.y = point->y;
|
||||
Do_Conic:
|
||||
if(point < limit) {
|
||||
FT_Vector vec;
|
||||
FT_Vector v_middle;
|
||||
point++;
|
||||
tags++;
|
||||
tag = FT_CURVE_TAG(tags[0]);
|
||||
vec.x = point->x;
|
||||
vec.y = point->y;
|
||||
if(tag == FT_CURVE_TAG_ON) {
|
||||
path.Quadratic(ft_dbl(v_control.x) + xx, -ft_dbl(v_control.y) + yy,
|
||||
ft_dbl(vec.x) + xx, -ft_dbl(vec.y) + yy);
|
||||
continue;
|
||||
}
|
||||
if(tag != FT_CURVE_TAG_CONIC) return false;
|
||||
v_middle.x = (v_control.x + vec.x) / 2;
|
||||
v_middle.y = (v_control.y + vec.y) / 2;
|
||||
path.Quadratic(ft_dbl(v_control.x) + xx, -ft_dbl(v_control.y) + yy,
|
||||
ft_dbl(v_middle.x) + xx, -ft_dbl(v_middle.y) + yy);
|
||||
v_control = vec;
|
||||
goto Do_Conic;
|
||||
}
|
||||
path.Quadratic(ft_dbl(v_control.x) + xx, -ft_dbl(v_control.y) + yy,
|
||||
ft_dbl(v_start.x) + xx, -ft_dbl(v_start.y) + yy);
|
||||
goto Close;
|
||||
|
||||
default:
|
||||
FT_Vector vec1, vec2;
|
||||
if(point + 1 > limit || FT_CURVE_TAG(tags[1]) != FT_CURVE_TAG_CUBIC)
|
||||
return false;
|
||||
vec1.x = point[0].x;
|
||||
vec1.y = point[0].y;
|
||||
vec2.x = point[1].x;
|
||||
vec2.y = point[1].y;
|
||||
point += 2;
|
||||
tags += 2;
|
||||
if(point <= limit) {
|
||||
FT_Vector vec;
|
||||
vec.x = point->x;
|
||||
vec.y = point->y;
|
||||
path.Cubic(ft_dbl(vec1.x) + xx, -ft_dbl(vec1.y) + yy,
|
||||
ft_dbl(vec2.x) + xx, -ft_dbl(vec2.y) + yy,
|
||||
ft_dbl(vec.x) + xx, -ft_dbl(vec.y) + yy);
|
||||
continue;
|
||||
}
|
||||
path.Cubic(ft_dbl(vec1.x) + xx, -ft_dbl(vec1.y) + yy,
|
||||
ft_dbl(vec2.x) + xx, -ft_dbl(vec2.y) + yy,
|
||||
ft_dbl(v_start.x) + xx, -ft_dbl(v_start.y) + yy);
|
||||
goto Close;
|
||||
}
|
||||
}
|
||||
Close:
|
||||
path.Close();
|
||||
first = last + 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void PaintCharacterSys(Painter& sw, double x, double y, int ch, Font fnt)
|
||||
{
|
||||
DrawLock __;
|
||||
PAINTER_TIMING("CharacterOp");
|
||||
FT_Face face = FTFace(fnt, NULL);
|
||||
int glyph_index = FT_Get_Char_Index(face, ch);
|
||||
if(glyph_index && FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT) == 0)
|
||||
RenderOutline(face->glyph->outline, sw, x, y + fnt.GetAscent());
|
||||
sw.EvenOdd(true);
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -267,7 +267,7 @@ PdfDraw::OutlineInfo PdfDraw::GetOutlineInfo(Font fnt)
|
|||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef PLATFORM_X11
|
||||
#ifdef PLATFORM_POSIX
|
||||
FontInfo fi = fnt.Info();
|
||||
String fn = fi.GetFileName();
|
||||
String ext = ToLower(GetFileExt(fn));
|
||||
|
|
@ -299,7 +299,7 @@ void PdfDraw::DrawTextOp(int x, int y, int angle, const wchar *s, Font fnt,
|
|||
#ifdef PLATFORM_WIN32
|
||||
int fh = ff.GetHeight() - ff.GetInternal();//TODO
|
||||
#endif
|
||||
#ifdef PLATFORM_X11
|
||||
#ifdef PLATFORM_POSIX
|
||||
int fh = fnt.GetHeight();
|
||||
#endif
|
||||
OutlineInfo of = GetOutlineInfo(fnt);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef _PdfDraw_icpp_init_stub
|
||||
#define _PdfDraw_icpp_init_stub
|
||||
#include "Draw/init"
|
||||
#define BLITZ_INDEX__ F2EB858D15FF91342F7F9648AA934C9C8
|
||||
#define BLITZ_INDEX__ FA6D939FEC0881A8606B7621CDFC33471
|
||||
#include "PdfReport.icpp"
|
||||
#undef BLITZ_INDEX__
|
||||
#endif
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,364 +1,364 @@
|
|||
#include "usvn.h"
|
||||
|
||||
bool CheckSvn()
|
||||
{
|
||||
String h;
|
||||
if(Sys("svn", h) >= 0)
|
||||
return true;
|
||||
#ifdef PLATFORM_WIN32
|
||||
Exclamation("Unable to execute svn.exe!&"
|
||||
"You can download svn client here: [^http://www.sliksvn.com/en/download^ http://www.sliksvn.com/en/download]");
|
||||
#else
|
||||
Exclamation("Unable to execute 'svn' binary!&Please install svn client.");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
SvnSync::SvnSync()
|
||||
{
|
||||
CtrlLayoutOKCancel(*this, "SvnSynchronize SVN repositories");
|
||||
list.AddIndex();
|
||||
list.AddIndex();
|
||||
list.AddColumn("Action");
|
||||
list.AddColumn("Path");
|
||||
list.AddColumn("Changes");
|
||||
list.ColumnWidths("170 500 100");
|
||||
list.NoCursor().EvenRowColor();
|
||||
list.SetLineCy(max(Draw::GetStdFontCy(), 20));
|
||||
list.WhenLeftClick = THISBACK(Diff);
|
||||
Sizeable().Zoomable();
|
||||
setup <<= THISBACK(Setup);
|
||||
BackPaint();
|
||||
}
|
||||
|
||||
void SvnSync::Setup()
|
||||
{
|
||||
works.Execute();
|
||||
SyncList();
|
||||
}
|
||||
|
||||
int CharFilterSvnMsg(int c)
|
||||
{
|
||||
return c >= 32 && c < 128 && c != '\"' ? c : 0;
|
||||
}
|
||||
|
||||
void SvnSync::SyncList()
|
||||
{
|
||||
list.Clear();
|
||||
for(int i = 0; i < works.GetCount(); i++) {
|
||||
SvnWork w = works[i];
|
||||
String path = GetFullPath(w.working);
|
||||
list.Add(REPOSITORY, path,
|
||||
AttrText("Working directory").SetFont(StdFont().Bold()).Ink(White).Paper(Blue),
|
||||
AttrText(path).SetFont(Arial(20).Bold()).Paper(Blue).Ink(White),
|
||||
AttrText("").SetFont(Arial(20).Bold()).Paper(Blue).Ink(White));
|
||||
list.SetLineCy(list.GetCount() - 1, 26);
|
||||
Vector<String> ln = Split(Sys("svn status " + path), CharFilterCrLf);
|
||||
bool actions = false;
|
||||
for(int pass = 0; pass < 2; pass++)
|
||||
for(int i = 0; i < ln.GetCount(); i++) {
|
||||
String h = ln[i];
|
||||
if(h.GetCount() > 7) {
|
||||
String file = h.Mid(7);
|
||||
if(IsFullPath(file)) {
|
||||
actions = true;
|
||||
h.Trim(7);
|
||||
bool simple = h.Mid(1, 6) == " ";
|
||||
int action = simple ? String("MC?!~").Find(h[0]) : -1;
|
||||
if(h == " S ")
|
||||
action = REPLACE;
|
||||
String an;
|
||||
Color color;
|
||||
if(action < 0) {
|
||||
color = Black;
|
||||
if(simple && h[0] == 'A')
|
||||
an = "svn add";
|
||||
else
|
||||
if(simple && h[0] == 'D')
|
||||
an = "svn delete";
|
||||
else {
|
||||
an = h.Mid(0, 7);
|
||||
color = Gray;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int q = file.ReverseFind('.');
|
||||
if(action == ADD && q >= 0 && (file.Mid(q + 1) == "mine" ||
|
||||
file[q + 1] == 'r' && IsDigit(file[q + 2]))
|
||||
&& FileExists(file.Mid(0, q))) {
|
||||
action = DELETEC;
|
||||
an = "Delete";
|
||||
color = Black;
|
||||
}
|
||||
else {
|
||||
static const char *as[] = {
|
||||
"Modify", "Resolved", "Add", "Remove", "Replace"
|
||||
};
|
||||
static Color c[] = { LtBlue, Magenta, Green, LtRed, LtMagenta };
|
||||
an = as[action];
|
||||
color = c[action];
|
||||
}
|
||||
}
|
||||
if(pass == action < 0) {
|
||||
int ii = list.GetCount();
|
||||
list.Add(action, file,
|
||||
action < 0 ? Value(AttrText(an).Ink(color)) : Value(true),
|
||||
AttrText(" " + file.Mid(path.GetCount() + 1)).Ink(color));
|
||||
if(action >= 0) {
|
||||
list.SetCtrl(ii, 0, revert.Add().SetLabel("Revert\n" + an).NoWantFocus());
|
||||
Ctrl& b = diff.Add().SetLabel("Changes..").SizePos().NoWantFocus();
|
||||
b <<= THISBACK1(DoDiff, ii);
|
||||
list.SetCtrl(ii, 2, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(actions) {
|
||||
list.Add(MESSAGE, Null, AttrText("Commit message:").SetFont(StdFont().Bold()));
|
||||
list.SetLineCy(list.GetCount() - 1, (3 * EditField::GetStdHeight()) + 4);
|
||||
list.SetCtrl(list.GetCount() - 1, 1, message.Add().SetFilter(CharFilterSvnMsg).VSizePos(2, 2).HSizePos());
|
||||
int q = msgmap.Find(w.working);
|
||||
if(q >= 0) {
|
||||
message.Top() <<= msgmap[q];
|
||||
msgmap.Unlink(q);
|
||||
}
|
||||
}
|
||||
else
|
||||
list.Add(-1, Null, "", AttrText("Nothing to do").SetFont(StdFont().Italic()));
|
||||
}
|
||||
}
|
||||
|
||||
void SvnSync::DoDiff(int ii)
|
||||
{
|
||||
String f = list.Get(ii, 1);
|
||||
if(!IsNull(f))
|
||||
RunSvnDiff(f);
|
||||
}
|
||||
|
||||
void SvnSync::Diff()
|
||||
{
|
||||
int cr = list.GetClickRow();
|
||||
if(cr >= 0)
|
||||
DoDiff(cr);
|
||||
}
|
||||
|
||||
#ifdef PLATFORM_WIN32
|
||||
void sDeleteFolderDeep(const char *dir)
|
||||
{
|
||||
{
|
||||
FindFile ff(AppendFileName(dir, "*.*"));
|
||||
while(ff) {
|
||||
String name = ff.GetName();
|
||||
String p = AppendFileName(dir, name);
|
||||
if(ff.IsFile()) {
|
||||
SetFileAttributes(p, GetFileAttributes(p) & ~FILE_ATTRIBUTE_READONLY);
|
||||
FileDelete(p);
|
||||
}
|
||||
else
|
||||
if(ff.IsFolder())
|
||||
sDeleteFolderDeep(p);
|
||||
ff.Next();
|
||||
}
|
||||
}
|
||||
DirectoryDelete(dir);
|
||||
}
|
||||
#else
|
||||
void sDeleteFolderDeep(const char *path)
|
||||
{
|
||||
DeleteFolderDeep(path);
|
||||
}
|
||||
#endif
|
||||
|
||||
void SvnDel(const char *path)
|
||||
{
|
||||
FindFile ff(AppendFileName(path, "*.*"));
|
||||
while(ff) {
|
||||
if(ff.IsFolder()) {
|
||||
String dir = AppendFileName(path, ff.GetName());
|
||||
if(ff.GetName() == ".svn")
|
||||
sDeleteFolderDeep(dir);
|
||||
else
|
||||
SvnDel(dir);
|
||||
}
|
||||
ff.Next();
|
||||
}
|
||||
}
|
||||
|
||||
void SvnSync::Dir(const char *dir)
|
||||
{
|
||||
setup.Hide();
|
||||
works.Add(dir, Null, Null);
|
||||
}
|
||||
|
||||
void SvnSync::Perform()
|
||||
{
|
||||
if(!CheckSvn())
|
||||
return;
|
||||
const Vector<String>& cl = CommandLine();
|
||||
if(cl.GetCount())
|
||||
for(int i = 0; i < cl.GetCount(); i++) {
|
||||
if(cl[i] == "-") {
|
||||
works.Load(LoadFile(ConfigFile("svnworks")));
|
||||
DoSync();
|
||||
SaveFile(ConfigFile("svnworks"), works.Save());
|
||||
return;
|
||||
}
|
||||
String d = GetFullPath(cl[i]);
|
||||
if(!DirectoryExists(cl[i])) {
|
||||
Cerr() << cl[i] << " not a directory\n";
|
||||
SetExitCode(1);
|
||||
return;
|
||||
}
|
||||
works.Add(d, "", "");
|
||||
}
|
||||
else
|
||||
works.Add(GetCurrentDirectory(), "", "");
|
||||
setup.Hide();
|
||||
DoSync();
|
||||
}
|
||||
|
||||
void MoveSvn(const String& path, const String& tp)
|
||||
{
|
||||
FindFile ff(AppendFileName(path, "*.*"));
|
||||
while(ff) {
|
||||
String nm = ff.GetName();
|
||||
String s = AppendFileName(path, nm);
|
||||
String t = AppendFileName(tp, nm);
|
||||
if(ff.IsFolder())
|
||||
if(nm == ".svn")
|
||||
FileMove(s, t);
|
||||
else
|
||||
MoveSvn(s, t);
|
||||
ff.Next();
|
||||
}
|
||||
}
|
||||
|
||||
void SvnSync::DoSync()
|
||||
{
|
||||
SyncList();
|
||||
msgmap.Sweep();
|
||||
again:
|
||||
if(Execute() != IDOK || list.GetCount() == 0) {
|
||||
int repoi = 0;
|
||||
for(int i = 0; i < list.GetCount(); i++)
|
||||
if(list.Get(i, 0) == MESSAGE)
|
||||
msgmap.GetAdd(works[repoi++].working) = list.Get(i, 3);
|
||||
return;
|
||||
}
|
||||
bool changes = false;
|
||||
for(int i = 0; i < list.GetCount(); i++) {
|
||||
int action = list.Get(i, 0);
|
||||
Value v = list.Get(i, 2);
|
||||
if(action == MESSAGE) {
|
||||
if(changes && IsNull(list.Get(i, 3))
|
||||
&& !PromptYesNo("Commit message is empty.&Do you want to continue?"))
|
||||
goto again;
|
||||
changes = false;
|
||||
}
|
||||
else if(action != REPOSITORY && IsNumber(v) && (int)v)
|
||||
changes = true;
|
||||
}
|
||||
SysConsole sys;
|
||||
int repoi = 0;
|
||||
int l = 0;
|
||||
bool commit = false;
|
||||
while(l < list.GetCount()) {
|
||||
SvnWork w = works[repoi++];
|
||||
l++;
|
||||
String message;
|
||||
while(l < list.GetCount()) {
|
||||
int action = list.Get(l, 0);
|
||||
String path = list.Get(l, 1);
|
||||
if(action == MESSAGE && commit) {
|
||||
String msg = list.Get(l, 3);
|
||||
if(sys.CheckSystem(SvnCmd("commit", w).Cat() << w.working << " -m \"" << msg << "\""))
|
||||
msgmap.GetAdd(w.working) = msg;
|
||||
l++;
|
||||
break;
|
||||
}
|
||||
if(action == REPOSITORY)
|
||||
break;
|
||||
Value v = list.Get(l, 2);
|
||||
if(IsNumber(v) && (int)v == 0) {
|
||||
if(action == REPLACE || action == ADD)
|
||||
DeleteFolderDeep(path);
|
||||
if(action != ADD)
|
||||
sys.CheckSystem("svn revert " + path);
|
||||
}
|
||||
else {
|
||||
commit = true;
|
||||
switch(action) {
|
||||
case ADD:
|
||||
SvnDel(path);
|
||||
sys.CheckSystem("svn add --force " + path);
|
||||
break;
|
||||
case REMOVE:
|
||||
sys.CheckSystem("svn delete " + path);
|
||||
break;
|
||||
case CONFLICT:
|
||||
sys.CheckSystem("svn resolved " + path);
|
||||
break;
|
||||
case REPLACE: {
|
||||
SvnDel(path);
|
||||
String tp = AppendFileName(GetFileFolder(path), Format(Uuid::Create()));
|
||||
FileMove(path, tp);
|
||||
sys.CheckSystem(SvnCmd("update", w).Cat() << ' ' << path);
|
||||
MoveSvn(path, tp);
|
||||
sDeleteFolderDeep(path);
|
||||
FileMove(tp, path);
|
||||
Vector<String> ln = Split(Sys("svn status " + path), CharFilterCrLf);
|
||||
for(int l = 0; l < ln.GetCount(); l++) {
|
||||
String h = ln[l];
|
||||
if(h.GetCount() > 7) {
|
||||
String file = h.Mid(7);
|
||||
if(IsFullPath(file)) {
|
||||
h.Trim(7);
|
||||
if(h == "? ")
|
||||
sys.CheckSystem("svn add --force " + file);
|
||||
if(h == "! ")
|
||||
sys.CheckSystem("svn delete " + file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DELETEC:
|
||||
FileDelete(path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
l++;
|
||||
}
|
||||
sys.CheckSystem(SvnCmd("update", w).Cat() << w.working);
|
||||
}
|
||||
sys.Perform();
|
||||
}
|
||||
|
||||
void SvnSync::SetMsgs(const String& s)
|
||||
{
|
||||
LoadFromString(msgmap, s);
|
||||
}
|
||||
|
||||
String SvnSync::GetMsgs()
|
||||
{
|
||||
return StoreAsString(msgmap);
|
||||
}
|
||||
|
||||
bool IsSvnDir(const String& p)
|
||||
{
|
||||
return DirectoryExists(AppendFileName(p, ".svn")) || DirectoryExists(AppendFileName(p, "_svn"));
|
||||
}
|
||||
|
||||
#ifdef flagMAIN
|
||||
GUI_APP_MAIN
|
||||
{
|
||||
if(!CheckSvn())
|
||||
return;
|
||||
SvnSync ss;
|
||||
String mp = ConfigFile("usvn.msg");
|
||||
ss.SetMsgs(LoadFile(mp));
|
||||
ss.Perform();
|
||||
SaveFile(mp, ss.GetMsgs());
|
||||
}
|
||||
#endif
|
||||
#include "usvn.h"
|
||||
|
||||
bool CheckSvn()
|
||||
{
|
||||
String h;
|
||||
if(Sys("svn", h) >= 0)
|
||||
return true;
|
||||
#ifdef PLATFORM_WIN32
|
||||
Exclamation("Unable to execute svn.exe!&"
|
||||
"You can download svn client here: [^http://www.sliksvn.com/en/download^ http://www.sliksvn.com/en/download]");
|
||||
#else
|
||||
Exclamation("Unable to execute 'svn' binary!&Please install svn client.");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
SvnSync::SvnSync()
|
||||
{
|
||||
CtrlLayoutOKCancel(*this, "SvnSynchronize SVN repositories");
|
||||
list.AddIndex();
|
||||
list.AddIndex();
|
||||
list.AddColumn("Action");
|
||||
list.AddColumn("Path");
|
||||
list.AddColumn("Changes");
|
||||
list.ColumnWidths("170 500 100");
|
||||
list.NoCursor().EvenRowColor();
|
||||
list.SetLineCy(max(Draw::GetStdFontCy(), 20));
|
||||
list.WhenLeftClick = THISBACK(Diff);
|
||||
Sizeable().Zoomable();
|
||||
setup <<= THISBACK(Setup);
|
||||
BackPaint();
|
||||
}
|
||||
|
||||
void SvnSync::Setup()
|
||||
{
|
||||
works.Execute();
|
||||
SyncList();
|
||||
}
|
||||
|
||||
int CharFilterSvnMsg(int c)
|
||||
{
|
||||
return c >= 32 && c < 128 && c != '\"' ? c : 0;
|
||||
}
|
||||
|
||||
void SvnSync::SyncList()
|
||||
{
|
||||
list.Clear();
|
||||
for(int i = 0; i < works.GetCount(); i++) {
|
||||
SvnWork w = works[i];
|
||||
String path = GetFullPath(w.working);
|
||||
list.Add(REPOSITORY, path,
|
||||
AttrText("Working directory").SetFont(StdFont().Bold()).Ink(White).Paper(Blue),
|
||||
AttrText(path).SetFont(Arial(20).Bold()).Paper(Blue).Ink(White),
|
||||
AttrText("").SetFont(Arial(20).Bold()).Paper(Blue).Ink(White));
|
||||
list.SetLineCy(list.GetCount() - 1, 26);
|
||||
Vector<String> ln = Split(Sys("svn status " + path), CharFilterCrLf);
|
||||
bool actions = false;
|
||||
for(int pass = 0; pass < 2; pass++)
|
||||
for(int i = 0; i < ln.GetCount(); i++) {
|
||||
String h = ln[i];
|
||||
if(h.GetCount() > 7) {
|
||||
String file = TrimLeft(h.Mid(7));
|
||||
if(IsFullPath(file)) {
|
||||
actions = true;
|
||||
h.Trim(7);
|
||||
bool simple = h.Mid(1, 6) == " ";
|
||||
int action = simple ? String("MC?!~").Find(h[0]) : -1;
|
||||
if(h == " S ")
|
||||
action = REPLACE;
|
||||
String an;
|
||||
Color color;
|
||||
if(action < 0) {
|
||||
color = Black;
|
||||
if(simple && h[0] == 'A')
|
||||
an = "svn add";
|
||||
else
|
||||
if(simple && h[0] == 'D')
|
||||
an = "svn delete";
|
||||
else {
|
||||
an = h.Mid(0, 7);
|
||||
color = Gray;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int q = file.ReverseFind('.');
|
||||
if(action == ADD && q >= 0 && (file.Mid(q + 1) == "mine" ||
|
||||
file[q + 1] == 'r' && IsDigit(file[q + 2]))
|
||||
&& FileExists(file.Mid(0, q))) {
|
||||
action = DELETEC;
|
||||
an = "Delete";
|
||||
color = Black;
|
||||
}
|
||||
else {
|
||||
static const char *as[] = {
|
||||
"Modify", "Resolved", "Add", "Remove", "Replace"
|
||||
};
|
||||
static Color c[] = { LtBlue, Magenta, Green, LtRed, LtMagenta };
|
||||
an = as[action];
|
||||
color = c[action];
|
||||
}
|
||||
}
|
||||
if(pass == action < 0) {
|
||||
int ii = list.GetCount();
|
||||
list.Add(action, file,
|
||||
action < 0 ? Value(AttrText(an).Ink(color)) : Value(true),
|
||||
AttrText(" " + file.Mid(path.GetCount() + 1)).Ink(color));
|
||||
if(action >= 0) {
|
||||
list.SetCtrl(ii, 0, revert.Add().SetLabel("Revert\n" + an).NoWantFocus());
|
||||
Ctrl& b = diff.Add().SetLabel("Changes..").SizePos().NoWantFocus();
|
||||
b <<= THISBACK1(DoDiff, ii);
|
||||
list.SetCtrl(ii, 2, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(actions) {
|
||||
list.Add(MESSAGE, Null, AttrText("Commit message:").SetFont(StdFont().Bold()));
|
||||
list.SetLineCy(list.GetCount() - 1, (3 * EditField::GetStdHeight()) + 4);
|
||||
list.SetCtrl(list.GetCount() - 1, 1, message.Add().SetFilter(CharFilterSvnMsg).VSizePos(2, 2).HSizePos());
|
||||
int q = msgmap.Find(w.working);
|
||||
if(q >= 0) {
|
||||
message.Top() <<= msgmap[q];
|
||||
msgmap.Unlink(q);
|
||||
}
|
||||
}
|
||||
else
|
||||
list.Add(-1, Null, "", AttrText("Nothing to do").SetFont(StdFont().Italic()));
|
||||
}
|
||||
}
|
||||
|
||||
void SvnSync::DoDiff(int ii)
|
||||
{
|
||||
String f = list.Get(ii, 1);
|
||||
if(!IsNull(f))
|
||||
RunSvnDiff(f);
|
||||
}
|
||||
|
||||
void SvnSync::Diff()
|
||||
{
|
||||
int cr = list.GetClickRow();
|
||||
if(cr >= 0)
|
||||
DoDiff(cr);
|
||||
}
|
||||
|
||||
#ifdef PLATFORM_WIN32
|
||||
void sDeleteFolderDeep(const char *dir)
|
||||
{
|
||||
{
|
||||
FindFile ff(AppendFileName(dir, "*.*"));
|
||||
while(ff) {
|
||||
String name = ff.GetName();
|
||||
String p = AppendFileName(dir, name);
|
||||
if(ff.IsFile()) {
|
||||
SetFileAttributes(p, GetFileAttributes(p) & ~FILE_ATTRIBUTE_READONLY);
|
||||
FileDelete(p);
|
||||
}
|
||||
else
|
||||
if(ff.IsFolder())
|
||||
sDeleteFolderDeep(p);
|
||||
ff.Next();
|
||||
}
|
||||
}
|
||||
DirectoryDelete(dir);
|
||||
}
|
||||
#else
|
||||
void sDeleteFolderDeep(const char *path)
|
||||
{
|
||||
DeleteFolderDeep(path);
|
||||
}
|
||||
#endif
|
||||
|
||||
void SvnDel(const char *path)
|
||||
{
|
||||
FindFile ff(AppendFileName(path, "*.*"));
|
||||
while(ff) {
|
||||
if(ff.IsFolder()) {
|
||||
String dir = AppendFileName(path, ff.GetName());
|
||||
if(ff.GetName() == ".svn")
|
||||
sDeleteFolderDeep(dir);
|
||||
else
|
||||
SvnDel(dir);
|
||||
}
|
||||
ff.Next();
|
||||
}
|
||||
}
|
||||
|
||||
void SvnSync::Dir(const char *dir)
|
||||
{
|
||||
setup.Hide();
|
||||
works.Add(dir, Null, Null);
|
||||
}
|
||||
|
||||
void SvnSync::Perform()
|
||||
{
|
||||
if(!CheckSvn())
|
||||
return;
|
||||
const Vector<String>& cl = CommandLine();
|
||||
if(cl.GetCount())
|
||||
for(int i = 0; i < cl.GetCount(); i++) {
|
||||
if(cl[i] == "-") {
|
||||
works.Load(LoadFile(ConfigFile("svnworks")));
|
||||
DoSync();
|
||||
SaveFile(ConfigFile("svnworks"), works.Save());
|
||||
return;
|
||||
}
|
||||
String d = GetFullPath(cl[i]);
|
||||
if(!DirectoryExists(cl[i])) {
|
||||
Cerr() << cl[i] << " not a directory\n";
|
||||
SetExitCode(1);
|
||||
return;
|
||||
}
|
||||
works.Add(d, "", "");
|
||||
}
|
||||
else
|
||||
works.Add(GetCurrentDirectory(), "", "");
|
||||
setup.Hide();
|
||||
DoSync();
|
||||
}
|
||||
|
||||
void MoveSvn(const String& path, const String& tp)
|
||||
{
|
||||
FindFile ff(AppendFileName(path, "*.*"));
|
||||
while(ff) {
|
||||
String nm = ff.GetName();
|
||||
String s = AppendFileName(path, nm);
|
||||
String t = AppendFileName(tp, nm);
|
||||
if(ff.IsFolder())
|
||||
if(nm == ".svn")
|
||||
FileMove(s, t);
|
||||
else
|
||||
MoveSvn(s, t);
|
||||
ff.Next();
|
||||
}
|
||||
}
|
||||
|
||||
void SvnSync::DoSync()
|
||||
{
|
||||
SyncList();
|
||||
msgmap.Sweep();
|
||||
again:
|
||||
if(Execute() != IDOK || list.GetCount() == 0) {
|
||||
int repoi = 0;
|
||||
for(int i = 0; i < list.GetCount(); i++)
|
||||
if(list.Get(i, 0) == MESSAGE)
|
||||
msgmap.GetAdd(works[repoi++].working) = list.Get(i, 3);
|
||||
return;
|
||||
}
|
||||
bool changes = false;
|
||||
for(int i = 0; i < list.GetCount(); i++) {
|
||||
int action = list.Get(i, 0);
|
||||
Value v = list.Get(i, 2);
|
||||
if(action == MESSAGE) {
|
||||
if(changes && IsNull(list.Get(i, 3))
|
||||
&& !PromptYesNo("Commit message is empty.&Do you want to continue?"))
|
||||
goto again;
|
||||
changes = false;
|
||||
}
|
||||
else if(action != REPOSITORY && IsNumber(v) && (int)v)
|
||||
changes = true;
|
||||
}
|
||||
SysConsole sys;
|
||||
int repoi = 0;
|
||||
int l = 0;
|
||||
bool commit = false;
|
||||
while(l < list.GetCount()) {
|
||||
SvnWork w = works[repoi++];
|
||||
l++;
|
||||
String message;
|
||||
while(l < list.GetCount()) {
|
||||
int action = list.Get(l, 0);
|
||||
String path = list.Get(l, 1);
|
||||
if(action == MESSAGE && commit) {
|
||||
String msg = list.Get(l, 3);
|
||||
if(sys.CheckSystem(SvnCmd("commit", w).Cat() << w.working << " -m \"" << msg << "\""))
|
||||
msgmap.GetAdd(w.working) = msg;
|
||||
l++;
|
||||
break;
|
||||
}
|
||||
if(action == REPOSITORY)
|
||||
break;
|
||||
Value v = list.Get(l, 2);
|
||||
if(IsNumber(v) && (int)v == 0) {
|
||||
if(action == REPLACE || action == ADD)
|
||||
DeleteFolderDeep(path);
|
||||
if(action != ADD)
|
||||
sys.CheckSystem("svn revert " + path);
|
||||
}
|
||||
else {
|
||||
commit = true;
|
||||
switch(action) {
|
||||
case ADD:
|
||||
SvnDel(path);
|
||||
sys.CheckSystem("svn add --force " + path);
|
||||
break;
|
||||
case REMOVE:
|
||||
sys.CheckSystem("svn delete " + path);
|
||||
break;
|
||||
case CONFLICT:
|
||||
sys.CheckSystem("svn resolved " + path);
|
||||
break;
|
||||
case REPLACE: {
|
||||
SvnDel(path);
|
||||
String tp = AppendFileName(GetFileFolder(path), Format(Uuid::Create()));
|
||||
FileMove(path, tp);
|
||||
sys.CheckSystem(SvnCmd("update", w).Cat() << ' ' << path);
|
||||
MoveSvn(path, tp);
|
||||
sDeleteFolderDeep(path);
|
||||
FileMove(tp, path);
|
||||
Vector<String> ln = Split(Sys("svn status " + path), CharFilterCrLf);
|
||||
for(int l = 0; l < ln.GetCount(); l++) {
|
||||
String h = ln[l];
|
||||
if(h.GetCount() > 7) {
|
||||
String file = h.Mid(7);
|
||||
if(IsFullPath(file)) {
|
||||
h.Trim(7);
|
||||
if(h == "? ")
|
||||
sys.CheckSystem("svn add --force " + file);
|
||||
if(h == "! ")
|
||||
sys.CheckSystem("svn delete " + file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DELETEC:
|
||||
FileDelete(path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
l++;
|
||||
}
|
||||
sys.CheckSystem(SvnCmd("update", w).Cat() << w.working);
|
||||
}
|
||||
sys.Perform();
|
||||
}
|
||||
|
||||
void SvnSync::SetMsgs(const String& s)
|
||||
{
|
||||
LoadFromString(msgmap, s);
|
||||
}
|
||||
|
||||
String SvnSync::GetMsgs()
|
||||
{
|
||||
return StoreAsString(msgmap);
|
||||
}
|
||||
|
||||
bool IsSvnDir(const String& p)
|
||||
{
|
||||
return DirectoryExists(AppendFileName(p, ".svn")) || DirectoryExists(AppendFileName(p, "_svn"));
|
||||
}
|
||||
|
||||
#ifdef flagMAIN
|
||||
GUI_APP_MAIN
|
||||
{
|
||||
if(!CheckSvn())
|
||||
return;
|
||||
SvnSync ss;
|
||||
String mp = ConfigFile("usvn.msg");
|
||||
ss.SetMsgs(LoadFile(mp));
|
||||
ss.Perform();
|
||||
SaveFile(mp, ss.GetMsgs());
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue