reorganizing repo

git-svn-id: svn://ultimatepp.org/upp/trunk@9214 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2015-11-22 19:53:58 +00:00
parent e5d5257d47
commit f0e42f8693
265 changed files with 69272 additions and 0 deletions

View file

@ -0,0 +1,42 @@
uniform sampler2D Texture;
uniform vec4 GlyphColor;
uniform vec4 GlowColor;
uniform vec4 OutlineColor;
uniform bool Outline;
uniform bool Glow;
uniform bool Shadow;
const float AlphaCenter = 0.5;
const float DistanceScale = 25.0;
uniform float OutlineCenter;
uniform float GlowCenter;
void main()
{
vec4 color = texture2D(Texture, gl_TexCoord[0].xy);
float alpha = color.a;
float width = min(length(fwidth(gl_TexCoord[0])), 1.0) * DistanceScale;
vec4 finalColor = GlyphColor;
float ma = smoothstep(AlphaCenter - width, AlphaCenter + width, alpha);
finalColor.a = ma;
if(Outline)
{
float mo = smoothstep(OutlineCenter - width, OutlineCenter + width, alpha);
finalColor = mix(OutlineColor, finalColor, ma);
finalColor.a = mo;
}
if(Glow && alpha >= finalColor.a - 0.5)
{
float mg = smoothstep(AlphaCenter, GlowCenter, sqrt(alpha));
finalColor = mix(GlowColor, finalColor, ma);
finalColor.a = mg;
}
gl_FragColor = finalColor * GlyphColor.a;
}

View file

@ -0,0 +1,5 @@
void main()
{
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = ftransform();
}

51
rainbow/CoreGl/Blur.frag Normal file
View file

@ -0,0 +1,51 @@
uniform float sigma; // The sigma value for the gaussian function: higher value means more blur
// A good value for 9x9 is around 3 to 5
// A good value for 7x7 is around 2.5 to 4
// A good value for 5x5 is around 2 to 3.5
// ... play around with this based on what you need :)
uniform float blurSize; // This should usually be equal to
// 1.0f / texture_pixel_width for a horizontal blur, and
// 1.0f / texture_pixel_height for a vertical blur.
uniform sampler2D blurSampler; // Texture that will be blurred by this shader
const float numBlurPixelsPerSide = 3.0f;
// 9x9 - 4
// 7x7 - 3
// 5x5 - 2
uniform vec2 blurMultiplyVec;
// 1, 0 - vertical
// 0, 1 - horizontal
uniform vec3 gaussian;
uniform float grayStrength;
uniform float blurStrength;
void main() {
vec4 v = texture2D(blurSampler, gl_TexCoord[0].xy);
if(blurStrength > 0.0f)
{
vec4 avgValue = vec4(0.0f, 0.0f, 0.0f, 0.0f);
float coefficientSum = 0.0f;
vec3 incGaussian = gaussian;
avgValue += v * incGaussian.x;
coefficientSum += incGaussian.x;
incGaussian.xy *= incGaussian.yz;
for (float i = 1.0f; i <= numBlurPixelsPerSide; i++) {
vec2 pos = i * blurSize * blurMultiplyVec;
avgValue += texture2D(blurSampler, gl_TexCoord[0].xy - pos) * incGaussian.x;
avgValue += texture2D(blurSampler, gl_TexCoord[0].xy + pos) * incGaussian.x;
coefficientSum += 2.0f * incGaussian.x;
incGaussian.xy *= incGaussian.yz;
}
v = avgValue / coefficientSum;
}
float gray = dot(v.rgb, vec3(0.299, 0.587, 0.114));
vec4 grayColor = vec4(gray, gray, gray, v.a);
gl_FragColor = mix(v, grayColor, grayStrength);
}

5
rainbow/CoreGl/Blur.vert Normal file
View file

@ -0,0 +1,5 @@
void main()
{
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = ftransform();
}

View file

@ -0,0 +1,21 @@
#if defined(flagWINGL) || defined(flagLINUXGL)
#include <CtrlLib/CtrlLib.h>
NAMESPACE_UPP
void ChSysInit()
{
CtrlImg::Reset();
CtrlsImg::Reset();
ChReset();
}
void ChHostSkin()
{
ChSysInit();
}
END_UPP_NAMESPACE
#endif

238
rainbow/CoreGl/Clip.cpp Normal file
View file

@ -0,0 +1,238 @@
#if defined(flagWINGL) || defined(flagLINUXGL)
#include "TopFrame.h"
NAMESPACE_UPP
#define LLOG(x) // LOG(x)
static VectorMap<String, ClipData> fbClipboard;
void ClearClipboard()
{
GuiLock __;
fbClipboard.Clear();
}
void AppendClipboard(const char *format, const Value& data, String (*render)(const Value&))
{
GuiLock __;
ClipData& cd = fbClipboard.GetAdd(format);
cd.data = data;
cd.render = render;
}
static String sRawRender(const Value& v)
{
return v;
}
void AppendClipboard(const char *format, const String& data)
{
GuiLock __;
AppendClipboard(format, data, sRawRender);
}
void AppendClipboard(const char *format, const byte *data, int length)
{
GuiLock __;
AppendClipboard(format, String(data, length));
}
String ReadClipboard(const char *format)
{
GuiLock __;
int q = fbClipboard.Find(format);
return q >= 0 ? (*fbClipboard[q].render)(fbClipboard[q].data) : String();
}
void AppendClipboardText(const String& s)
{
AppendClipboard("text", ToSystemCharset(s));
}
void AppendClipboardUnicodeText(const WString& s)
{
AppendClipboard("wtext", (byte *)~s, 2 * s.GetLength());
}
const char *ClipFmtsText()
{
return "wtext;text";
}
String GetString(PasteClip& clip)
{
GuiLock __;
if(clip.Accept("wtext")) {
String s = ~clip;
return WString((const wchar *)~s, wstrlen((const wchar *)~s)).ToString();
}
if(clip.IsAvailable("text"))
return ~clip;
return Null;
}
WString GetWString(PasteClip& clip)
{
GuiLock __;
if(clip.Accept("wtext")) {
String s = ~clip;
return WString((const wchar *)~s, wstrlen((const wchar *)~s));
}
if(clip.IsAvailable("text"))
return (~clip).ToWString();
return Null;
}
bool AcceptText(PasteClip& clip)
{
return clip.Accept(ClipFmtsText());
}
static String sText(const Value& data)
{
return data;
}
static String sWText(const Value& data)
{
return Unicode__(WString(data));
}
void Append(VectorMap<String, ClipData>& data, const String& text)
{
data.GetAdd("text", ClipData(text, sText));
data.GetAdd("wtext", ClipData(text, sWText));
}
void Append(VectorMap<String, ClipData>& data, const WString& text)
{
data.GetAdd("text", ClipData(text, sText));
data.GetAdd("wtext", ClipData(text, sWText));
}
String GetTextClip(const WString& text, const String& fmt)
{
if(fmt == "text")
return text.ToString();
if(fmt == "wtext")
return Unicode__(text);
return Null;
}
String GetTextClip(const String& text, const String& fmt)
{
if(fmt == "text")
return text;
if(fmt == "wtext")
return Unicode__(text.ToWString());
return Null;
}
String ReadClipboardText()
{
String w = ReadClipboard("text");
return w.GetCount() ? w : ReadClipboardUnicodeText().ToString();
}
WString ReadClipboardUnicodeText()
{
String w = ReadClipboard("wtext");
if(w.GetCount())
return WString((const wchar *)~w, w.GetLength() / 2);
return ReadClipboard("text").ToWString();
}
bool IsClipboardAvailable(const char *id)
{
return fbClipboard.Find(id) >= 0;
}
bool IsClipboardAvailableText()
{
return IsClipboardAvailable("text") || IsClipboardAvailable("wtext");
}
const char *ClipFmtsImage()
{
static const char *q;
ONCELOCK {
static String s = "dib;" + ClipFmt<Image>();
q = s;
}
return q;
}
bool AcceptImage(PasteClip& clip)
{
GuiLock __;
return clip.Accept(ClipFmtsImage());
}
Image GetImage(PasteClip& clip)
{
GuiLock __;
Image m;
if(Accept<Image>(clip)) {
LoadFromString(m, ~clip);
if(!m.IsEmpty())
return m;
}
return Null;
}
Image ReadClipboardImage()
{
GuiLock __;
PasteClip d = Ctrl::Clipboard();
return GetImage(d);
}
String sImage(const Value& image)
{
Image img = image;
return StoreAsString(const_cast<Image&>(img));
}
String GetImageClip(const Image& img, const String& fmt)
{
GuiLock __;
if(img.IsEmpty()) return Null;
if(fmt == ClipFmt<Image>())
return sImage(img);
return Null;
}
void AppendClipboardImage(const Image& img)
{
GuiLock __;
if(img.IsEmpty()) return;
AppendClipboard(ClipFmt<Image>(), img, sImage);
}
bool AcceptFiles(PasteClip& clip)
{
if(clip.Accept("files")) {
clip.SetAction(DND_COPY);
return true;
}
return false;
}
bool IsAvailableFiles(PasteClip& clip)
{
return clip.IsAvailable("files");
}
Vector<String> GetFiles(PasteClip& clip)
{
GuiLock __;
Vector<String> f;
return f;
}
END_UPP_NAMESPACE
#endif

199
rainbow/CoreGl/Console.cpp Normal file
View file

@ -0,0 +1,199 @@
#if defined(flagWINGL) || defined(flagLINUXGL)
#include "Console.h"
NAMESPACE_UPP
void Console::Paint(Draw& w)
{
Size sz = GetSize();
#ifndef COLOR_ALPHA
SystemDraw& sw = (SystemDraw&) w;
sw.alpha = 100.f;
Color frame = Yellow;
Color body = Black;
#else
Color frame = Yellow().Alpha(100);
Color body = Black().Alpha(100);
#endif
w.DrawRect(sz, body);
w.DrawRect(0, 0, sz.cx, 1, frame);
w.DrawRect(sz.cx - 1, 1, 1, sz.cy - 1, frame);
w.DrawRect(0, 1, 1, sz.cy, frame);
w.DrawRect(1, sz.cy - 1, sz.cx - 2, 1, frame);
//DrawFrame(w, sz, Yellow);
//w.DrawImage(sz.cx - 18, sz.cy - 21, LinuxGlImg::ResizeMarker());
w.DrawRect(1, sz.cy - 22, sz.cx - 2, 1, frame);
w.Clip(5, 5, sz.cx - 10, sz.cy - 5 - 21);
#ifndef COLOR_ALPHA
sw.alpha = 255.f;
#endif
int y = 5;
//int ty = Draw::GetStdFontCy() + 2;
int ty = 12 + 2;
for(int i = 0; i < fixedText.GetCount(); i++)
{
w.DrawText(5, y, fixedText[i].text, StdFont(), fixedText[i].ink);
y += ty;
}
if(fixedText.GetCount() > 0 && floatText.GetCount() > 0)
{
#ifndef COLOR_ALPHA
sw.alpha = 150.f;
#endif
w.DrawRect(5, y, sz.cx - 10, 1, frame);
#ifndef COLOR_ALPHA
sw.alpha = 255.f;
#endif
y += 2;
}
int lines = (sz.cy - y - 22) / ty;
int n = fceil(sb.GetPos() / double(ty));
int maxn = min(n + lines, currLine);
while(n < maxn)
{
LineInfo& lf = floatText[n];
w.DrawText(5, y, lf.text, StdFont(), lf.ink);
y += ty;
++n;
}
w.End();
}
void Console::Log(int line, const char* text, Color ink)
{
LineInfo& lf = fixedText.GetAdd(line);
lf.ink = ink;
lf.text = text;
}
void Console::Log(const char* text, Color ink)
{
bool isend = sb.IsEnd();
if(++currLine >= maxLine)
{
currLine = maxLine;
for(int i = 0; i < maxLine - 1; i++)
floatText[i] = floatText[i + 1];
}
int ty = Draw::GetStdFontCy() + 2;
int total = currLine * ty;
int fcnt = fixedText.GetCount();
sb.SetTotal(total + 5 + 22);
if(isend)
sb.GoEnd();
LineInfo& lf = floatText[currLine - 1];
lf.ink = ink;
lf.text = text;
}
void Console::LeftDown(Point p, dword keys)
{
SetCapture();
pos = p;
rs = GetSize();
tl = GetScreenRect().TopLeft();
Size sz = GetSize();
resize = p.x > sz.cx - 18 && p.y > sz.cy - 18;
}
void Console::LeftUp(Point p, dword keys)
{
ReleaseCapture();
}
void Console::MouseMove(Point p, dword keys)
{
if(HasCapture())
{
Rect r = GetRect();
bool isend = sb.IsEnd();
if(resize)
{
tl = Point(p.x - pos.x, p.y - pos.y);
SetConsoleRect(r.left, r.top, max(2, rs.cx + tl.x), max(2, rs.cy + tl.y));
}
else
{
tl += Point(p.x - pos.x, p.y - pos.y);
SetConsoleRect(tl.x, tl.y, r.Width(), r.Height());
}
if(isend)
sb.GoEnd();
}
}
void Console::Layout()
{
}
void Console::SetConsoleRect(int x, int y, int cx, int cy)
{
int width = cx < 0 ? 300 : cx;
int height = cy < 0 ? 5 + 5 + (Draw::GetStdFontCy() + 2) * 30 + 3 : cy;
SetRect(x, y, width, height);
}
void Console::SetLines(int lines)
{
maxLine = lines;
floatText.SetCount(lines);
}
void Console::Init(Ctrl& parent)
{
if(!init)
return;
init = false;
this->parent = &parent;
SetConsoleRect(parent.GetSize().cx - 5 - 300, 5);
sb.SetFrameSize(5, false).SetAlign(AlignedFrame::RIGHT);
Show();
}
void Console::Show(bool b)
{
if(IsOpen())
{
if(!b)
Close();
}
else
{
if(b)
PopUp(parent, true, false);
}
}
void Console::Clear()
{
currLine = 0;
sb.Clear();
}
Console::Console() : init(true), resize(false)
{
Add(sb.RightPos(2, 7).VSizePos(2, 22));
Add(clear.LeftPos(2, 50).BottomPos(2, 18));
clear.SetLabel("Clear");
//clear.bg = Yellow;
//clear.alpha = 150.f;
clear <<= THISBACK(Clear);
SetLines(3000);
currLine = 0;
scrollLine = 0;
}
END_UPP_NAMESPACE
#endif

51
rainbow/CoreGl/Console.h Normal file
View file

@ -0,0 +1,51 @@
#ifndef _CoreGl_Console_h_
#define _CoreGl_Console_h_
#include "ControlPanel.h"
#include "Scrollbar.h"
NAMESPACE_UPP
struct Console : Ctrl
{
Ctrl* parent;
SlimScrollBar sb;
SlimButton clear;
struct LineInfo : Moveable<LineInfo> {
Color ink;
String text;
};
bool init;
bool resize;
Point pos;
Point tl;
Size rs;
int currLine;
int scrollLine;
int maxLine;
VectorMap<int, LineInfo> fixedText;
Vector<LineInfo> floatText;
void Init(Ctrl& parent);
void SetConsoleRect(int x, int y, int cx = -1, int cy = -1);
virtual void Paint(Draw& w);
virtual void LeftDown(Point p, dword keys);
virtual void LeftUp(Point p, dword keys);
virtual void MouseMove(Point p, dword keys);
virtual void Layout();
void Log(int line, const char* text, Color ink = White);
void Log(const char* text, Color ink = White);
void SetLines(int lines);
void Show(bool b = true);
void Clear();
typedef Console CLASSNAME;
Console();
};
END_UPP_NAMESPACE
#endif

View file

@ -0,0 +1,211 @@
#if defined(flagWINGL) || defined(flagLINUXGL)
#include "ControlPanel.h"
NAMESPACE_UPP
ValueSlider::ValueSlider()
{
pos = 0;
shaded = true;
immediate = false;
src = Color(255, 255, 0);
dst = Color(255, 153, 51);
}
void ValueSlider::Paint(Draw &w)
{
Size sz = GetSize();
/*w.DrawRect(0, 0, sz.cx, 1, Black);
w.DrawRect(0, sz.cy - 1, sz.cx, 1, Black);
w.DrawRect(0, 0, 1, sz.cy, Black);
w.DrawRect(sz.cx - 1, 0, 1, sz.cy, Black);*/
int t = (int) (((pos - minValue) * sz.cx) / (maxValue - minValue));
if(t < 1) t = 1;
if(t > sz.cx - 1) t = sz.cx - 1;
if(shaded)
{
for(int i = 1; i < t; i++)
w.DrawRect(i, 1, 1, sz.cy - 2, Blend(src, dst, 256 * i / (sz.cx - 1)));
}
else
{
w.DrawRect(Rect(1, 1, t, sz.cy - 1), dst);
}
if(t < sz.cx - 1)
w.DrawRect(Rect(t, 1, sz.cx - 1, sz.cy - 1), Color(245, 245, 255));
String s = Format("%s : %.2f", text, pos);
Size tsz = GetTextSize(s, StdFont());
w.DrawText((sz.cx - tsz.cx) / 2, (sz.cy - tsz.cy) / 2, s);
}
void ValueSlider::LeftDown(Point p, dword keyflags)
{
pos = minValue + (p.x * (maxValue - minValue)) / (float) GetSize().cx;
Refresh();
SetCapture();
if(immediate)
WhenAction();
}
void ValueSlider::LeftUp(Point p, dword keyflags)
{
ReleaseCapture();
if(!immediate)
WhenAction();
}
void ValueSlider::MouseMove(Point p, dword keyflags)
{
if(HasCapture())
{
pos = minValue + (p.x * (maxValue - minValue)) / (float) GetSize().cx;
if(pos > maxValue) pos = maxValue;
if(pos < minValue) pos = minValue;
Refresh();
if(immediate)
WhenAction();
}
}
void ValueSlider::SetPos(float p, float minv, float maxv)
{
pos = p;
minValue = minv;
maxValue = maxv;
Refresh();
}
float ValueSlider::GetPos()
{
return pos;
}
void SlimButton::Paint(Draw &w)
{
SystemDraw& sw = (SystemDraw&) w;
float a = sw.alpha;
sw.alpha = alpha;
Size sz = GetSize();
if(HasMouseIn(sz))
w.DrawRect(sz, bg);
sw.alpha = a;
Size tsz = GetTextSize(label, StdFont());
w.DrawText((sz.cx - tsz.cx) / 2, (sz.cy - tsz.cy) / 2, label, StdFont(), fg);
}
void SlimButton::LeftDown(Point p, dword keyflags)
{
SetCapture();
}
void SlimButton::LeftUp(Point p, dword keyflags)
{
ReleaseCapture();
Action();
}
void SlimButton::MouseMove(Point p, dword keyflags)
{
}
void SlimButton::SetLabel(const char* s)
{
label = s;
}
SlimButton::SlimButton()
{
fg = White;
bg = Black;
alpha = 255.f;
}
InfoPanel::InfoPanel() : init(true), parent(NULL)
{
Add(alphaSlider.RightPos(199, 100).VSizePos(1, 0));
Add(angleSlider.RightPos(100, 100).VSizePos(1, 0));
Add(scaleSlider.RightPos(1, 100).VSizePos(1, 0));
alphaSlider.text = "Alpha";
angleSlider.text = "Angle";
scaleSlider.text = "Scale";
alphaSlider.shaded = true;
angleSlider.shaded = true;
scaleSlider.shaded = true;
alphaSlider.immediate = true;
angleSlider.immediate = true;
scaleSlider.immediate = true;
alphaSlider.SetPos(255.f, 0.f, 255.f);
angleSlider.SetPos(0.f, 0.f, 360.f);
scaleSlider.SetPos(1.f, 1.f, 5.f);
}
void InfoPanel::Paint(Draw& w)
{
Size sz = GetSize();
Size wsz = screenRect.GetSize();
Color frameColor = Color(183, 183, 183);
Color bgColor = Color(102, 102, 102);
w.DrawRect(sz, bgColor);
w.DrawRect(0, 0, 1, sz.cy, frameColor);
w.DrawRect(0, 0, sz.cx, 1, frameColor);
w.DrawRect(sz.cx - 1, 0, 1, sz.cy, frameColor);
String info = Format("FPS: %.2f, Textures: %d (%d), Size: %d, %d", GetFps(), resources.textures.GetCount(), resources.bindedTextures, wsz.cx, wsz.cy);
w.DrawText(5, sz.cy - 18, info, StdFont(), White);
}
void InfoPanel::Init(Ctrl& parent, float angle, float scale, float alpha)
{
const int width = 585;
SetRect((screenRect.Width() - width) / 2, screenRect.Height() - 22, width, 22);
if(!init)
return;
init = false;
this->parent = &parent;
Show();
alphaSlider.SetPos(alpha, 0.f, 255.f);
angleSlider.SetPos(angle, 0.f, 360.f);
scaleSlider.SetPos(scale, 1.f, 5.f);
}
void InfoPanel::Show(bool b)
{
if(IsOpen())
{
if(!b)
Close();
}
else
{
if(b)
PopUp(parent, true, false);
}
}
float InfoPanel::GetAlpha()
{
return alphaSlider.GetPos();
}
float InfoPanel::GetAngle()
{
return angleSlider.GetPos();
}
float InfoPanel::GetScale()
{
return scaleSlider.GetPos();
}
END_UPP_NAMESPACE
#endif

View file

@ -0,0 +1,71 @@
#ifndef _rainbow_CoreGl_ControlPanel_h_
#define _rainbow_CoreGl_ControlPanel_h_
#include <CtrlLib/CtrlLib.h>
NAMESPACE_UPP
struct ValueSlider : Ctrl
{
bool shaded;
bool immediate;
Color src;
Color dst;
float pos;
float minValue;
float maxValue;
String text;
typedef ValueSlider CLASSNAME;
ValueSlider();
virtual void Paint(Draw &w);
virtual void LeftDown(Point p, dword keyflags);
virtual void LeftUp(Point p, dword keyflags);
virtual void MouseMove(Point p, dword keyflags);
void SetPos(float p, float minValue, float maxValue);
float GetPos();
Callback WhenLeftUp;
};
struct SlimButton : Ctrl
{
Color fg;
Color bg;
float alpha;
String label;
virtual void Paint(Draw &w);
virtual void LeftDown(Point p, dword keyflags);
virtual void LeftUp(Point p, dword keyflags);
virtual void MouseMove(Point p, dword keyflags);
void SetLabel(const char* s);
SlimButton();
};
struct InfoPanel : Ctrl
{
bool init;
Ctrl* parent;
ValueSlider alphaSlider;
ValueSlider angleSlider;
ValueSlider scaleSlider;
float GetAlpha();
float GetAngle();
float GetScale();
void Init(Ctrl& parent, float angle = 0.f, float scale = 1.f, float alpha = 255.f);
void Show(bool b = true);
virtual void Paint(Draw& w);
typedef InfoPanel CLASSNAME;
InfoPanel();
};
END_UPP_NAMESPACE
#endif

305
rainbow/CoreGl/CoreGl.h Normal file
View file

@ -0,0 +1,305 @@
#ifndef _CoreGl_CoreGl_h_
#define _CoreGl_CoreGl_h_
#ifndef GLEW_STATIC
#define GLEW_STATIC
#endif
#define DRAW_ON_TIMER 0
#define DRAW_ON_IDLE 1
#define DRAW_ON_EVENT 2
#define CLIP_MODE 2
/*
0 - Scissor clip
1 - Plane clip
2 - Stencil clip
3 - Manual clip
*/
#include "Gl.h"
#include <Painter/Painter.h>
#include "Shaders.h"
#include "Fbo.h"
NAMESPACE_UPP
struct FrameInfo {
int64 curr_tick_count;
float fps;
float frame_factor;
float frame_skip;
int64 frame_time;
FrameInfo() : fps(0.f), frame_factor(1.f), frame_skip(60.f), frame_time(0), curr_tick_count(0)
{}
};
extern FrameInfo frameInfo;
float GetFps();
#define IMAGECLASS CoreGlImg
#define IMAGEFILE <CoreGl/CoreGl.iml>
#include <Draw/iml_header.h>
#include "Resources.brc"
typedef Rect_<float> RectF;
typedef Point_<float> PointF;
#include "FontGl.h"
#include "ResGl.h"
enum TransformState {
TS_BEFORE_CTRL_PAINT,
TS_AFTER_CTRL_PAINT,
TS_BEFORE_PAINT,
TS_AFTER_PAINT,
TS_BEFORE_SCREEN,
TS_AFTER_SCREEN
};
#define TEXEL_OFFSET 0.325f
class SystemDraw : public Draw {
public:
virtual dword GetInfo() const;
virtual Size GetPageSize() const;
bool CanSetSurface() { return false; }
void PlaneEquation(double eq[4], float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3);
void SetClipRect(const Rect& r);
void ScissorClip(const Rect& r);
void PlaneClip(const Rect& r);
void StencilClip(const Rect& r, int mode = 0, bool exlude = false);
void SetClip(const Rect& r, int mode = 0, bool exclude = false);
virtual void BeginOp();
virtual void EndOp();
virtual void OffsetOp(Point p);
virtual bool ClipOp(const Rect& r);
virtual bool ClipoffOp(const Rect& r);
virtual bool ExcludeClipOp(const Rect& r);
virtual bool IntersectClipOp(const Rect& r);
virtual bool IsPaintingOp(const Rect& r) const;
virtual Rect GetPaintRect() const;
virtual void DrawRectOp(int x, int y, int cx, int cy, Color color);
virtual void DrawImageOp(int x, int y, int cx, int cy, const Image& img, const Rect& src, Color color);
virtual void DrawImageOp(float x0, float y0, float z0, float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3, const Image& img, const Rect& src, Color color);
virtual void DrawTextureOp(const RectF& r, int textureId, int width, int height, const RectF& src);
virtual void DrawLineOp(int x1, int y1, int x2, int y2, int width, Color color);
virtual void DrawPolyPolylineOp(const Point *vertices, int vertex_count,
const int *counts, int count_count,
int width, Color color, Color doxor);
virtual void DrawPolyPolyPolygonOp(const Point *vertices, int vertex_count,
const int *subpolygon_counts, int scc,
const int *disjunct_polygon_counts, int dpcc,
Color color, int width, Color outline,
uint64 pattern, Color doxor);
virtual void DrawArcOp(const Rect& rc, Point start, Point end, int width, Color color);
virtual void DrawEllipseOp(const Rect& r, Color color, int pen, Color pencolor);
virtual void DrawTextOp(int x, int y, int angle, const wchar *text, Font font,
Color ink, int n, const int *dx);
virtual Size GetNativeDpi() const;
virtual void BeginNative();
virtual void EndNative();
virtual int GetCloffLevel() const;
void Text(int x, int y, int angle, const wchar *text, Font font, Color ink,
int outlineStrength, Color outlineColor,
int glowStrength, Color glowColor,
int n, const int *dx);
void ImageColoring(bool b = true) { image_coloring = b; }
RectF UnProject(const RectF& r, float& depth);
void UnProject(float* vtx, float sx, float sy, float dx, float dy);
void UnProject(float& x, float& y, float &z);
void SetVtx(float* vtx, float sx, float sy, float dx, float dy);
void SetProjectionMode(int mode);
bool IsPerspectiveProjection() { return projection_mode == 1; }
bool IsOrthogonalProjection() { return projection_mode == 0; }
private:
static SystemDraw* systemDraw;
friend class FontInfo;
friend class Font;
OpenGLFont fi;
struct Cloff : Moveable<Cloff> {
bool clipping;
bool exclude;
Point org;
Rect drawing_clip;
};
struct MatrixStack : Moveable<MatrixStack>
{
double projection_matrix[16];
double modelview_matrix[16];
int projection_mode;
};
float current_color[4];
float vtx[8];
float crd[8];
double projection_matrix[16];
void SetVec(float* v, float sx, float sy, float dx, float dy);
void SetVec(float* v, int sx, int sy, int dx, int dy);
void SaveCurrentColor();
void RestoreLastColor();
public:
Rect drawing_clip;
Size drawing_size;
Point drawing_offset;
Rect clip;
float r, g, b, a;
float alpha;
float angle;
float scale;
static float blurStrength;
static float grayStrength;
private:
Array<Cloff> cloff;
Array<MatrixStack> mstack;
int ci;
int cn;
int cd;
int mi;
bool image_coloring;
int projection_mode;
void Reset();
protected:
SystemDraw();
void InitClip(const Rect& clip);
void Init();
public:
static SystemDraw& Get() { return *systemDraw; }
static void Flush() { /*glFlush();*/ }
Point GetOffset() const { return drawing_offset; }
SystemDraw(Size sz);
virtual ~SystemDraw();
void ViewPort(int width = -1, int height = -1);
void OrthogonalView(bool clear_modelview = true);
void PerspectiveView(bool clear_modelview = true);
void ApplyTransforms();
void Clear(bool ontransforms = false);
void PushContext();
void PopContext();
float GetAspect() { return drawing_size.cx / (float) drawing_size.cy; };
};
struct BackDraw__ : public SystemDraw {
BackDraw__() {}
};
class BackDraw : public BackDraw__ { // Dummy only, as we are running in GlobalBackBuffer mode
Size size;
Draw *painting;
Point painting_offset;
ImageBuffer ib;
public:
virtual bool IsPaintingOp(const Rect& r) const;
public:
void Put(SystemDraw& w, int x, int y) {}
void Put(SystemDraw& w, Point p) { Put(w, p.x, p.y); }
void Create(SystemDraw& w, int cx, int cy) {}
void Create(SystemDraw& w, Size sz) { Create(w, sz.cx, sz.cy); }
void Destroy() {}
void SetPaintingDraw(Draw& w, Point off) { painting = &w; painting_offset = off; }
BackDraw();
~BackDraw();
};
struct ImageDraw__ {
ImageBuffer image;
ImageBuffer alpha;
ImageDraw__(int cx, int cy) : image(cx, cy), alpha(cx, cy) {}
};
class ImageDraw : private ImageDraw__, public BufferPainter {
BufferPainter alpha_painter;
bool has_alpha;
Image Get(bool pm) const;
public:
Draw& Alpha();
operator Image() const { return Get(true); }
Image GetStraight() const { return Get(false); }
ImageDraw(Size sz);
ImageDraw(int cx, int cy);
};
void DrawDragRect(SystemDraw& w, const Rect& rect1, const Rect& rect2, const Rect& clip, int n, Color color, int type, int animation);
class PrinterJob { // Dummy only...
NilDraw nil;
Vector<int> pages;
public:
Draw& GetDraw() { return nil; }
operator Draw&() { return GetDraw(); }
const Vector<int>& GetPages() const { return pages; }
int operator[](int i) const { return 0; }
int GetPageCount() const { return 0; }
bool Execute() { return false; }
PrinterJob& Landscape(bool b = true) { return *this; }
PrinterJob& MinMaxPage(int minpage, int maxpage) { return *this; }
PrinterJob& PageCount(int n) { return *this; }
PrinterJob& CurrentPage(int currentpage) { return *this; }
PrinterJob& Name(const char *_name) { return *this; }
PrinterJob(const char *name = NULL) {}
~PrinterJob() {}
};
class TopWindowFrame;
struct InfoPanel;
struct Console;
void GlLog(int line, const char* text, Color ink = White);
void GlLog(const char* text, Color ink = White);
void GlLogF(Color ink, const char* fmt, ...);
void GlLogF(const char* fmt, ...);
#define GUIPLATFORM_CTRL_TOP_DECLS Ctrl *owner_window;
#define GUIPLATFORM_CTRL_DECLS_INCLUDE <CoreGl/Ctrl.h>
#define GUIPLATFORM_PASTECLIP_DECLS \
bool dnd; \
friend struct DnDLoop;
#define GUIPLATFORM_TOPWINDOW_DECLS_INCLUDE <CoreGl/Top.h>
#ifdef flagLINUXGL
#define GUIPLATFORM_INCLUDE_AFTER <LinuxGl/After.h>
#endif
#ifdef flagWINGL
#define GUIPLATFORM_INCLUDE_AFTER <WinGl/After.h>
#endif
END_UPP_NAMESPACE
#endif

60
rainbow/CoreGl/CoreGl.iml Normal file
View file

@ -0,0 +1,60 @@
PREMULTIPLIED
IMAGE_ID(arrow)
IMAGE_ID(ibeam)
IMAGE_ID(wait)
IMAGE_ID(no)
IMAGE_ID(sizeall)
IMAGE_ID(sizehorz)
IMAGE_ID(sizeright)
IMAGE_ID(sizeleft)
IMAGE_ID(sizevert)
IMAGE_ID(sizetopleft)
IMAGE_ID(sizetop)
IMAGE_ID(sizetopright)
IMAGE_ID(sizebottomleft)
IMAGE_ID(sizebottom)
IMAGE_ID(sizebottomright)
IMAGE_ID(overlap)
IMAGE_ID(maximize)
IMAGE_ID(close)
IMAGE_ID(bgtitle)
IMAGE_ID(title)
IMAGE_ID(border)
IMAGE_ID(hand)
IMAGE_ID(ResizeMarker)
IMAGE_BEGIN_DATA
IMAGE_DATA(120,156,237,90,205,75,85,65,20,159,50,211,66,9,137,118,46,218,180,233,79,136,160,109,203,192,130,32,218,228,34,90)
IMAGE_DATA(180,171,69,148,249,130,136,32,66,131,44,9,75,203,2,53,107,241,54,34,42,234,194,15,4,63,240,3,30,162,8,34)
IMAGE_DATA(136,136,160,43,221,157,230,61,223,199,120,238,220,51,231,204,187,207,10,238,25,14,58,119,126,191,51,103,126,231,220,123)
IMAGE_DATA(159,31,170,74,93,80,105,59,173,78,164,191,128,146,25,8,57,0,32,226,192,193,193,69,216,223,191,196,229,192,222,222)
IMAGE_DATA(21,216,221,189,6,59,59,215,57,28,216,222,190,1,91,91,55,97,115,243,14,172,175,215,187,56,176,177,81,175,113,247)
IMAGE_DATA(97,109,237,33,172,174,62,130,84,234,41,197,129,149,149,199,176,188,252,68,227,26,97,113,241,21,204,207,191,133,217,217)
IMAGE_DATA(230,48,14,44,45,189,132,133,133,215,48,55,215,4,51,51,173,48,53,213,9,147,147,223,97,98,162,221,198,209,152,102)
IMAGE_DATA(152,158,126,175,113,109,48,62,222,13,35,35,35,89,255,5,195,195,157,152,163,99,181,106,92,27,140,141,117,194,232,232)
IMAGE_DATA(239,60,94,21,106,105,114,52,230,179,246,14,24,26,250,1,131,131,63,161,191,63,73,158,119,96,160,29,250,250,190,230)
IMAGE_DATA(227,36,147,221,36,62,153,252,18,200,177,171,235,91,168,62,54,13,58,58,62,81,120,235,190,45,45,239,68,125,216,212)
IMAGE_DATA(244,70,220,235,137,196,115,209,30,13,13,207,196,123,8,176,65,43,87,231,212,73,85,145,113,133,10,175,50,55,235,161)
IMAGE_DATA(161,239,243,155,163,249,127,127,45,228,188,1,93,84,149,22,174,92,139,86,126,84,56,174,103,56,181,61,31,72,55,176)
IMAGE_DATA(199,129,39,57,22,108,40,135,192,6,56,12,108,158,35,193,250,228,226,115,86,31,45,255,66,125,101,253,89,163,71,101)
IMAGE_DATA(118,80,194,89,156,107,220,155,132,195,47,102,93,146,103,177,252,64,1,25,49,236,79,31,127,126,88,94,82,62,55,134)
IMAGE_DATA(100,221,181,7,39,71,234,156,148,185,52,150,240,109,57,73,122,197,118,205,151,207,141,227,115,223,249,220,183,174,88,118)
IMAGE_DATA(99,62,144,14,163,6,95,239,34,51,95,255,197,240,115,46,141,131,249,62,113,192,48,52,117,198,192,56,155,30,84,172)
IMAGE_DATA(48,60,231,154,121,29,231,109,59,11,198,98,190,143,219,226,248,228,17,149,30,81,213,197,22,203,118,22,23,23,239,143)
IMAGE_DATA(93,18,195,22,71,202,199,113,124,249,40,14,109,53,250,99,127,165,42,203,56,38,187,2,80,24,238,33,194,112,84,211)
IMAGE_DATA(218,76,169,227,191,121,56,121,68,165,135,185,238,85,151,184,208,113,161,253,2,50,19,118,225,138,21,216,188,230,227,182)
IMAGE_DATA(56,62,121,68,165,135,185,238,85,151,10,93,234,178,108,169,45,27,178,19,193,194,186,4,183,9,132,230,206,131,255,235)
IMAGE_DATA(107,212,249,40,93,40,61,57,185,24,235,5,171,214,227,116,118,4,50,65,162,19,1,201,164,92,28,23,190,88,14,22)
IMAGE_DATA(219,197,193,197,226,238,23,182,119,177,60,73,29,36,103,53,121,170,132,181,240,237,17,107,47,198,79,166,210,173,81,231)
IMAGE_DATA(163,116,161,244,228,228,98,172,23,204,124,50,81,22,200,18,21,132,216,236,88,159,66,92,14,22,223,197,161,10,201,197)
IMAGE_DATA(227,117,28,75,146,3,7,111,114,212,49,235,207,205,77,218,83,113,195,198,13,91,18,14,55,55,113,195,198,175,210,210)
IMAGE_DATA(173,81,231,163,116,161,244,228,228,98,172,23,44,254,144,31,228,224,98,113,247,11,219,187,88,158,164,14,146,179,154,60)
IMAGE_DATA(85,194,90,248,246,136,181,23,171,244,136,200,172,119,154,225,54,60,21,203,23,207,201,3,227,93,123,70,133,231,232,83)
IMAGE_DATA(42,93,204,107,146,58,241,45,130,102,114,37,39,17,203,134,137,241,209,227,37,245,226,91,20,79,166,171,213,213,161,155)
IMAGE_DATA(227,181,244,60,231,54,172,109,205,118,157,138,131,215,93,216,48,14,133,149,226,37,249,72,206,235,171,39,149,39,117,14)
IMAGE_DATA(210,78,233,145,179,186,186,86,184,253,160,23,238,190,232,133,123,31,123,65,58,207,7,43,203,252,109,38,1,103,46,247)
IMAGE_DATA(192,249,91,75,80,219,152,126,9,11,231,233,54,47,215,35,251,179,44,247,126,58,242,230,119,153,249,255,212,185,57,229)
IMAGE_DATA(137,68,34,198,151,8,159,155,187,220,167,23,50,205,228,248,197,8,245,233,5,227,32,149,74,29,249,26,134,197,56,3)
IMAGE_DATA(111,253,4,18,134,71,251,228,99,112,241,46,156,13,159,115,41,62,204,209,153,165,120,39,135,210,148,137,229,225,207,234)
IMAGE_DATA(225,99,250,161,6,148,199,56,26,199,177,63,147,104,81,173,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
IMAGE_END_DATA(1056, 23)

57
rainbow/CoreGl/CoreGl.upp Normal file
View file

@ -0,0 +1,57 @@
uses
Painter;
options(WIN32) "-D_WIN32 -DGLEW_STATIC";
file
Gl.h,
CoreGl.h,
FontGl.h,
ResGl.h,
ControlPanel.h,
ControlPanel.cpp,
Scrollbar.h,
Scrollbar.cpp,
Console.h,
Console.cpp,
Draw.cpp,
DrawOp.cpp,
DrawText.cpp,
Clip.cpp,
Ctrl.h,
Ctrl.cpp,
Dnd.cpp,
Event.cpp,
Wnd.cpp,
Image.cpp,
Top.h,
Top.cpp,
TopFrame.h,
TopFrame.cpp,
ChSysInit.cpp,
Util.cpp,
Glew readonly separator,
glew.h,
glxew.h,
wglew.h,
glew.c,
SceneGraph readonly separator,
SceneGraph.h,
SceneGraph.cpp,
Resources readonly separator,
Resources.cpp,
Resources.brc,
Fbo.h,
Fbo.cpp,
Shaders.h,
Shaders.cpp,
AlphaMag.vert,
AlphaMag.frag,
Blur.vert,
Blur.frag,
Fonts/TahomaB.fnt,
Fonts/TahomaB_0.png,
Fonts/TahomaN.fnt,
Fonts/TahomaN_0.png,
CoreGl.iml;

97
rainbow/CoreGl/Ctrl.cpp Normal file
View file

@ -0,0 +1,97 @@
#if defined(flagWINGL) || defined(flagLINUXGL)
#include "TopFrame.h"
#define LLOG(x) // DLOG(x)
NAMESPACE_UPP
int Ctrl::Xbuttons;
int Ctrl::Xbuttontime;
Point Ctrl::Xbuttonpos;
void Ctrl::GuiPlatformConstruct()
{
cliptobounds = true;
}
void Ctrl::GuiPlatformRemove()
{
}
void Ctrl::GuiPlatformGetTopRect(Rect& r) const
{
}
bool Ctrl::GuiPlatformRefreshFrameSpecial(const Rect& r)
{
return true;
}
bool Ctrl::GuiPlatformSetFullRefreshSpecial()
{
return false;
}
void Ctrl::PaintCaret(SystemDraw& w)
{
}
String GuiPlatformGetKeyDesc(dword key)
{
return Null;
}
void Ctrl::GuiPlatformSelection(PasteClip&)
{
}
void GuiPlatformAdjustDragImage(ImageBuffer&)
{
}
bool GuiPlatformHasSizeGrip()
{
return true;
}
void GuiPlatformGripResize(TopWindow *q)
{
q->GripResize();
}
Color GuiPlatformGetScreenPixel(int x, int y)
{
return Black;
}
void GuiPlatformAfterMenuPopUp()
{
}
void Ctrl::InstallPanicBox()
{
}
void Ctrl::ApplyLayout()
{
GuiLock __;
for(Ctrl *q = GetFirstChild(); q; q = q->GetNext())
q->ApplyLayout();
}
String Ctrl::Name() const {
GuiLock __;
#ifdef CPU_64
String s = String(typeid(*this).name()) + " : 0x" + FormatIntHex(this);
#else
String s = String(typeid(*this).name()) + " : " + Format("0x%x", (int) this);
#endif
if(IsChild())
s << "(parent " << String(typeid(*parent).name()) << ")";
return s;
}
END_UPP_NAMESPACE
#endif

83
rainbow/CoreGl/Ctrl.h Normal file
View file

@ -0,0 +1,83 @@
//$ class Ctrl {
static Ptr<Ctrl> desktop;
static Vector<Ctrl *> topctrl;
static InfoPanel infoPanel;
static float angle;
static float scale;
static float alpha;
static Point glCursorPos;
static Image glCursorImage;
static Rect glCaretRect;
static int glCaretTm;
static int64 glEventLoop;
static int64 glEndSessionLoop;
bool cliptobounds:1;
int FindTopCtrl() const;
static void SyncTopWindows();
void DestroyWnd();
void NewTop() { top = new Top; top->owner_window = NULL; }
void PutForeground();
static void MouseEventGl(Ptr<Ctrl> t, int event, Point p, int zdelta);
static void DrawLine(const Vector<Rect>& clip, int x, int y, int cx, int cy, bool horz,
const byte *pattern, int animation);
static void DragRectDraw0(const Vector<Rect>& clip, const Rect& rect, int n,
const byte *pattern, int animation);
friend class TopWindowFrame;
friend class SystemDraw;
friend struct DnDLoop;
void SetOpen(bool b) { isopen = b; }
protected:
static int PaintLock;
public:
static int Xbuttons;
static int Xbuttontime;
static Point Xbuttonpos;
static Console console;
static Rect screenRect;
static bool screenReady;
static void InitGl();
static void ExitGl();
static void EndSession();
static bool DoMouseGl(Ctrl* q, int event, Point p, int zdelta);
static void DoMouseGl(int event, Point p, int zdelta = 0);
static bool DoKeyGl(dword key, int cnt);
static void CursorSync(Draw& w);
static void MouseSync(Draw& w);
static void SetDesktop(Ctrl& q);
static Ctrl *GetDesktop() { return desktop; }
static void SetWindowSize(Size sz);
static Size GetScreenSize() { return screenRect.GetSize(); }
static dword GetCaretTm() { return glCaretTm; }
static void ResetCaretTm() { glCaretTm = GetTickCount(); }
static void DrawScreen();
Ctrl& ClipToBounds(bool b = true) { cliptobounds = b; return *this; }
bool IsClipToBounds() const { return cliptobounds; }
virtual void ApplyTransform(TransformState state) {}
virtual void PostPaint(Draw& w) {}
virtual void ApplyLayout();
void DragRectDraw(const Rect& rect1, const Rect& rect2, const Rect& clip, int n,
Color color, int type, int animation);
static Ctrl *FindMouseTopCtrl();
enum { DRAWDRAGRECT_SCREEN = 0x8000 };
//$ };

150
rainbow/CoreGl/Dnd.cpp Normal file
View file

@ -0,0 +1,150 @@
#if defined(flagWINGL) || defined(flagLINUXGL)
#include "TopFrame.h"
NAMESPACE_UPP
#define LLOG(x) // LOG(x)
// --------------------------------------------------------------------------------------------
Ptr<Ctrl> sDnDSource;
Ctrl * Ctrl::GetDragAndDropSource()
{
return sDnDSource;
}
struct DnDLoop : LocalLoop {
const VectorMap<String, ClipData> *data;
Vector<String> fmts;
Image move, copy, reject;
Ptr<Ctrl> target;
int action;
byte actions;
void Sync();
String GetData(const String& f);
void DnD(bool paste);
virtual void LeftUp(Point, dword);
virtual bool Key(dword, int);
virtual void MouseMove(Point p, dword);
virtual Image CursorImage(Point, dword);
};
Ptr<DnDLoop> dndloop;
bool PasteClip::IsAvailable(const char *fmt) const
{
GuiLock __;
return dnd ? dndloop && FindIndex(dndloop->fmts, fmt) >= 0
: IsClipboardAvailable(fmt);
}
String DnDLoop::GetData(const String& f)
{
GuiLock __;
int i = data->Find(f);
String d;
if(i >= 0)
d = (*data)[i].Render();
else
if(sDnDSource)
d = sDnDSource->GetDropData(f);
return d;
}
String PasteClip::Get(const char *fmt) const
{
return dnd ? dndloop ? dndloop->GetData(fmt) : String() : ReadClipboard(fmt);
}
void PasteClip::GuiPlatformConstruct()
{
dnd = false;
}
void DnDLoop::DnD(bool paste)
{
PasteClip d;
d.paste = paste;
d.accepted = false;
d.allowed = (byte)actions;
d.action = GetCtrl() ? DND_COPY : DND_MOVE;
d.dnd = true;
if(target)
target->DnD(GetMousePos(), d);
action = d.IsAccepted() ? d.GetAction() : DND_NONE;
}
void DnDLoop::Sync()
{
GuiLock __;
Ptr<Ctrl> t = FindMouseTopCtrl();
if(t != target)
if(target)
target->DnDLeave();
target = t;
DnD(false);
}
void DnDLoop::LeftUp(Point, dword)
{
GuiLock __;
LLOG("DnDLoop::LeftUp");
DnD(true);
EndLoop();
}
void DnDLoop::MouseMove(Point p, dword)
{
GuiLock __;
LLOG("DnDLoop::MouseMove");
Sync();
}
bool DnDLoop::Key(dword, int)
{
GuiLock __;
LLOG("DnDLoop::Key");
Sync();
return false;
}
Image DnDLoop::CursorImage(Point, dword)
{
GuiLock __;
return action == DND_MOVE ? move : action == DND_COPY ? copy : reject;
}
int Ctrl::DoDragAndDrop(const char *fmts, const Image& sample, dword actions,
const VectorMap<String, ClipData>& data)
{
GuiLock __;
DnDLoop d;
d.actions = (byte)actions;
d.reject = actions & DND_EXACTIMAGE ? CtrlCoreImg::DndNone() : MakeDragImage(CtrlCoreImg::DndNone(), sample);
if(actions & DND_COPY)
d.copy = actions & DND_EXACTIMAGE ? sample : MakeDragImage(CtrlCoreImg::DndCopy(), sample);
if(actions & DND_MOVE)
d.move = actions & DND_EXACTIMAGE ? sample : MakeDragImage(CtrlCoreImg::DndMoveX11(), sample);
d.SetMaster(*this);
d.data = &data;
d.action = DND_NONE;
d.fmts = Split(fmts, ';');
dndloop = &d;
sDnDSource = this;
d.Run();
sDnDSource = NULL;
SyncCaret();
LLOG("DoDragAndDrop finished");
return d.action;
}
void Ctrl::SetSelectionSource(const char *fmts) {}
END_UPP_NAMESPACE
#endif

189
rainbow/CoreGl/Draw.cpp Normal file
View file

@ -0,0 +1,189 @@
#if defined(flagWINGL) || defined(flagLINUXGL)
#include <CtrlCore/CtrlCore.h>
NAMESPACE_UPP
#define LLOG(x) // LOG(x)
#define LTIMING(x) // RTIMING(x)
FrameInfo frameInfo;
SystemDraw* SystemDraw::systemDraw = NULL;
float SystemDraw::blurStrength = 0;
float SystemDraw::grayStrength = 0;
dword SystemDraw::GetInfo() const
{
return 0;
}
Size SystemDraw::GetPageSize() const
{
return Size(0, 0);
}
Size SystemDraw::GetNativeDpi() const
{
return Size(96, 96);
}
void SystemDraw::BeginNative()
{
}
void SystemDraw::EndNative()
{
}
int SystemDraw::GetCloffLevel() const
{
return ci;
}
void SystemDraw::InitClip(const Rect& clip)
{
GuiLock __;
drawing_clip = clip;
}
void SystemDraw::Reset() {
systemDraw = this;
cloff.SetCount(32);
mstack.SetCount(32);
ci = 0;
cn = 0;
cd = 0;
mi = 0;
drawing_offset = Point(0, 0);
alpha = 255;
r = g = b = a = 255;
angle = 0;
scale = 1;
image_coloring = true;
projection_mode = 0;
}
SystemDraw::SystemDraw() {
GuiLock __;
Reset();
}
SystemDraw::SystemDraw(Size sz) {
GuiLock __;
Reset();
drawing_clip = sz;
drawing_size = sz;
clip = sz;
Init();
}
void SystemDraw::Init()
{
//glVertexPointer(2, GL_FLOAT, 0, vtx);
//glTexCoordPointer(2, GL_FLOAT, 0, crd);
glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glDisable(GL_ALPHA_TEST);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
#if CLIP_MODE == 0
glEnable(GL_SCISSOR_TEST);
#elif CLIP_MODE == 1
glEnable(GL_CLIP_PLANE0);
glEnable(GL_CLIP_PLANE1);
glEnable(GL_CLIP_PLANE2);
glEnable(GL_CLIP_PLANE3);
#elif CLIP_MODE == 2
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 0, ~0);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glClearStencil(0);
#endif
glEnable(GL_LINE_SMOOTH);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor(0.f, 0.f, 0.f, 1.f);
glClearDepth(1.0f);
glEnableClientState(GL_VERTEX_ARRAY);
//glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glColor4f(1.f, 1.f, 1.f, 1.f);
}
void SystemDraw::Clear(bool ontransforms)
{
GuiLock __;
if(ontransforms && (angle == 0 && scale == 1))
return;
#if CLIP_MODE == 0
glDisable(GL_SCISSOR_TEST);
#endif
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
#if CLIP_MODE == 0
glEnable(GL_SCISSOR_TEST);
#endif
}
void SystemDraw::ViewPort(int width, int height)
{
GuiLock __;
glViewport(0, 0, (GLsizei) width < 0 ? drawing_size.cx : width, (GLsizei) height < 0 ? drawing_size.cy : height);
}
void SystemDraw::OrthogonalView(bool clear_modelview)
{
GuiLock __;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, drawing_size.cx, drawing_size.cy, 0, -100, 100);
glMatrixMode(GL_MODELVIEW);
if(clear_modelview)
glLoadIdentity();
}
void SystemDraw::PerspectiveView(bool clear_modelview)
{
GuiLock __;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, GetAspect(), 1.f, 100.0f);
glMatrixMode(GL_MODELVIEW);
if(clear_modelview)
glLoadIdentity();
}
void SystemDraw::ApplyTransforms()
{
GuiLock __;
float dx = (float) drawing_size.cx / 2;
float dy = (float) drawing_size.cy / 2;
glTranslatef(dx, dy, 0.f);
glRotatef(angle, 0, 0, 1);
glScalef(scale, scale, 1);
glTranslatef(-dx, -dy, 0.f);
}
void SystemDraw::PushContext()
{
GuiLock __;
MatrixStack& m = mstack[mi++];
glGetDoublev(GL_PROJECTION_MATRIX, m.projection_matrix);
glGetDoublev(GL_MODELVIEW_MATRIX, m.modelview_matrix);
m.projection_mode = projection_mode;
}
void SystemDraw::PopContext()
{
GuiLock __;
MatrixStack& m = mstack[--mi];
glMatrixMode(GL_PROJECTION);
glLoadMatrixd(m.projection_matrix);
glMatrixMode(GL_MODELVIEW);
glLoadMatrixd(m.modelview_matrix);
projection_mode = m.projection_mode;
}
SystemDraw::~SystemDraw() {
}
END_UPP_NAMESPACE
#endif

657
rainbow/CoreGl/DrawOp.cpp Normal file
View file

@ -0,0 +1,657 @@
#if defined(flagWINGL) || defined(flagLINUXGL)
#include <CtrlCore/CtrlCore.h>
NAMESPACE_UPP
#define LLOG(x) // LOG(x)
#define LTIMING(x) // RTIMING(x)
void SystemDraw::PlaneEquation(double eq[4], float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3)
{
eq[0] = y1 * (z2 - z3) +
y2 * (z3 - z1) +
y3 * (z1 - z2);
eq[1] = z1 * (x2 - x3) +
z2 * (x3 - x1) +
z3 * (x1 - x2);
eq[2] = x1 * (y2 - y3) +
x2 * (y3 - y1) +
x3 * (y1 - y2);
eq[3] = -(x1 * (y2 * z3 - y3 * z2) +
x2 * (y3 * z1 - y1 * z3) +
x3 * (y1 * z2 - y2 * z1));
}
void SystemDraw::SetClipRect(const Rect& r)
{
clip = r;
#if CLIP_MODE != 2
for(int i = 0; i < ci; i++)
if(!cloff[i].exclude)
clip &= cloff[i].drawing_clip;
#endif
}
void SystemDraw::ScissorClip(const Rect& r)
{
glScissor(r.left, drawing_size.cy - r.top - r.Height(), r.Width(), r.Height());
}
void SystemDraw::PlaneClip(const Rect& r)
{
float cl = (float) r.left;
float ct = (float) r.top;
float cr = (float) r.right;
float cb = (float) r.bottom;
double eq[4];
PlaneEquation(eq, cl, ct, 0, cl, cb, 0, cl, cb, +1.0f);
glClipPlane(GL_CLIP_PLANE0, eq);
PlaneEquation(eq, cr, ct, 0, cr, cb, 0, cr, cb, -1.0f);
glClipPlane(GL_CLIP_PLANE1, eq);
PlaneEquation(eq, cl, ct, 0, cr, ct, 0, cr, ct, -1.0f);
glClipPlane(GL_CLIP_PLANE2, eq);
PlaneEquation(eq, cl, cb, 0, cr, cb, 0, cr, cb, +1.0f);
glClipPlane(GL_CLIP_PLANE3, eq);
}
void SystemDraw::SetVec(float* v, float sx, float sy, float dx, float dy)
{
v[0] = sx; v[1] = dy;
v[2] = sx; v[3] = sy;
v[4] = dx; v[5] = dy;
v[6] = dx; v[7] = sy;
}
void SystemDraw::SetVec(float* v, int sx, int sy, int dx, int dy)
{
v[0] = (float) sx; v[1] = (float) dy;
v[2] = (float) sx; v[3] = (float) sy;
v[4] = (float) dx; v[5] = (float) dy;
v[6] = (float) dx; v[7] = (float) sy;
}
void SystemDraw::StencilClip(const Rect& r, int mode, bool exclude)
{
float vtx[12];
SetVtx(vtx, (float) r.left, (float) r.top, (float) r.right, (float) r.bottom);
glVertexPointer(projection_mode ? 3 : 2, GL_FLOAT, 0, vtx);
int prev_cn = cn;
glColorMask(0, 0, 0, 0);
if(mode == 0)
{
if(exclude)
{
glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
glStencilFunc(GL_ALWAYS, 255, ~0);
}
else
{
++cn;
glStencilOp(GL_KEEP, GL_INCR, GL_INCR);
glStencilFunc(GL_GEQUAL, cn, ~0);
}
}
else
{
if(exclude)
{
glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
glStencilFunc(GL_ALWAYS, cn, ~0);
}
else
{
--cn;
glStencilOp(GL_KEEP, GL_DECR, GL_DECR);
glStencilFunc(GL_ALWAYS, cn, ~0);
}
}
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
if(exclude)
glStencilFunc(GL_GREATER, 255, ~0);
else
glStencilFunc(GL_EQUAL, cn, ~0);
glColorMask(1, 1, 1, 1);
}
void SystemDraw::SetClip(const Rect& r, int mode, bool exclude)
{
SetClipRect(r);
#if CLIP_MODE == 0
ScissorClip(clip);
#elif CLIP_MODE == 1
PlaneClip(clip);
#elif CLIP_MODE == 2
StencilClip(clip, mode, exclude);
#endif
}
void SystemDraw::BeginOp()
{
Cloff& w = cloff[ci++];
w.clipping = false;
w.exclude = false;
w.org = drawing_offset;
w.drawing_clip = drawing_clip;
}
void SystemDraw::EndOp()
{
ASSERT(ci);
#if CLIP_MODE == 2
if(cloff[ci - 1].clipping)
SetClip(drawing_clip, 1, cloff[ci - 1].exclude);
#endif
Cloff& w = cloff[--ci];
drawing_offset = w.org;
drawing_clip = w.drawing_clip;
#if CLIP_MODE != 2
if(cloff[ci].clipping)
SetClip(drawing_clip);
#endif
}
void SystemDraw::OffsetOp(Point p)
{
GuiLock __;
BeginOp();
drawing_offset += p;
}
bool SystemDraw::ClipOp(const Rect& r)
{
GuiLock __;
BeginOp();
cloff[ci - 1].clipping = true;
drawing_clip = r + drawing_offset;
SetClip(drawing_clip);
return true;
}
bool SystemDraw::ClipoffOp(const Rect& r)
{
GuiLock __;
BeginOp();
cloff[ci - 1].clipping = true;
drawing_clip = r + drawing_offset;
drawing_offset += r.TopLeft();
SetClip(drawing_clip);
return true;
}
bool SystemDraw::ExcludeClipOp(const Rect& r)
{
GuiLock __;
ASSERT(ci > 0);
cloff[ci - 1].clipping = true;
cloff[ci - 1].exclude = true;
drawing_clip = r + drawing_offset;
SetClip(drawing_clip, 0, true);
return true;
}
bool SystemDraw::IntersectClipOp(const Rect& r)
{
GuiLock __;
Cloff& w = cloff[ci];
drawing_clip = r + drawing_offset;
SetClip(drawing_clip);
return true;
}
bool SystemDraw::IsPaintingOp(const Rect& r) const
{
return true;
}
Rect SystemDraw::GetPaintRect() const
{
GuiLock __;
return drawing_clip;
}
void SystemDraw::DrawRectOp(int x, int y, int cx, int cy, Color color)
{
GuiLock __;
if(IsNull(color))
return;
if(cx <= 0 || cy <= 0) return;
float sx = (float) x + drawing_offset.x;
float sy = (float) y + drawing_offset.y;
float dx = sx + cx;
float dy = sy + cy;
#if CLIP_MODE == 3
float cl = (float) clip.left;
float ct = (float) clip.top;
float cr = (float) clip.right;
float cb = (float) clip.bottom;
if(sx > cr || sy > cb)
return;
if(dx < cl || dy < ct)
return;
if(sx < cl)
sx = cl;
if(sy < ct)
sy = ct;
if(dx > cr)
dx = cr;
if(dy > cb)
dy = cb;
#endif
#ifdef COLOR_ALPHA
glColor4ub(color.GetR(), color.GetG(), color.GetB(), color.GetA() >= 255 ? (int) alpha : color.GetA());
#else
glColor4ub(color.GetR(), color.GetG(), color.GetB(), (int) alpha);
#endif
float vtx[12];
SetVtx(vtx, sx, sy, dx, dy);
glVertexPointer(projection_mode ? 3 : 2, GL_FLOAT, 0, vtx);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
#ifdef COLOR_ALPHA
glColor4ub(255, 255, 255, 255);
#else
glColor4ub(255, 255, 255, (int) alpha);
#endif
}
void SystemDraw::DrawImageOp(int x, int y, int cx, int cy, const Image& img, const Rect& src, Color color)
{
GuiLock __;
if(cx <= 0 || cy <= 0) return;
float sx = (float) x + drawing_offset.x;
float sy = (float) y + drawing_offset.y;
float dx = sx + cx;
float dy = sy + cy;
#if CLIP_MODE == 3
if(sx > clip.right || sy > clip.bottom)
return;
if(dx < clip.left || dy < clip.top)
return;
#endif
float tl = (float) src.left;
float tr = (float) src.right;
float tt = (float) src.top;
float tb = (float) src.bottom;
float sw = (float) src.GetWidth();
float sh = (float) src.GetHeight();
#if CLIP_MODE == 3
float cl = (float) clip.left;
float ct = (float) clip.top;
float cr = (float) clip.right;
float cb = (float) clip.bottom;
if(sx < cl)
{
float dl = cl - sx;
tl += dl * sw / (float) cx;
sx = cl;
}
if(sy < ct)
{
float dt = ct - sy;
tt += dt * sh / (float) cy;
sy = ct;
}
if(dx > cr)
{
float dr = dx - cr;
tr -= dr * sw / (float) cx;
dx = cr;
}
if(dy > cb)
{
float db = dy - cb;
tb -= db * sh / (float) cy;
dy = cb;
}
#endif
const TextureResource& t = resources.Bind(img, Resources::AUTO_ATLAS | Resources::NEAREST_FILTERING);
float tw = 1.f / (float) t.realWidth;
float th = 1.f / (float) t.realHeight;
tl = (tl + t.x + TEXEL_OFFSET) * tw;
tr = (tr + t.x - TEXEL_OFFSET) * tw;
tt = (tt + t.y + TEXEL_OFFSET) * th;
tb = (tb + t.y - TEXEL_OFFSET) * th;
if(image_coloring)
{
if(IsNull(color))
glColor4ub(255, 255, 255, (int) alpha);
else
{
#ifdef COLOR_ALPHA
glColor4ub(color.GetR(), color.GetG(), color.GetB(), color.GetA() >= 255 ? (int) alpha : color.GetA());
#else
glColor4ub(color.GetR(), color.GetG(), color.GetB(), (int) alpha);
#endif
}
}
else
glColor4ub(255, 255, 255, 255);
float vtx[12];
SetVtx(vtx, sx, sy, dx, dy);
float crd[] = {
tl, tb,
tl, tt,
tr, tb,
tr, tt
};
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, crd);
glVertexPointer(projection_mode ? 3 : 2, GL_FLOAT, 0, vtx);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
}
void SystemDraw::DrawTextureOp(const RectF& r, int textureId, int width, int height, const RectF& src)
{
GuiLock __;
float sx = r.left + drawing_offset.x;
float sy = r.top + drawing_offset.y;
float dx = sx + r.GetWidth();
float dy = sy + r.GetHeight();
float tl = src.left;
float tr = src.right;
float tt = src.top;
float tb = src.bottom;
resources.Bind(textureId, Resources::NEAREST_FILTERING);
float tw = 1.f / (float) (width);
float th = 1.f / (float) (height);
tl = (tl + TEXEL_OFFSET) * tw;
tr = (tr - TEXEL_OFFSET) * tw;
tt = (tt + TEXEL_OFFSET) * th;
tb = (tb - TEXEL_OFFSET) * th;
float vtx[12];
SetVtx(vtx, sx, sy, dx, dy);
float crd[] = {
tl, tt,
tl, tb,
tr, tt,
tr, tb
};
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, crd);
glVertexPointer(projection_mode ? 3 : 2, GL_FLOAT, 0, vtx);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
}
void SystemDraw::DrawImageOp(float x0, float y0, float z0, float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3, const Image& img, const Rect& src, Color color)
{
GuiLock __;
float tl = (float) src.left;
float tr = (float) src.right;
float tt = (float) src.top;
float tb = (float) src.bottom;
float sw = (float) src.GetWidth();
float sh = (float) src.GetHeight();
const TextureResource& t = resources.Bind(img, Resources::AUTO_ATLAS | Resources::NEAREST_FILTERING);
float tw = 1.f / (float) t.realWidth;
float th = 1.f / (float) t.realHeight;
tl = (tl + t.x + TEXEL_OFFSET) * tw;
tr = (tr + t.x - TEXEL_OFFSET) * tw;
tt = (tt + t.y + TEXEL_OFFSET) * th;
tb = (tb + t.y - TEXEL_OFFSET) * th;
if(image_coloring)
{
if(IsNull(color))
glColor4ub(255, 255, 255, (int) alpha);
else
{
#ifdef COLOR_ALPHA
glColor4ub(color.GetR(), color.GetG(), color.GetB(), color.GetA());
#else
glColor4ub(color.GetR(), color.GetG(), color.GetB(), (int) alpha);
#endif
}
}
glEnable(GL_TEXTURE_2D);
float vtx[] = {
x3, y3, z3,
x0, y0, z0,
x2, y2, z2,
x1, y1, z1
};
float crd[] = {
tl, tb,
tl, tt,
tr, tb,
tr, tt
};
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, crd);
glVertexPointer(3, GL_FLOAT, 0, vtx);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
}
void SystemDraw::DrawLineOp(int x1, int y1, int x2, int y2, int width, Color color)
{
GuiLock __;
#ifdef COLOR_ALPHA
glColor4ub(color.GetR(), color.GetG(), color.GetB(), color.GetA());
#else
glColor4ub(color.GetR(), color.GetG(), color.GetB(), (int) alpha);
#endif
glLineWidth((GLfloat) width);
glBegin(GL_LINES);
glVertex2i(x1 + drawing_offset.x, y1 + drawing_offset.y);
glVertex2i(x2 + drawing_offset.x, y2 + drawing_offset.y);
glEnd();
}
void SystemDraw::DrawPolyPolylineOp(const Point *vertices, int vertex_count, const int *counts, int count_count, int width, Color color, Color doxor)
{
GuiLock __;
}
void SystemDraw::DrawPolyPolyPolygonOp(const Point *vertices, int vertex_count, const int *subpolygon_counts, int scc, const int *disjunct_polygon_counts, int dpcc, Color color, int width, Color outline, uint64 pattern, Color doxor)
{
GuiLock __;
}
void SystemDraw::DrawArcOp(const Rect& rc, Point start, Point end, int width, Color color)
{
GuiLock __;
}
void SystemDraw::DrawEllipseOp(const Rect& r, Color color, int pen, Color pencolor)
{
GuiLock __;
}
void SystemDraw::SaveCurrentColor()
{
GuiLock __;
glGetFloatv(GL_CURRENT_COLOR, current_color);
}
void SystemDraw::RestoreLastColor()
{
GuiLock __;
glColor4f(current_color[0], current_color[1], current_color[2], current_color[3]);
}
RectF SystemDraw::UnProject(const RectF& r, float& depth)
{
GuiLock __;
double projMat[16];
double modelMat[16];
int viewPort[4];
glGetDoublev(GL_PROJECTION_MATRIX, projMat);
glGetDoublev(GL_MODELVIEW_MATRIX, modelMat);
glGetIntegerv(GL_VIEWPORT, viewPort);
RectF fr;
double x, y, z;
gluUnProject(r.left, r.top, 0.99f, modelMat, projMat, viewPort, &x, &y, &z);
depth = (float) z;
fr.left = (float) x;
fr.top = (float) y;
gluUnProject(r.right, r.bottom, 0.99f, modelMat, projMat, viewPort, &x, &y, &z);
fr.right = (float) x;
fr.bottom = (float) y;
return fr;
}
void SystemDraw::UnProject(float* vtx, float sx, float sy, float dx, float dy)
{
GuiLock __;
double projMat[16];
double modelMat[16] = {
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
};
int viewPort[4];
glGetDoublev(GL_PROJECTION_MATRIX, projMat);
//glGetDoublev(GL_MODELVIEW_MATRIX, modelMat);
glGetIntegerv(GL_VIEWPORT, viewPort);
double xs, ys, xd, yd, z;
gluUnProject(sx, drawing_size.cy - sy, 0.99, modelMat, projMat, viewPort, &xs, &ys, &z);
gluUnProject(dx, drawing_size.cy - dy, 0.99, modelMat, projMat, viewPort, &xd, &yd, &z);
vtx[0] = (float) xs;
vtx[1] = (float) yd;
vtx[2] = (float) z;
vtx[3] = (float) xs;
vtx[4] = (float) ys;
vtx[5] = (float) z;
vtx[6] = (float) xd;
vtx[7] = (float) yd;
vtx[8] = (float) z;
vtx[9] = (float) xd;
vtx[10] = (float) ys;
vtx[11] = (float) z;
}
void SystemDraw::UnProject(float& x, float& y, float &z)
{
GuiLock __;
double projMat[16];
double modelMat[16] = {
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
};
int viewPort[4];
glGetDoublev(GL_PROJECTION_MATRIX, projMat);
glGetIntegerv(GL_VIEWPORT, viewPort);
double xd, yd, zd;
gluUnProject(x, drawing_size.cy - y, 0.99, modelMat, projMat, viewPort, &xd, &yd, &zd);
x = (float) xd;
y = (float) yd;
z = (float) zd;
}
void SystemDraw::SetVtx(float* vtx, float sx, float sy, float dx, float dy)
{
if(projection_mode == 1)
{
UnProject(vtx, sx, sy, dx, dy);
}
else
{
vtx[0] = sx;
vtx[1] = dy;
vtx[2] = sx;
vtx[3] = sy;
vtx[4] = dx;
vtx[5] = dy;
vtx[6] = dx;
vtx[7] = sy;
}
}
void SystemDraw::SetProjectionMode(int mode)
{
if(mode != projection_mode)
{
projection_mode = mode;
if(projection_mode)
PerspectiveView(false);
else
OrthogonalView(false);
}
}
END_UPP_NAMESPACE
#endif

321
rainbow/CoreGl/DrawText.cpp Normal file
View file

@ -0,0 +1,321 @@
#if defined(flagWINGL) || defined(flagLINUXGL)
#include <CtrlCore/CtrlCore.h>
NAMESPACE_UPP
void OpenGLFont::LoadBrc(const byte* xml, const byte** imagesData, const int* imagesSize, int imagesCount)
{
Parse((const char*) xml, false);
for(int i = 0; i < imagesCount; i++)
{
MemStream ms((void*) imagesData[i], imagesSize[i]);
Image img = StreamRaster::LoadAny(ms);
images.Add(img);
if(preload)
resources.Add(img, true);
}
}
void OpenGLFont::Load(const String& fileName, bool preload)
{
String filePath = GetDataFile(fileName);
String xml = LoadFile(filePath);
Parse(xml, true);
}
void OpenGLFont::Parse(const char* xml, bool parsePages)
{
chars.SetCount(512);
XmlParser p(xml);
while(!p.IsTag())
p.Skip();
p.PassTag("font");
while(!p.End())
{
if(p.TagE("common"))
{
scaleW = (float) p.Double("scaleW");
scaleH = (float) p.Double("scaleH");
lineHeight = (float) p.Double("lineHeight");
base = (float) p.Double("base");
}
else if(p.Tag("pages"))
{
while(!p.End())
{
if(p.TagE("page"))
{
if(parsePages)
{
String fileName = p["file"];
Image img = StreamRaster::LoadFileAny(GetDataFile(fileName));
images.Add(img);
if(preload)
resources.Add(img, true);
}
pages.Add(StrInt(p["id"]));
}
else
p.Skip();
}
}
else if(p.Tag("chars"))
{
while(!p.End())
{
if(p.TagE("char"))
{
int id = p.Int("id");
CharInfo& ci = chars[id];
ci.id = id;
ci.x = (float) p.Double("x");
ci.y = (float) p.Double("y");
ci.width = (float) p.Double("width");
ci.height = (float) p.Double("height");
ci.xoffset = (float) p.Double("xoffset");
ci.yoffset = (float) p.Double("yoffset");
ci.xadvance = (float) p.Double("xadvance");
ci.page = p.Int("page");
}
else
p.Skip();
}
}
else if(p.Tag("kernings"))
{
while(!p.End())
{
if(p.TagE("kerning"))
{
int first = p.Int("first");
int second = p.Int("second");
float amount = (float) p.Double("amount");
VectorMap<int, float>& vm = kerns.GetAdd(first);
vm.Add(second, amount);
}
else
p.Skip();
}
}
else
p.Skip();
}
}
void OpenGLFont::UpdateTextures()
{
if(texturesUpdated)
return;
for(int i = 0; i < images.GetCount(); i++)
{
const TextureResource& t = resources.Bind(images[i], Resources::LINEAR_FILTERING);
pages[i] = t.serialId;
}
texturesUpdated = true;
}
float ConvStrength(float min, float max, float p)
{
return min + (max - min) * p / 100.f;
}
void SystemDraw::Text(int x, int y, int angle, const wchar *text, Font font, Color ink, int outlineStrength, Color outlineColor, int glowStrength, Color glowColor, int n, const int *dx)
{
if(!text)
return;
const wchar* s = text;
OpenGLFont& fi = resources.GetFont(font);
glEnable(GL_TEXTURE_2D);
#if CLIP_MODE == 3
float cl = (float) clip.left;
float ct = (float) clip.top;
float cr = (float) clip.right;
float cb = (float) clip.bottom;
#endif
fi.UpdateTextures();
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
alphaMagProg.Start();
const float ic = 1.f / 255.f;
float outlineCenter = ConvStrength(0.1f, 0.45f, (float) 100 - min(outlineStrength, 100));
float glowCenter = ConvStrength(0.55f, 0.95f, (float) 100 - min(glowStrength, 100));
#ifdef COLOR_ALPHA
float ac = alpha / 255.f;
int inkA = ink.GetA();
int outlineA = outlineColor.GetA();
int glowA = glowColor.GetA();
#else
float ac = alpha;
int inkA = 1;
int outlineA = 1;
int glowA = 1;
#endif
alphaMagProg.SetUniform("GlyphColor", ink.GetR() * ic, ink.GetG() * ic, ink.GetB() * ic, inkA * ic * ac);
alphaMagProg.SetUniform("OutlineColor", outlineColor.GetR() * ic, outlineColor.GetG() * ic, outlineColor.GetB() * ic, outlineA * ic * ac);
alphaMagProg.SetUniform("GlowColor", glowColor.GetR() * ic, glowColor.GetG() * ic, glowColor.GetB() * ic, glowA * ic * ac);
alphaMagProg.SetUniform("Outline", outlineStrength > 0); //0.1 - 0.45
alphaMagProg.SetUniform("Glow", glowStrength > 0); //0.55 - 0.095
alphaMagProg.SetUniform("Shadow", false);
alphaMagProg.SetUniform("OutlineCenter", outlineCenter);
alphaMagProg.SetUniform("GlowCenter", glowCenter);
float xp = (float) x;
float yp = (float) y;
int page = -1;
float sw = (float) fi.scaleW;
float sh = (float) fi.scaleH;
float tw = 1.f / sw;
float th = 1.f / sh;
while(*s && n > 0)
{
int cn = *s;
if(cn >= 0 && cn < fi.chars.GetCount())
{
const OpenGLFont::CharInfo& ci = fi.chars[cn];
cn <<= 3;
if(ci.page != page)
{
resources.Bind(fi.pages[ci.page], Resources::LINEAR_FILTERING);
glActiveTexture(GL_TEXTURE0);
alphaMagProg.SetUniform("Texture", 0);
page = ci.page;
}
float sx = (float) ci.xoffset * fi.scale + xp + drawing_offset.x;
float sy = (float) ci.yoffset * fi.scale + yp + drawing_offset.y;
float dx = sx + ci.width * fi.scale;
float dy = sy + ci.height * fi.scale;
#if CLIP_MODE == 3
if(sx <= clip.right && sy <= clip.bottom && dx >= clip.left && dy >= clip.top)
#endif
{
float tl = (float) ci.x;
float tt = (float) ci.y;
float tr = (float) ci.x + ci.width;
float tb = (float) ci.y + ci.height;
#if CLIP_MODE == 3
if(sx < cl)
{
tl += (cl - sx);
sx = cl;
}
if(sy < ct)
{
tt += (ct - sy);
sy = ct;
}
if(dx > cr)
{
tr -= dx - cr;
dx = cr;
}
if(dy > cb)
{
tb -= dy - cb;
dy = cb;
}
#endif
tl = (tl + TEXEL_OFFSET) * tw;
tr = (tr - TEXEL_OFFSET) * tw;
tt = (tt + TEXEL_OFFSET) * th;
tb = (tb - TEXEL_OFFSET) * th;
/*
float vtx[] = {
sx, dy,
sx, sy,
dx, dy,
dx, sy
};*/
float vtx[12];
SetVtx(vtx, sx, sy, dx, dy);
float crd[] = {
tl, tb,
tl, tt,
tr, tb,
tr, tt
};
glTexCoordPointer(2, GL_FLOAT, 0, crd);
glVertexPointer(projection_mode ? 3: 2, GL_FLOAT, 0, vtx);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
xp += int(ci.xadvance * fi.scale + 0.5f);
int k = fi.kerns.Find(*s);
if(k >= 0)
xp += int(fi.kerns[k].Get(*(s + 1), 0) * fi.scale);
}
++s;
--n;
}
alphaMagProg.Stop();
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
}
void SystemDraw::DrawTextOp(int x, int y, int angle, const wchar *text, Font font, Color ink, int n, const int *dx)
{
GuiLock __;
Text(x, y, angle, text, font, ink, 0, White, 0, White, n, dx);
}
Size GetTextSize(const wchar *text, const OpenGLFont& fi, int n)
{
if(n < 0)
n = wstrlen(text);
Size sz;
sz.cx = 0;
const wchar *wtext = (const wchar *)text;
while(n > 0) {
int cn = *wtext++;
if(cn >= 0 && cn < fi.chars.GetCount())
{
const OpenGLFont::CharInfo& ci = fi.chars[cn];
sz.cx += int(ci.xadvance * fi.scale + 0.5f);
int k = fi.kerns.Find(cn);
if(k >= 0)
sz.cx += int(fi.kerns[k].Get(*wtext, 0) * fi.scale);
}
n--;
}
sz.cy = int(fi.lineHeight * fi.scale + 0.5f);
return sz;
}
END_UPP_NAMESPACE
#endif

174
rainbow/CoreGl/Event.cpp Normal file
View file

@ -0,0 +1,174 @@
#if defined(flagWINGL) || defined(flagLINUXGL)
#include "TopFrame.h"
NAMESPACE_UPP
#define LLOG(x) //LOG(x)
static Point glmousepos;
Point GetMousePos() {
return glmousepos;
}
void Ctrl::SysEndLoop()
{
}
void WakeUpGuiThread()
{
}
void Ctrl::MouseEventGl(Ptr<Ctrl> t, int event, Point p, int zdelta)
{
if(!t->IsEnabled() && (t != (Ctrl*) &infoPanel && t != (Ctrl*) &console))
return;
Rect rr = t->GetRect();
if((event & Ctrl::ACTION) == DOWN) {
Ptr<Ctrl> q = t;
TopWindowFrame *wf = dynamic_cast<TopWindowFrame *>(~t);
if(wf)
q = wf->window;
if(q) q->ClickActivateWnd();
if(q) q->SetForeground();
if(ignoreclick)
return;
}
if(t)
t->DispatchMouse(event, p - rr.TopLeft(), zdelta);
if(t)
t->PostInput();
}
Ctrl *Ctrl::FindMouseTopCtrl()
{
for(int i = topctrl.GetCount() - 1; i >= 0; i--) {
Ctrl *t = topctrl[i];
if(t->GetRect().Contains(glmousepos))
return t->IsEnabled() ? t : NULL;
}
return desktop->IsEnabled() ? desktop : NULL;
}
bool Ctrl::DoMouseGl(Ctrl* q, int event, Point p, int zdelta)
{
Rect rr = q->GetRect();
if(rr.Contains(p)) {
MouseEventGl(q, event, p, zdelta);
return true;
}
return false;
}
void Ctrl::DoMouseGl(int event, Point p, int zdelta)
{
glmousepos = p;
int a = event & Ctrl::ACTION;
if(a == Ctrl::UP && Ctrl::ignoreclick) {
EndIgnore();
return;
}
else
if(a == Ctrl::DOWN && ignoreclick)
return;
LLOG("### Mouse event: " << event << " position " << p << " zdelta " << zdelta << ", capture " << Upp::Name(captureCtrl));
if(captureCtrl)
MouseEventGl(captureCtrl->GetTopCtrl(), event, p, zdelta);
else
{
bool processed = consoleActive && DoMouseGl((Ctrl*) &console, event, p, zdelta);
if(!processed && controlPanelActive)
processed = DoMouseGl((Ctrl*) &infoPanel, event, p, zdelta);
if(!processed)
{
for(int i = topctrl.GetCount() - 1; i >= 0; i--) {
Ptr<Ctrl> t = topctrl[i];
if(t != (Ctrl*) &infoPanel && t != (Ctrl*) &console && t->GetRect().Contains(p) &&
DoMouseGl(t, event, p, zdelta))
return;
}
Ctrl *desktop = GetDesktop();
if(desktop) {
desktop->DispatchMouse(event, p, zdelta);
desktop->PostInput();
}
}
}
}
bool Ctrl::DoKeyGl(dword key, int cnt)
{
if(key == K_CTRL_GRAVE)
{
controlPanelActive = !controlPanelActive;
consoleActive = !consoleActive;
return true;
}
else if(key == K_CTRL_F12)
{
consoleActive = !consoleActive;
return true;
}
else if(key == K_CTRL_F11)
{
controlPanelActive = !controlPanelActive;
return true;
}
bool b = DispatchKey(key, cnt);
SyncCaret();
Ctrl *desktop = GetDesktop();
if(desktop)
desktop->PostInput();
return b;
}
void Ctrl::SetCaret(int x, int y, int cx, int cy)
{
GuiLock __;
caretx = x;
carety = y;
caretcx = cx;
caretcy = cy;
glCaretTm = GetTickCount();
SyncCaret();
}
void Ctrl::SyncCaret() {
GuiLock __;
}
void Ctrl::CursorSync(Draw& w)
{
Rect cr = Null;
if(focusCtrl && (((GetTickCount() - glCaretTm) / 500) & 1) == 0)
cr = (RectC(focusCtrl->caretx, focusCtrl->carety, focusCtrl->caretcx, focusCtrl->caretcy)
+ focusCtrl->GetScreenView().TopLeft()) & focusCtrl->GetScreenView();
glCaretRect = cr;
if(!cr.IsEmpty())
w.DrawRect(cr, Black);
}
void Ctrl::MouseSync(Draw& w)
{
glCursorPos = GetMousePos() - glCursorImage.GetHotSpot();
Size sz = glCursorImage.GetSize();
w.DrawImage(glCursorPos.x, glCursorPos.y, sz.cx, sz.cy, glCursorImage);
}
void Ctrl::SetMouseCursor(const Image& image)
{
GuiLock __;
if(image.GetSerialId() != glCursorImage.GetSerialId()) {
glCursorImage = image;
glCursorPos = Null;
}
}
END_UPP_NAMESPACE
#endif

103
rainbow/CoreGl/Fbo.cpp Normal file
View file

@ -0,0 +1,103 @@
#include "Fbo.h"
NAMESPACE_UPP
bool Fbo::Create(int width, int height, bool resize)
{
this->width = width;
this->height = height;
if(!resize)
{
glGenFramebuffers(1, &fbId);
glGenRenderbuffers(1, &rbId);
glGenTextures(1, &texId);
}
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbId);
glBindTexture(GL_TEXTURE_2D, texId);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, 0);
glBindRenderbuffer(GL_RENDERBUFFER, rbId);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbId, 0);
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbId);
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbId);
status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
ready = true;
return status == GL_FRAMEBUFFER_COMPLETE;
}
void Fbo::Resize(int width, int height)
{
if(ready)
Create(width, height, true);
}
void Fbo::Bind()
{
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbId);
}
void Fbo::Unbind()
{
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}
void Fbo::Clear()
{
glClearColor(0.f, 0.f, 0.f, 1.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
}
void Fbo::BlitToScreen()
{
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbId);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
}
void Fbo::BlitTo(const Fbo& fbo)
{
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbId);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo.fbId);
glBlitFramebuffer(0, 0, width, height, 0, 0, fbo.width, fbo.height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
}
void Fbo::Remove()
{
glDeleteTextures(1, &texId);
glDeleteRenderbuffers(1, &rbId);
glDeleteFramebuffers(1, &fbId);
}
String Fbo::GetError()
{
switch(status)
{
case GL_FRAMEBUFFER_COMPLETE:
return "Framebuffer complete";
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
return "Framebuffer incomplete attachment";
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
return "Framebuffer incomplete missing attachment";
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
return "Framebuffer incomplete draw buffer";
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
return "Framebuffer incomplete read buffer";
case GL_FRAMEBUFFER_UNSUPPORTED:
return "Framebuffer unsupported";
default:
return "Unknown error";
}
}
END_UPP_NAMESPACE

36
rainbow/CoreGl/Fbo.h Normal file
View file

@ -0,0 +1,36 @@
#ifndef _CoreGl_Fbo_h_
#define _CoreGl_Fbo_h_
#include <Core/Core.h>
#include <Draw/Draw.h>
#include "Gl.h"
NAMESPACE_UPP
struct Fbo : Moveable<Fbo>
{
GLuint texId;
GLuint fbId;
GLuint rbId;
GLenum status;
int width;
int height;
bool ready;
bool Create(int width, int height, bool resize = false);
void Resize(int width, int height);
void Bind();
void Unbind();
void Clear();
void BlitToScreen();
void BlitTo(const Fbo& fbo);
void Remove();
String GetError();
Fbo() : width(0), height(0), ready(false)
{}
};
END_UPP_NAMESPACE
#endif

57
rainbow/CoreGl/FontGl.h Normal file
View file

@ -0,0 +1,57 @@
#ifndef _CoreGl_FontGl_h_
#define _CoreGl_FontGl_h_
struct OpenGLFont : Moveable<OpenGLFont>
{
float scaleW;
float scaleH;
float lineHeight;
float base;
float scale;
bool texturesUpdated;
float vtx[1024 * 4 * 2];
float crd[1024 * 4 * 2];
struct CharInfo : Moveable<CharInfo>
{
int id;
float x;
float y;
float width;
float height;
float xoffset;
float yoffset;
float xadvance;
int page;
};
struct BrcImage : Moveable<BrcImage>
{
const byte* data;
int length;
};
Vector<CharInfo> chars;
VectorMap<int, VectorMap<int, float> > kerns;
Vector<Image> images;
Vector<int64> pages;
bool preload;
OpenGLFont() : texturesUpdated(false), preload(false), scale(1.0f)
{}
~OpenGLFont()
{}
void LoadBrc(const byte* xml, const byte** imagesData, const int* imagesSize, int imagesCount);
void Load(const String& fileName, bool preload = false);
void Parse(const char* xml, bool parsePages);
void UpdateTextures();
void BuildVertices();
};
Size GetTextSize(const wchar *text, const OpenGLFont& fi, int n);
#endif

4
rainbow/CoreGl/Fonts.brc Normal file
View file

@ -0,0 +1,4 @@
BINARY(resTahoma14Fnt, "tahoma14.fnt")
BINARY(resTahoma14BoldFnt, "tahoma14b.fnt")
BINARY(resTahoma14Img, "tahoma14.png")
BINARY(resTahoma14BoldImg, "tahoma14b.png")

View file

@ -0,0 +1,329 @@
<?xml version="1.0"?>
<font>
<info face="Tahoma" size="64" bold="1" italic="0" charset="" unicode="1" stretchH="100" smooth="0" aa="1" padding="64,64,64,64" spacing="1,1" outline="0" />
<common lineHeight="64" base="53" scaleW="1024" scaleH="1024" pages="1" packed="0" alphaChnl="0" redChnl="0" greenChnl="0" blueChnl="0" />
<pages>
<page id="0" file="TahomaB_0.png" />
</pages>
<chars count="319">
<char id="32" x="1006" y="16,25" width="16,125" height="16,125" xoffset="-8" yoffset="45" xadvance="15,5" page="0" chnl="15" />
<char id="33" x="793" y="681,375" width="26,25" height="54,5" xoffset="-4" yoffset="6,5" xadvance="18,125" page="0" chnl="15" />
<char id="34" x="654,875" y="783,75" width="35,375" height="31,25" xoffset="-4,75" yoffset="4,75" xadvance="25,875" page="0" chnl="15" />
<char id="35" x="608,75" y="628,375" width="52,875" height="54,5" xoffset="-4,75" yoffset="6,5" xadvance="43,375" page="0" chnl="15" />
<char id="36" x="862,5" y="206,25" width="45,25" height="66,125" xoffset="-5,5" yoffset="4,25" xadvance="33,75" page="0" chnl="15" />
<char id="37" x="878,125" y="514,625" width="73,875" height="56,125" xoffset="-5,25" yoffset="5,75" xadvance="63,5" page="0" chnl="15" />
<char id="38" x="952,125" y="513,625" width="56,625" height="56,125" xoffset="-5,75" yoffset="5,75" xadvance="41,375" page="0" chnl="15" />
<char id="39" x="690,375" y="783,75" width="24,5" height="31,25" xoffset="-4,875" yoffset="4,75" xadvance="14,625" page="0" chnl="15" />
<char id="40" x="291,75" y="208,125" width="35,125" height="66,875" xoffset="-5,125" yoffset="4,75" xadvance="24,125" page="0" chnl="15" />
<char id="41" x="327" y="208" width="35,125" height="66,875" xoffset="-6" yoffset="4,75" xadvance="24,125" page="0" chnl="15" />
<char id="42" x="160" y="795,25" width="41,875" height="41,375" xoffset="-4,625" yoffset="4,75" xadvance="33,75" page="0" chnl="15" />
<char id="43" x="148,25" y="746" width="49,375" height="49,125" xoffset="-3" yoffset="11,375" xadvance="43,375" page="0" chnl="15" />
<char id="44" x="523,625" y="787,375" width="30,625" height="35,75" xoffset="-8,125" yoffset="34,875" xadvance="16,625" page="0" chnl="15" />
<char id="45" x="891,625" y="780,75" width="33,125" height="23,125" xoffset="-5,125" yoffset="24,375" xadvance="22,875" page="0" chnl="15" />
<char id="46" x="830,5" y="781,25" width="25,125" height="26,125" xoffset="-4,25" yoffset="34,875" xadvance="16,625" page="0" chnl="15" />
<char id="47" x="942" y="272,375" width="38,75" height="64,625" xoffset="-5" yoffset="4,75" xadvance="30,625" page="0" chnl="15" />
<char id="48" x="152" y="578,375" width="45,75" height="56,125" xoffset="-6" yoffset="5,75" xadvance="33,75" page="0" chnl="15" />
<char id="49" x="688,25" y="682,875" width="41,5" height="54,5" xoffset="-3" yoffset="6,5" xadvance="33,75" page="0" chnl="15" />
<char id="50" x="755" y="571,375" width="44,25" height="55,25" xoffset="-4,125" yoffset="5,75" xadvance="33,75" page="0" chnl="15" />
<char id="51" x="289,125" y="577,25" width="44,625" height="56,125" xoffset="-5,375" yoffset="5,75" xadvance="33,75" page="0" chnl="15" />
<char id="52" x="138" y="636,625" width="47,625" height="54,625" xoffset="-6,875" yoffset="6,5" xadvance="33,75" page="0" chnl="15" />
<char id="53" x="598,375" y="572,875" width="44,25" height="55,375" xoffset="-4,875" yoffset="6,5" xadvance="33,75" page="0" chnl="15" />
<char id="54" x="197,875" y="577,875" width="45,5" height="56,125" xoffset="-5,5" yoffset="5,75" xadvance="33,75" page="0" chnl="15" />
<char id="55" x="475,875" y="685,875" width="44,375" height="54,5" xoffset="-5" yoffset="6,5" xadvance="33,75" page="0" chnl="15" />
<char id="56" x="486,375" y="518,375" width="46,5" height="56,25" xoffset="-6,375" yoffset="5,625" xadvance="33,75" page="0" chnl="15" />
<char id="57" x="243,5" y="577,375" width="45,5" height="56,125" xoffset="-6,25" yoffset="5,75" xadvance="33,75" page="0" chnl="15" />
<char id="58" x="989,75" y="680,75" width="25,125" height="45,125" xoffset="-3" yoffset="15,875" xadvance="19,25" page="0" chnl="15" />
<char id="59" x="983,875" y="569,875" width="30,625" height="54,75" xoffset="-6,875" yoffset="15,875" xadvance="19,25" page="0" chnl="15" />
<char id="60" x="49,5" y="747,875" width="49,25" height="49,25" xoffset="-3,375" yoffset="11,375" xadvance="43,375" page="0" chnl="15" />
<char id="61" x="554,375" y="787,25" width="47,75" height="35,5" xoffset="-2,25" yoffset="18,25" xadvance="43,375" page="0" chnl="15" />
<char id="62" x="98,875" y="747" width="49,25" height="49,25" xoffset="-2,5" yoffset="11,375" xadvance="43,375" page="0" chnl="15" />
<char id="63" x="843,625" y="571,125" width="41,125" height="55,25" xoffset="-5,125" yoffset="5,75" xadvance="30" page="0" chnl="15" />
<char id="64" x="173,375" y="341,75" width="58,25" height="61,125" xoffset="-5" yoffset="5,75" xadvance="48,75" page="0" chnl="15" />
<char id="65" x="767,25" y="626,75" width="52,5" height="54,5" xoffset="-8,125" yoffset="6,5" xadvance="36,25" page="0" chnl="15" />
<char id="66" x="244,375" y="689,25" width="46,875" height="54,5" xoffset="-4" yoffset="6,5" xadvance="36,375" page="0" chnl="15" />
<char id="67" x="104" y="580,375" width="47,875" height="56,125" xoffset="-6,25" yoffset="5,75" xadvance="35,375" page="0" chnl="15" />
<char id="68" x="924,125" y="626,125" width="50,375" height="54,5" xoffset="-4" yoffset="6,5" xadvance="40,125" page="0" chnl="15" />
<char id="69" x="520,375" y="685,75" width="42,125" height="54,5" xoffset="-4" yoffset="6,5" xadvance="32,625" page="0" chnl="15" />
<char id="70" x="562,625" y="683" width="41,75" height="54,5" xoffset="-4" yoffset="6,5" xadvance="30,75" page="0" chnl="15" />
<char id="71" x="53,375" y="581,25" width="50,5" height="56,125" xoffset="-6,25" yoffset="5,75" xadvance="39,5" page="0" chnl="15" />
<char id="72" x="98,75" y="692,375" width="48,5" height="54,5" xoffset="-4" yoffset="6,5" xadvance="40,5" page="0" chnl="15" />
<char id="73" x="729,875" y="682,75" width="36,625" height="54,5" xoffset="-5,5" yoffset="6,5" xadvance="25,625" page="0" chnl="15" />
<char id="74" x="944,875" y="570,875" width="38,875" height="55,125" xoffset="-7,875" yoffset="6,5" xadvance="26,5" page="0" chnl="15" />
<char id="75" x="0" y="693,25" width="49,75" height="54,5" xoffset="-4" yoffset="6,5" xadvance="36,875" page="0" chnl="15" />
<char id="76" x="646,375" y="683" width="41,75" height="54,5" xoffset="-4" yoffset="6,5" xadvance="30,375" page="0" chnl="15" />
<char id="77" x="443,5" y="631,25" width="55,375" height="54,5" xoffset="-4" yoffset="6,5" xadvance="47,375" page="0" chnl="15" />
<char id="78" x="974,625" y="626,125" width="48,875" height="54,5" xoffset="-4" yoffset="6,5" xadvance="40,875" page="0" chnl="15" />
<char id="79" x="0" y="582,125" width="53,25" height="56,125" xoffset="-6,25" yoffset="5,75" xadvance="40,75" page="0" chnl="15" />
<char id="80" x="430,125" y="686,125" width="45,625" height="54,5" xoffset="-4" yoffset="6,5" xadvance="34,875" page="0" chnl="15" />
<char id="81" x="663,625" y="206,5" width="53,25" height="66,125" xoffset="-6,25" yoffset="5,75" xadvance="40,75" page="0" chnl="15" />
<char id="82" x="872,375" y="626,5" width="51,625" height="54,5" xoffset="-4" yoffset="6,5" xadvance="38,5" page="0" chnl="15" />
<char id="83" x="333,875" y="576,5" width="46,75" height="56" xoffset="-6,125" yoffset="5,75" xadvance="33,625" page="0" chnl="15" />
<char id="84" x="147,375" y="691,375" width="48,375" height="54,5" xoffset="-8" yoffset="6,5" xadvance="32,5" page="0" chnl="15" />
<char id="85" x="550,125" y="572,875" width="48,125" height="55,375" xoffset="-4,5" yoffset="6,5" xadvance="39,125" page="0" chnl="15" />
<char id="86" x="714,625" y="628,125" width="52,5" height="54,5" xoffset="-8,375" yoffset="6,5" xadvance="35,75" page="0" chnl="15" />
<char id="87" x="185,75" y="634,625" width="69" height="54,5" xoffset="-7,25" yoffset="6,5" xadvance="54,5" page="0" chnl="15" />
<char id="88" x="661,75" y="628,25" width="52,75" height="54,5" xoffset="-8,25" yoffset="6,5" xadvance="36,25" page="0" chnl="15" />
<char id="89" x="819,875" y="626,75" width="52,375" height="54,5" xoffset="-8,5" yoffset="6,5" xadvance="35,5" page="0" chnl="15" />
<char id="90" x="291,375" y="688,25" width="46,5" height="54,5" xoffset="-6,625" yoffset="6,5" xadvance="33" page="0" chnl="15" />
<char id="91" x="584,5" y="207,25" width="32,25" height="66,375" xoffset="-3,75" yoffset="4,75" xadvance="24,125" page="0" chnl="15" />
<char id="92" x="903,125" y="272,5" width="38,75" height="64,625" xoffset="-3" yoffset="4,75" xadvance="30,625" page="0" chnl="15" />
<char id="93" x="552,125" y="207,25" width="32,25" height="66,375" xoffset="-4,5" yoffset="4,75" xadvance="24,125" page="0" chnl="15" />
<char id="94" x="386,75" y="789,75" width="50,375" height="37,125" xoffset="-3,5" yoffset="6,5" xadvance="43,375" page="0" chnl="15" />
<char id="95" x="958,125" y="779,5" width="50,5" height="21,25" xoffset="-8,375" yoffset="48,75" xadvance="33,75" page="0" chnl="15" />
<char id="96" x="745,25" y="782,625" width="29,875" height="26,125" xoffset="-1" yoffset="1,625" xadvance="28,875" page="0" chnl="15" />
<char id="97" x="420" y="742,75" width="43,125" height="46,875" xoffset="-6,625" yoffset="15" xadvance="31,75" page="0" chnl="15" />
<char id="98" x="845,25" y="457,625" width="44,5" height="56,875" xoffset="-4,5" yoffset="4,75" xadvance="33,5" page="0" chnl="15" />
<char id="99" x="508,125" y="740,5" width="41,75" height="46,75" xoffset="-6,625" yoffset="15" xadvance="28" page="0" chnl="15" />
<char id="100" x="532,125" y="459,25" width="44,5" height="57,125" xoffset="-6,625" yoffset="4,75" xadvance="33,375" page="0" chnl="15" />
<char id="101" x="463,25" y="740,75" width="44,75" height="46,75" xoffset="-6,625" yoffset="15" xadvance="31,5" page="0" chnl="15" />
<char id="102" x="260,25" y="520,625" width="37,5" height="56,5" xoffset="-7,5" yoffset="4,5" xadvance="20,25" page="0" chnl="15" />
<char id="103" x="889,875" y="457" width="44,5" height="56,875" xoffset="-6,625" yoffset="15" xadvance="33,375" page="0" chnl="15" />
<char id="104" x="624,75" y="516,375" width="43,125" height="56,25" xoffset="-4,5" yoffset="4,75" xadvance="33,875" page="0" chnl="15" />
<char id="105" x="407,375" y="518,875" width="25,625" height="56,375" xoffset="-4,75" yoffset="4,625" xadvance="16" page="0" chnl="15" />
<char id="106" x="818,625" y="139,125" width="33,875" height="67,25" xoffset="-10,125" yoffset="4,625" xadvance="19,25" page="0" chnl="15" />
<char id="107" x="579,625" y="516,5" width="45" height="56,25" xoffset="-4,5" yoffset="4,75" xadvance="31,875" page="0" chnl="15" />
<char id="108" x="853" y="514,625" width="25" height="56,25" xoffset="-4,5" yoffset="4,75" xadvance="16" page="0" chnl="15" />
<char id="109" x="591" y="737,625" width="59,75" height="46" xoffset="-4,625" yoffset="15" xadvance="50,5" page="0" chnl="15" />
<char id="110" x="694,125" y="737,5" width="43,125" height="46" xoffset="-4,5" yoffset="15" xadvance="33,875" page="0" chnl="15" />
<char id="111" x="373,875" y="742,75" width="46" height="46,875" xoffset="-6,625" yoffset="15" xadvance="32,75" page="0" chnl="15" />
<char id="112" x="172,375" y="521,125" width="44,5" height="56,625" xoffset="-4,5" yoffset="15" xadvance="33,375" page="0" chnl="15" />
<char id="113" x="127,75" y="521,625" width="44,5" height="56,625" xoffset="-6,625" yoffset="15" xadvance="33,375" page="0" chnl="15" />
<char id="114" x="981,625" y="733,5" width="35,5" height="45,125" xoffset="-4,5" yoffset="15,875" xadvance="23" page="0" chnl="15" />
<char id="115" x="550" y="740,375" width="40,875" height="46,75" xoffset="-6,5" yoffset="15" xadvance="27,25" page="0" chnl="15" />
<char id="116" x="819,375" y="681,375" width="37,25" height="54" xoffset="-7,5" yoffset="7,625" xadvance="22" page="0" chnl="15" />
<char id="117" x="650,875" y="737,625" width="43,125" height="46" xoffset="-4,75" yoffset="15,875" xadvance="33,875" page="0" chnl="15" />
<char id="118" x="848,25" y="735,5" width="46,625" height="45,125" xoffset="-8" yoffset="15,875" xadvance="30,625" page="0" chnl="15" />
<char id="119" x="737,375" y="737,375" width="62,375" height="45,125" xoffset="-7,625" yoffset="15,875" xadvance="47,125" page="0" chnl="15" />
<char id="120" x="799,875" y="736" width="48,25" height="45,125" xoffset="-8,125" yoffset="15,875" xadvance="32" page="0" chnl="15" />
<char id="121" x="416,375" y="575,375" width="46,75" height="55,75" xoffset="-8,125" yoffset="15,875" xadvance="30,5" page="0" chnl="15" />
<char id="122" x="940,125" y="734,25" width="41,375" height="45,125" xoffset="-6,75" yoffset="15,875" xadvance="27,875" page="0" chnl="15" />
<char id="123" x="463,875" y="207,375" width="44" height="66,375" xoffset="-6,5" yoffset="4,75" xadvance="33" page="0" chnl="15" />
<char id="124" x="616,875" y="207,25" width="23,25" height="66,375" xoffset="5,25" yoffset="4,75" xadvance="33,75" page="0" chnl="15" />
<char id="125" x="508" y="207,375" width="44" height="66,375" xoffset="-4,5" yoffset="4,75" xadvance="33" page="0" chnl="15" />
<char id="126" x="602,25" y="783,75" width="52,5" height="33" xoffset="-4,5" yoffset="19,375" xadvance="43,375" page="0" chnl="15" />
<char id="160" x="1002,125" y="0" width="16,125" height="16,125" xoffset="-8" yoffset="45" xadvance="15,5" page="0" chnl="15" />
<char id="161" x="766,625" y="682,75" width="26,25" height="54,5" xoffset="-4" yoffset="6,5" xadvance="18,125" page="0" chnl="15" />
<char id="162" x="44,75" y="342,25" width="42" height="63,375" xoffset="-4,125" yoffset="6,875" xadvance="33,75" page="0" chnl="15" />
<char id="163" x="799,375" y="571,375" width="44,125" height="55,25" xoffset="-4,875" yoffset="5,75" xadvance="33,75" page="0" chnl="15" />
<char id="164" x="25,125" y="797,875" width="43,75" height="43,75" xoffset="-5" yoffset="14" xadvance="33,75" page="0" chnl="15" />
<char id="165" x="49,875" y="693,25" width="48,75" height="54,5" xoffset="-7,375" yoffset="6,5" xadvance="33,75" page="0" chnl="15" />
<char id="166" x="640,25" y="207,25" width="23,25" height="66,375" xoffset="5,25" yoffset="4,75" xadvance="33,75" page="0" chnl="15" />
<char id="167" x="636,875" y="273,75" width="44,375" height="65,375" xoffset="-5,25" yoffset="5,75" xadvance="33,75" page="0" chnl="15" />
<char id="168" x="855,75" y="780,75" width="35,75" height="23,125" xoffset="-3,5" yoffset="4,625" xadvance="28,875" page="0" chnl="15" />
<char id="169" x="292,625" y="341,25" width="60,75" height="60,75" xoffset="-5,75" yoffset="5,75" xadvance="49,25" page="0" chnl="15" />
<char id="170" x="314,875" y="789,875" width="37,75" height="40,5" xoffset="-6,125" yoffset="5,75" xadvance="26,875" page="0" chnl="15" />
<char id="171" x="114,5" y="796,375" width="45,375" height="42,375" xoffset="-4,625" yoffset="14,75" xadvance="37,25" page="0" chnl="15" />
<char id="172" x="474,375" y="787,625" width="49,125" height="35,875" xoffset="-3" yoffset="23,875" xadvance="43,375" page="0" chnl="15" />
<char id="173" x="924,875" y="779,5" width="33,125" height="23,125" xoffset="-5,125" yoffset="24,375" xadvance="22,875" page="0" chnl="15" />
<char id="174" x="231,75" y="341,625" width="60,75" height="60,75" xoffset="-5,75" yoffset="5,75" xadvance="49,25" page="0" chnl="15" />
<char id="175" x="0" y="843,125" width="50,5" height="21,25" xoffset="-8,375" yoffset="-2,375" xadvance="33,75" page="0" chnl="15" />
<char id="176" x="437,25" y="789,75" width="37" height="36,875" xoffset="-4,75" yoffset="5,75" xadvance="27,5" page="0" chnl="15" />
<char id="177" x="894,125" y="681,125" width="49,375" height="53" xoffset="-3" yoffset="8" xadvance="43,375" page="0" chnl="15" />
<char id="178" x="278,25" y="790,875" width="36,5" height="40,625" xoffset="-3,375" yoffset="5,75" xadvance="28,625" page="0" chnl="15" />
<char id="179" x="202" y="791,125" width="36" height="41,25" xoffset="-3,625" yoffset="5,75" xadvance="28,625" page="0" chnl="15" />
<char id="180" x="775,25" y="782,625" width="29,875" height="26,125" xoffset="0,875" yoffset="1,625" xadvance="28,875" page="0" chnl="15" />
<char id="181" x="463,25" y="575,25" width="43,5" height="55,75" xoffset="-4,5" yoffset="15,875" xadvance="34,5" page="0" chnl="15" />
<char id="182" x="0" y="342,25" width="44,625" height="63,875" xoffset="-6,25" yoffset="6,5" xadvance="33,75" page="0" chnl="15" />
<char id="183" x="805,25" y="781,25" width="25,125" height="26,125" xoffset="-3" yoffset="15,875" xadvance="19,25" page="0" chnl="15" />
<char id="184" x="715" y="783,625" width="30,125" height="27,375" xoffset="-0,625" yoffset="44,5" xadvance="28,875" page="0" chnl="15" />
<char id="185" x="352,75" y="789,875" width="33,875" height="39,875" xoffset="-2,125" yoffset="6,5" xadvance="28,625" page="0" chnl="15" />
<char id="186" x="238,125" y="791,125" width="40" height="40,625" xoffset="-5,375" yoffset="5,75" xadvance="28,625" page="0" chnl="15" />
<char id="187" x="69" y="797,25" width="45,375" height="42,375" xoffset="-3,25" yoffset="14,75" xadvance="37,25" page="0" chnl="15" />
<char id="188" x="69,75" y="637,5" width="68,125" height="54,75" xoffset="-3,75" yoffset="6,25" xadvance="59,75" page="0" chnl="15" />
<char id="189" x="0" y="638,375" width="69,625" height="54,75" xoffset="-4,25" yoffset="6,25" xadvance="59,75" page="0" chnl="15" />
<char id="190" x="684" y="572,75" width="70,875" height="55,25" xoffset="-4,375" yoffset="5,75" xadvance="59,75" page="0" chnl="15" />
<char id="191" x="642,75" y="572,75" width="41,125" height="55,375" xoffset="-6" yoffset="6,5" xadvance="30" page="0" chnl="15" />
<char id="192" x="113,75" y="70,375" width="52,5" height="69" xoffset="-8,125" yoffset="-8" xadvance="36,25" page="0" chnl="15" />
<char id="193" x="166,375" y="70,125" width="52,5" height="69" xoffset="-8,125" yoffset="-8" xadvance="36,25" page="0" chnl="15" />
<char id="194" x="255,75" y="139,25" width="52,5" height="68,75" xoffset="-8,125" yoffset="-7,75" xadvance="36,25" page="0" chnl="15" />
<char id="195" x="925,125" y="139" width="52,5" height="67" xoffset="-8,125" yoffset="-6" xadvance="36,25" page="0" chnl="15" />
<char id="196" x="907,875" y="206,25" width="52,5" height="66" xoffset="-8,125" yoffset="-5" xadvance="36,25" page="0" chnl="15" />
<char id="197" x="960,5" y="206,125" width="52,5" height="66" xoffset="-8,125" yoffset="-5" xadvance="36,25" page="0" chnl="15" />
<char id="198" x="321,625" y="633,5" width="66,25" height="54,5" xoffset="-8,5" yoffset="6,5" xadvance="52,375" page="0" chnl="15" />
<char id="199" x="767,625" y="206,5" width="47,875" height="66,125" xoffset="-6,25" yoffset="5,75" xadvance="35,375" page="0" chnl="15" />
<char id="200" x="757,125" y="70" width="42,125" height="69" xoffset="-4" yoffset="-8" xadvance="32,625" page="0" chnl="15" />
<char id="201" x="799,375" y="70" width="42,125" height="69" xoffset="-4" yoffset="-8" xadvance="32,625" page="0" chnl="15" />
<char id="202" x="883,875" y="69,875" width="42,125" height="69" xoffset="-4" yoffset="-8" xadvance="32,625" page="0" chnl="15" />
<char id="203" x="141,375" y="275,625" width="42,125" height="66" xoffset="-4" yoffset="-5" xadvance="32,625" page="0" chnl="15" />
<char id="204" x="36,75" y="139,875" width="36,625" height="69" xoffset="-5,5" yoffset="-8" xadvance="25,625" page="0" chnl="15" />
<char id="205" x="0" y="139,875" width="36,625" height="69" xoffset="-5,5" yoffset="-8" xadvance="25,625" page="0" chnl="15" />
<char id="206" x="968" y="69,75" width="37,875" height="69" xoffset="-6,125" yoffset="-8" xadvance="25,625" page="0" chnl="15" />
<char id="207" x="183,625" y="275,5" width="36,625" height="66" xoffset="-5,5" yoffset="-5" xadvance="25,625" page="0" chnl="15" />
<char id="208" x="499" y="631,125" width="54,75" height="54,5" xoffset="-7,5" yoffset="6,5" xadvance="41" page="0" chnl="15" />
<char id="209" x="642,375" y="139,125" width="48,875" height="67,25" xoffset="-4" yoffset="-6,25" xadvance="40,875" page="0" chnl="15" />
<char id="210" x="326,125" y="0" width="53,25" height="69,875" xoffset="-6,25" yoffset="-8" xadvance="40,75" page="0" chnl="15" />
<char id="211" x="272,75" y="0" width="53,25" height="69,875" xoffset="-6,25" yoffset="-8" xadvance="40,75" page="0" chnl="15" />
<char id="212" x="219,375" y="0" width="53,25" height="69,875" xoffset="-6,25" yoffset="-8" xadvance="40,75" page="0" chnl="15" />
<char id="213" x="360,875" y="139,125" width="53,25" height="68,125" xoffset="-6,25" yoffset="-6,25" xadvance="40,75" page="0" chnl="15" />
<char id="214" x="46,875" y="209" width="53,25" height="66,875" xoffset="-6,25" yoffset="-5" xadvance="40,75" page="0" chnl="15" />
<char id="215" x="197,75" y="743,875" width="47,125" height="47,125" xoffset="-1,875" yoffset="12,375" xadvance="43,375" page="0" chnl="15" />
<char id="216" x="353,5" y="341" width="53,25" height="60,5" xoffset="-6,25" yoffset="3,875" xadvance="40,75" page="0" chnl="15" />
<char id="217" x="580" y="0" width="48,125" height="69,875" xoffset="-4,5" yoffset="-8" xadvance="39,125" page="0" chnl="15" />
<char id="218" x="531,75" y="0" width="48,125" height="69,875" xoffset="-4,5" yoffset="-8" xadvance="39,125" page="0" chnl="15" />
<char id="219" x="483,5" y="0" width="48,125" height="69,875" xoffset="-4,5" yoffset="-8" xadvance="39,125" page="0" chnl="15" />
<char id="220" x="150,875" y="208,5" width="48,125" height="66,875" xoffset="-4,5" yoffset="-5" xadvance="39,125" page="0" chnl="15" />
<char id="221" x="308,375" y="139,125" width="52,375" height="68,75" xoffset="-8,5" yoffset="-7,75" xadvance="35,5" page="0" chnl="15" />
<char id="222" x="384,25" y="688,125" width="45,75" height="54,5" xoffset="-4" yoffset="6,5" xadvance="34,875" page="0" chnl="15" />
<char id="223" x="799,75" y="457,75" width="45,375" height="56,875" xoffset="-4,5" yoffset="4,5" xadvance="34,25" page="0" chnl="15" />
<char id="224" x="591,375" y="339,25" width="43,125" height="60,25" xoffset="-6,625" yoffset="1,625" xadvance="31,75" page="0" chnl="15" />
<char id="225" x="850,875" y="338" width="43,125" height="60,25" xoffset="-6,625" yoffset="1,625" xadvance="31,75" page="0" chnl="15" />
<char id="226" x="634,625" y="339,25" width="43,125" height="60,25" xoffset="-6,625" yoffset="1,625" xadvance="31,75" page="0" chnl="15" />
<char id="227" x="924,375" y="398" width="43,125" height="58,5" xoffset="-6,625" yoffset="3,375" xadvance="31,75" page="0" chnl="15" />
<char id="228" x="202,375" y="463,25" width="43,125" height="57,25" xoffset="-6,625" yoffset="4,625" xadvance="31,75" page="0" chnl="15" />
<char id="229" x="130,125" y="342,125" width="43,125" height="61,25" xoffset="-6,625" yoffset="0,625" xadvance="31,75" page="0" chnl="15" />
<char id="230" x="310,625" y="742,875" width="63,125" height="46,875" xoffset="-6,625" yoffset="15" xadvance="49,625" page="0" chnl="15" />
<char id="231" x="0" y="525,125" width="41,75" height="56,875" xoffset="-6,625" yoffset="15" xadvance="28" page="0" chnl="15" />
<char id="232" x="0" y="406,25" width="44,75" height="60,125" xoffset="-6,625" yoffset="1,625" xadvance="31,5" page="0" chnl="15" />
<char id="233" x="939" y="337,25" width="44,75" height="60,125" xoffset="-6,625" yoffset="1,625" xadvance="31,5" page="0" chnl="15" />
<char id="234" x="894,125" y="337,75" width="44,75" height="60,125" xoffset="-6,625" yoffset="1,625" xadvance="31,5" page="0" chnl="15" />
<char id="235" x="487,25" y="459,625" width="44,75" height="57,125" xoffset="-6,625" yoffset="4,625" xadvance="31,5" page="0" chnl="15" />
<char id="236" x="670,75" y="399,625" width="29,875" height="59,375" xoffset="-8,125" yoffset="1,625" xadvance="16" page="0" chnl="15" />
<char id="237" x="640,75" y="399,625" width="29,875" height="59,375" xoffset="-5,625" yoffset="1,625" xadvance="16" page="0" chnl="15" />
<char id="238" x="606,5" y="399,625" width="34,125" height="59,375" xoffset="-9,125" yoffset="1,625" xadvance="16" page="0" chnl="15" />
<char id="239" x="373,375" y="518,875" width="33,875" height="56,375" xoffset="-8,875" yoffset="4,625" xadvance="16" page="0" chnl="15" />
<char id="240" x="75,5" y="466" width="46,125" height="57,5" xoffset="-6,625" yoffset="4,375" xadvance="32,875" page="0" chnl="15" />
<char id="241" x="32,25" y="466,5" width="43,125" height="57,625" xoffset="-4,5" yoffset="3,375" xadvance="33,875" page="0" chnl="15" />
<char id="242" x="499,125" y="339,375" width="46" height="60,25" xoffset="-6,625" yoffset="1,625" xadvance="32,75" page="0" chnl="15" />
<char id="243" x="453" y="339,75" width="46" height="60,25" xoffset="-6,625" yoffset="1,625" xadvance="32,75" page="0" chnl="15" />
<char id="244" x="406,875" y="339,75" width="46" height="60,25" xoffset="-6,625" yoffset="1,625" xadvance="32,75" page="0" chnl="15" />
<char id="245" x="878,25" y="398,375" width="46" height="58,5" xoffset="-6,625" yoffset="3,375" xadvance="32,75" page="0" chnl="15" />
<char id="246" x="156,25" y="463,75" width="46" height="57,25" xoffset="-6,625" yoffset="4,625" xadvance="32,75" page="0" chnl="15" />
<char id="247" x="0" y="747,875" width="49,375" height="49,875" xoffset="-3" yoffset="11" xadvance="43,375" page="0" chnl="15" />
<char id="248" x="943,625" y="680,75" width="46" height="52,625" xoffset="-6,625" yoffset="12,5" xadvance="32,75" page="0" chnl="15" />
<char id="249" x="677,875" y="339,25" width="43,125" height="60,25" xoffset="-4,75" yoffset="1,625" xadvance="33,875" page="0" chnl="15" />
<char id="250" x="721,125" y="338,25" width="43,125" height="60,25" xoffset="-4,75" yoffset="1,625" xadvance="33,875" page="0" chnl="15" />
<char id="251" x="764,375" y="338" width="43,125" height="60,25" xoffset="-4,75" yoffset="1,625" xadvance="33,875" page="0" chnl="15" />
<char id="252" x="245,625" y="463,25" width="43,125" height="57,25" xoffset="-4,75" yoffset="4,625" xadvance="33,875" page="0" chnl="15" />
<char id="253" x="172,5" y="0" width="46,75" height="70" xoffset="-8,125" yoffset="1,625" xadvance="30,5" page="0" chnl="15" />
<char id="254" x="247,125" y="208,25" width="44,5" height="66,875" xoffset="-4,5" yoffset="4,75" xadvance="33,375" page="0" chnl="15" />
<char id="255" x="0" y="209" width="46,75" height="67" xoffset="-8,125" yoffset="4,625" xadvance="30,5" page="0" chnl="15" />
<char id="256" x="257,125" y="275,25" width="52,5" height="65,875" xoffset="-8,125" yoffset="-4,875" xadvance="36,25" page="0" chnl="15" />
<char id="257" x="620" y="459,125" width="43,125" height="57,125" xoffset="-6,625" yoffset="4,75" xadvance="31,75" page="0" chnl="15" />
<char id="258" x="510,75" y="139,125" width="52,5" height="68" xoffset="-8,125" yoffset="-7" xadvance="36,25" page="0" chnl="15" />
<char id="259" x="746,875" y="398,625" width="43,125" height="59,25" xoffset="-6,625" yoffset="2,625" xadvance="31,75" page="0" chnl="15" />
<char id="260" x="723,25" y="272,75" width="52,5" height="65,125" xoffset="-8,125" yoffset="6,5" xadvance="36,25" page="0" chnl="15" />
<char id="261" x="217" y="520,625" width="43,125" height="56,625" xoffset="-6,625" yoffset="15" xadvance="31,75" page="0" chnl="15" />
<char id="262" x="724,5" y="0" width="47,875" height="69,875" xoffset="-6,25" yoffset="-8" xadvance="35,375" page="0" chnl="15" />
<char id="263" x="174" y="403" width="41,75" height="60,125" xoffset="-6,625" yoffset="1,625" xadvance="28" page="0" chnl="15" />
<char id="264" x="676,5" y="0" width="47,875" height="69,875" xoffset="-6,25" yoffset="-8" xadvance="35,375" page="0" chnl="15" />
<char id="265" x="131,875" y="403,5" width="42" height="60,125" xoffset="-6,625" yoffset="1,625" xadvance="28" page="0" chnl="15" />
<char id="266" x="199,125" y="208,5" width="47,875" height="66,875" xoffset="-6,25" yoffset="-5" xadvance="35,375" page="0" chnl="15" />
<char id="267" x="663,25" y="459,125" width="41,75" height="57,125" xoffset="-6,625" yoffset="4,625" xadvance="28" page="0" chnl="15" />
<char id="268" x="772,5" y="0" width="47,875" height="69,875" xoffset="-6,25" yoffset="-8" xadvance="35,375" page="0" chnl="15" />
<char id="269" x="89,75" y="403,75" width="42" height="60,125" xoffset="-6,625" yoffset="1,625" xadvance="28" page="0" chnl="15" />
<char id="270" x="375" y="70" width="50,375" height="69" xoffset="-4" yoffset="-8" xadvance="40,125" page="0" chnl="15" />
<char id="271" x="288,875" y="462,75" width="59,25" height="57,125" xoffset="-6,625" yoffset="4,75" xadvance="43,375" page="0" chnl="15" />
<char id="272" x="553,875" y="628,375" width="54,75" height="54,5" xoffset="-7,5" yoffset="6,5" xadvance="41" page="0" chnl="15" />
<char id="273" x="348,25" y="461,625" width="47,875" height="57,125" xoffset="-6,625" yoffset="4,75" xadvance="33,125" page="0" chnl="15" />
<char id="274" x="309,75" y="275,125" width="42,125" height="65,875" xoffset="-4" yoffset="-4,875" xadvance="32,625" page="0" chnl="15" />
<char id="275" x="705,125" y="459" width="44,75" height="57" xoffset="-6,625" yoffset="4,75" xadvance="31,5" page="0" chnl="15" />
<char id="276" x="563,375" y="139,125" width="42,125" height="68" xoffset="-4" yoffset="-7" xadvance="32,625" page="0" chnl="15" />
<char id="277" x="833,375" y="398,375" width="44,75" height="59,125" xoffset="-6,625" yoffset="2,625" xadvance="31,5" page="0" chnl="15" />
<char id="278" x="99,125" y="276" width="42,125" height="66" xoffset="-4" yoffset="-5" xadvance="32,625" page="0" chnl="15" />
<char id="279" x="442,375" y="461,125" width="44,75" height="57,125" xoffset="-6,625" yoffset="4,625" xadvance="31,5" page="0" chnl="15" />
<char id="280" x="824,125" y="272,75" width="42,125" height="65,125" xoffset="-4" yoffset="6,5" xadvance="32,625" page="0" chnl="15" />
<char id="281" x="82,875" y="523,625" width="44,75" height="56,625" xoffset="-6,625" yoffset="15" xadvance="31,5" page="0" chnl="15" />
<char id="282" x="841,625" y="69,875" width="42,125" height="69" xoffset="-4" yoffset="-8" xadvance="32,625" page="0" chnl="15" />
<char id="283" x="44,875" y="405,75" width="44,75" height="60,125" xoffset="-6,625" yoffset="1,625" xadvance="31,5" page="0" chnl="15" />
<char id="284" x="432,875" y="0" width="50,5" height="69,875" xoffset="-6,25" yoffset="-8" xadvance="39,5" page="0" chnl="15" />
<char id="285" x="44,625" y="0" width="44,5" height="70,25" xoffset="-6,625" yoffset="1,625" xadvance="33,375" page="0" chnl="15" />
<char id="286" x="156,875" y="139,5" width="50,5" height="68,875" xoffset="-6,25" yoffset="-7" xadvance="39,5" page="0" chnl="15" />
<char id="287" x="0" y="70,5" width="44,5" height="69,25" xoffset="-6,625" yoffset="2,625" xadvance="33,375" page="0" chnl="15" />
<char id="288" x="100,25" y="208,625" width="50,5" height="66,875" xoffset="-6,25" yoffset="-5" xadvance="39,5" page="0" chnl="15" />
<char id="289" x="691,375" y="139,125" width="44,5" height="67,25" xoffset="-6,625" yoffset="4,625" xadvance="33,375" page="0" chnl="15" />
<char id="290" x="717" y="206,5" width="50,5" height="66,125" xoffset="-6,25" yoffset="5,75" xadvance="39,5" page="0" chnl="15" />
<char id="291" x="0" y="0" width="44,5" height="70,375" xoffset="-6,625" yoffset="1,5" xadvance="33,375" page="0" chnl="15" />
<char id="292" x="523,5" y="70" width="48,5" height="69" xoffset="-4" yoffset="-8" xadvance="40,5" page="0" chnl="15" />
<char id="293" x="713,875" y="70" width="43,125" height="69" xoffset="-4,5" yoffset="-8" xadvance="33,875" page="0" chnl="15" />
<char id="294" x="388" y="631,5" width="55,375" height="54,5" xoffset="-7" yoffset="6,5" xadvance="41,375" page="0" chnl="15" />
<char id="295" x="533" y="516,5" width="46,5" height="56,25" xoffset="-8,125" yoffset="4,75" xadvance="33,625" page="0" chnl="15" />
<char id="296" x="779,75" y="139,125" width="38,75" height="67,25" xoffset="-6,5" yoffset="-6,25" xadvance="25,625" page="0" chnl="15" />
<char id="297" x="121,75" y="464" width="34,375" height="57,5" xoffset="-9,125" yoffset="3,5" xadvance="16" page="0" chnl="15" />
<char id="298" x="352" y="275" width="36,625" height="65,875" xoffset="-5,5" yoffset="-4,875" xadvance="25,625" page="0" chnl="15" />
<char id="299" x="821,625" y="514,75" width="31,25" height="56,25" xoffset="-7,625" yoffset="4,75" xadvance="16" page="0" chnl="15" />
<char id="300" x="605,625" y="139,125" width="36,625" height="68" xoffset="-5,5" yoffset="-7" xadvance="25,625" page="0" chnl="15" />
<char id="301" x="0" y="466,5" width="32,125" height="58,5" xoffset="-8" yoffset="2,5" xadvance="16" page="0" chnl="15" />
<char id="302" x="866,375" y="272,5" width="36,625" height="65,125" xoffset="-5,5" yoffset="6,5" xadvance="25,625" page="0" chnl="15" />
<char id="303" x="977,75" y="138,875" width="26,375" height="67" xoffset="-5,5" yoffset="4,625" xadvance="16" page="0" chnl="15" />
<char id="304" x="220,375" y="275,5" width="36,625" height="66" xoffset="-5,5" yoffset="-5" xadvance="25,625" page="0" chnl="15" />
<char id="305" x="0" y="797,875" width="25" height="45,125" xoffset="-4,5" yoffset="15,875" xadvance="16" page="0" chnl="15" />
<char id="306" x="884,875" y="570,875" width="59,875" height="55,125" xoffset="-5,5" yoffset="6,5" xadvance="49,875" page="0" chnl="15" />
<char id="307" x="736" y="139,125" width="43,625" height="67,25" xoffset="-4,75" yoffset="4,625" xadvance="34,375" page="0" chnl="15" />
<char id="308" x="961,125" y="0" width="40,875" height="69,625" xoffset="-7,875" yoffset="-8" xadvance="26,5" page="0" chnl="15" />
<char id="309" x="89,25" y="0" width="36,25" height="70,25" xoffset="-10,125" yoffset="1,625" xadvance="19,25" page="0" chnl="15" />
<char id="310" x="440,5" y="274,25" width="49,75" height="65,375" xoffset="-4" yoffset="6,5" xadvance="36,875" page="0" chnl="15" />
<char id="311" x="852,625" y="139" width="45" height="67,125" xoffset="-4,5" yoffset="4,75" xadvance="31,875" page="0" chnl="15" />
<char id="312" x="895" y="734,25" width="45" height="45,125" xoffset="-4,5" yoffset="15,875" xadvance="31,875" page="0" chnl="15" />
<char id="313" x="926,125" y="69,875" width="41,75" height="69" xoffset="-4" yoffset="-8" xadvance="30,375" page="0" chnl="15" />
<char id="314" x="73,5" y="139,5" width="29,875" height="69" xoffset="-5,5" yoffset="-8" xadvance="16" page="0" chnl="15" />
<char id="315" x="681,375" y="272,75" width="41,75" height="65,375" xoffset="-4" yoffset="6,5" xadvance="30,375" page="0" chnl="15" />
<char id="316" x="897,75" y="139" width="27,25" height="67,125" xoffset="-5,5" yoffset="4,75" xadvance="16" page="0" chnl="15" />
<char id="317" x="668" y="516,375" width="43" height="56,25" xoffset="-4" yoffset="4,75" xadvance="30,375" page="0" chnl="15" />
<char id="318" x="711,125" y="516,125" width="39,75" height="56,25" xoffset="-4,5" yoffset="4,75" xadvance="26" page="0" chnl="15" />
<char id="319" x="604,5" y="683" width="41,75" height="54,5" xoffset="-4" yoffset="6,5" xadvance="30,375" page="0" chnl="15" />
<char id="320" x="751" y="515" width="37,5" height="56,25" xoffset="-4,5" yoffset="4,75" xadvance="25,875" page="0" chnl="15" />
<char id="321" x="338" y="688,125" width="46,125" height="54,5" xoffset="-7,5" yoffset="6,5" xadvance="31,25" page="0" chnl="15" />
<char id="322" x="788,625" y="515" width="32,875" height="56,25" xoffset="-7,5" yoffset="4,75" xadvance="17,75" page="0" chnl="15" />
<char id="323" x="425,5" y="70" width="48,875" height="69" xoffset="-4" yoffset="-8" xadvance="40,875" page="0" chnl="15" />
<char id="324" x="401,375" y="401,625" width="43,125" height="59,375" xoffset="-4,5" yoffset="1,625" xadvance="33,875" page="0" chnl="15" />
<char id="325" x="490,375" y="273,875" width="48,875" height="65,375" xoffset="-4" yoffset="6,5" xadvance="40,875" page="0" chnl="15" />
<char id="326" x="934,5" y="456,625" width="43,125" height="56,875" xoffset="-4,5" yoffset="15" xadvance="33,875" page="0" chnl="15" />
<char id="327" x="474,5" y="70" width="48,875" height="69" xoffset="-4" yoffset="-8" xadvance="40,875" page="0" chnl="15" />
<char id="328" x="444,625" y="400,125" width="43,125" height="59,375" xoffset="-4,5" yoffset="1,625" xadvance="33,875" page="0" chnl="15" />
<char id="329" x="433,125" y="518,875" width="53,125" height="56,25" xoffset="-9" yoffset="4,75" xadvance="39,375" page="0" chnl="15" />
<char id="330" x="539,375" y="273,875" width="48,875" height="65,375" xoffset="-4" yoffset="6,5" xadvance="40,875" page="0" chnl="15" />
<char id="331" x="977,75" y="456,125" width="43,125" height="56,875" xoffset="-4,5" yoffset="15" xadvance="33,875" page="0" chnl="15" />
<char id="332" x="362,25" y="207,375" width="53,25" height="66,75" xoffset="-6,25" yoffset="-4,875" xadvance="40,75" page="0" chnl="15" />
<char id="333" x="396,25" y="461,625" width="46" height="57,125" xoffset="-6,625" yoffset="4,75" xadvance="32,75" page="0" chnl="15" />
<char id="334" x="103,5" y="139,5" width="53,25" height="68,875" xoffset="-6,25" yoffset="-7" xadvance="40,75" page="0" chnl="15" />
<char id="335" x="700,75" y="399,625" width="46" height="59,25" xoffset="-6,625" yoffset="2,625" xadvance="32,75" page="0" chnl="15" />
<char id="336" x="379,5" y="0" width="53,25" height="69,875" xoffset="-6,25" yoffset="-8" xadvance="40,75" page="0" chnl="15" />
<char id="337" x="545,25" y="339,375" width="46" height="60,25" xoffset="-6,625" yoffset="1,625" xadvance="32,75" page="0" chnl="15" />
<char id="338" x="254,875" y="633,625" width="66,625" height="54,5" xoffset="-6,25" yoffset="6,5" xadvance="55" page="0" chnl="15" />
<char id="339" x="245" y="743,875" width="65,5" height="46,875" xoffset="-6,625" yoffset="15" xadvance="52,25" page="0" chnl="15" />
<char id="340" x="323,25" y="70" width="51,625" height="69" xoffset="-4" yoffset="-8" xadvance="38,5" page="0" chnl="15" />
<char id="341" x="570,875" y="399,75" width="35,5" height="59,375" xoffset="-4,5" yoffset="1,625" xadvance="23" page="0" chnl="15" />
<char id="342" x="388,75" y="274,25" width="51,625" height="65,375" xoffset="-4" yoffset="6,5" xadvance="38,5" page="0" chnl="15" />
<char id="343" x="380,75" y="575,375" width="35,5" height="56" xoffset="-4,5" yoffset="15,875" xadvance="23" page="0" chnl="15" />
<char id="344" x="271,5" y="70" width="51,625" height="69" xoffset="-4" yoffset="-8" xadvance="38,5" page="0" chnl="15" />
<char id="345" x="983,875" y="336,625" width="38,875" height="59,375" xoffset="-6,625" yoffset="1,625" xadvance="23" page="0" chnl="15" />
<char id="346" x="867,375" y="0" width="46,75" height="69,75" xoffset="-6,125" yoffset="-8" xadvance="33,625" page="0" chnl="15" />
<char id="347" x="256,875" y="402,5" width="40,875" height="60,125" xoffset="-6,5" yoffset="1,625" xadvance="27,25" page="0" chnl="15" />
<char id="348" x="820,5" y="0" width="46,75" height="69,75" xoffset="-6,125" yoffset="-8" xadvance="33,625" page="0" chnl="15" />
<char id="349" x="215,875" y="403" width="40,875" height="60,125" xoffset="-6,5" yoffset="1,625" xadvance="27,25" page="0" chnl="15" />
<char id="350" x="815,625" y="206,5" width="46,75" height="66,125" xoffset="-6,125" yoffset="5,75" xadvance="33,625" page="0" chnl="15" />
<char id="351" x="41,875" y="524,25" width="40,875" height="56,875" xoffset="-6,5" yoffset="15" xadvance="27,25" page="0" chnl="15" />
<char id="352" x="914,25" y="0" width="46,75" height="69,75" xoffset="-6,125" yoffset="-8" xadvance="33,625" page="0" chnl="15" />
<char id="353" x="297,875" y="402,125" width="40,875" height="60,125" xoffset="-6,5" yoffset="1,625" xadvance="27,25" page="0" chnl="15" />
<char id="354" x="588,375" y="273,75" width="48,375" height="65,375" xoffset="-8" yoffset="6,5" xadvance="32,5" page="0" chnl="15" />
<char id="355" x="980,875" y="272,25" width="37,25" height="64,25" xoffset="-7,5" yoffset="7,625" xadvance="22" page="0" chnl="15" />
<char id="356" x="572,125" y="70" width="48,375" height="69" xoffset="-8" yoffset="-8" xadvance="32,5" page="0" chnl="15" />
<char id="357" x="750" y="458" width="49,625" height="56,875" xoffset="-7,5" yoffset="4,75" xadvance="32,875" page="0" chnl="15" />
<char id="358" x="195,875" y="689,25" width="48,375" height="54,5" xoffset="-8" yoffset="6,5" xadvance="32,5" page="0" chnl="15" />
<char id="359" x="856,75" y="681,375" width="37,25" height="54" xoffset="-7,5" yoffset="7,625" xadvance="22" page="0" chnl="15" />
<char id="360" x="414,25" y="139,125" width="48,125" height="68,125" xoffset="-4,5" yoffset="-6,25" xadvance="39,125" page="0" chnl="15" />
<char id="361" x="967,625" y="397,5" width="43,125" height="58,5" xoffset="-4,75" yoffset="3,375" xadvance="33,875" page="0" chnl="15" />
<char id="362" x="415,625" y="207,375" width="48,125" height="66,75" xoffset="-4,5" yoffset="-4,875" xadvance="39,125" page="0" chnl="15" />
<char id="363" x="576,75" y="459,25" width="43,125" height="57,125" xoffset="-4,75" yoffset="4,75" xadvance="33,875" page="0" chnl="15" />
<char id="364" x="207,5" y="139,25" width="48,125" height="68,875" xoffset="-4,5" yoffset="-7" xadvance="39,125" page="0" chnl="15" />
<char id="365" x="790,125" y="398,375" width="43,125" height="59,25" xoffset="-4,75" yoffset="2,625" xadvance="33,875" page="0" chnl="15" />
<char id="366" x="462,5" y="139,125" width="48,125" height="68,125" xoffset="-4,5" yoffset="-6,25" xadvance="39,125" page="0" chnl="15" />
<char id="367" x="86,875" y="342,125" width="43,125" height="61,5" xoffset="-4,75" yoffset="0,375" xadvance="33,875" page="0" chnl="15" />
<char id="368" x="628,25" y="0" width="48,125" height="69,875" xoffset="-4,5" yoffset="-8" xadvance="39,125" page="0" chnl="15" />
<char id="369" x="807,625" y="338" width="43,125" height="60,25" xoffset="-4,75" yoffset="1,625" xadvance="33,875" page="0" chnl="15" />
<char id="370" x="775,875" y="272,75" width="48,125" height="65,125" xoffset="-4,5" yoffset="6,5" xadvance="39,125" page="0" chnl="15" />
<char id="371" x="506,875" y="574,75" width="43,125" height="55,75" xoffset="-4,75" yoffset="15,875" xadvance="33,875" page="0" chnl="15" />
<char id="372" x="44,625" y="70,375" width="69" height="69" xoffset="-7,25" yoffset="-8" xadvance="54,5" page="0" chnl="15" />
<char id="373" x="338,875" y="402,125" width="62,375" height="59,375" xoffset="-7,625" yoffset="1,625" xadvance="47,125" page="0" chnl="15" />
<char id="374" x="219" y="70,125" width="52,375" height="69" xoffset="-8,5" yoffset="-8" xadvance="35,5" page="0" chnl="15" />
<char id="375" x="125,625" y="0" width="46,75" height="70" xoffset="-8,125" yoffset="1,625" xadvance="30,5" page="0" chnl="15" />
<char id="376" x="0" y="276,125" width="52,375" height="66" xoffset="-8,5" yoffset="-5" xadvance="35,5" page="0" chnl="15" />
<char id="377" x="667,25" y="70" width="46,5" height="69" xoffset="-6,625" yoffset="-8" xadvance="33" page="0" chnl="15" />
<char id="378" x="529,375" y="399,75" width="41,375" height="59,375" xoffset="-6,75" yoffset="1,625" xadvance="27,875" page="0" chnl="15" />
<char id="379" x="52,5" y="276" width="46,5" height="66" xoffset="-6,625" yoffset="-5" xadvance="33" page="0" chnl="15" />
<char id="380" x="331,875" y="520" width="41,375" height="56,375" xoffset="-6,75" yoffset="4,625" xadvance="27,875" page="0" chnl="15" />
<char id="381" x="620,625" y="70" width="46,5" height="69" xoffset="-6,625" yoffset="-8" xadvance="33" page="0" chnl="15" />
<char id="382" x="487,875" y="400,125" width="41,375" height="59,375" xoffset="-6,75" yoffset="1,625" xadvance="27,875" page="0" chnl="15" />
<char id="383" x="297,875" y="520" width="33,875" height="56,5" xoffset="-4,5" yoffset="4,5" xadvance="17,125" page="0" chnl="15" />
</chars>
</font>

Binary file not shown.

After

Width:  |  Height:  |  Size: 321 KiB

View file

@ -0,0 +1,796 @@
<?xml version="1.0"?>
<font>
<info face="Tahoma" size="64" bold="0" italic="0" charset="" unicode="1" stretchH="100" smooth="0" aa="1" padding="64,64,64,64" spacing="1,1" outline="0" />
<common lineHeight="64" base="53" scaleW="1024" scaleH="1024" pages="1" packed="0" alphaChnl="0" redChnl="0" greenChnl="0" blueChnl="0" />
<pages>
<page id="0" file="TahomaN_0.png" />
</pages>
<chars count="319">
<char id="32" x="1005,625" y="0" width="16,125" height="16,125" xoffset="-8" yoffset="45" xadvance="16,625" page="0" chnl="15" />
<char id="33" x="667,125" y="619,5" width="21,75" height="54,5" xoffset="-2,125" yoffset="6,5" xadvance="17,625" page="0" chnl="15" />
<char id="34" x="338,875" y="724,5" width="31,375" height="31" xoffset="-5" yoffset="4,75" xadvance="21,25" page="0" chnl="15" />
<char id="35" x="647,25" y="564,875" width="47,25" height="54,5" xoffset="-4,375" yoffset="6,5" xadvance="38,5" page="0" chnl="15" />
<char id="36" x="42,25" y="208,375" width="39,75" height="66,125" xoffset="-5,25" yoffset="4,125" xadvance="28,875" page="0" chnl="15" />
<char id="37" x="538,875" y="453,5" width="62,5" height="56" xoffset="-5,375" yoffset="5,75" xadvance="51,75" page="0" chnl="15" />
<char id="38" x="601,5" y="453,375" width="51,625" height="56" xoffset="-6,25" yoffset="5,75" xadvance="35,75" page="0" chnl="15" />
<char id="39" x="370,375" y="724,5" width="21,625" height="31" xoffset="-5,25" yoffset="4,75" xadvance="11,125" page="0" chnl="15" />
<char id="40" x="686,25" y="139" width="31,625" height="66,875" xoffset="-5,25" yoffset="4,75" xadvance="20,25" page="0" chnl="15" />
<char id="41" x="718" y="139" width="31,625" height="66,875" xoffset="-6,125" yoffset="4,75" xadvance="20,25" page="0" chnl="15" />
<char id="42" x="66,75" y="727,125" width="39,375" height="40" xoffset="-5,125" yoffset="4,75" xadvance="28,875" page="0" chnl="15" />
<char id="43" x="973,75" y="613,75" width="46,5" height="46,375" xoffset="-4" yoffset="12,875" xadvance="38,5" page="0" chnl="15" />
<char id="44" x="267" y="725,875" width="27" height="33" xoffset="-6,125" yoffset="37,625" xadvance="16" page="0" chnl="15" />
<char id="45" x="598,875" y="719,5" width="30,625" height="20,625" xoffset="-5,625" yoffset="25,75" xadvance="19,25" page="0" chnl="15" />
<char id="46" x="522,375" y="722,5" width="22,125" height="23,375" xoffset="-3,125" yoffset="37,625" xadvance="16" page="0" chnl="15" />
<char id="47" x="79,5" y="274,625" width="35,5" height="64,625" xoffset="-8,625" yoffset="4,75" xadvance="20,25" page="0" chnl="15" />
<char id="48" x="920,5" y="447,75" width="40,625" height="56" xoffset="-5,875" yoffset="5,75" xadvance="28,875" page="0" chnl="15" />
<char id="49" x="0" y="571,625" width="34,875" height="54,625" xoffset="-2,25" yoffset="6,375" xadvance="28,875" page="0" chnl="15" />
<char id="50" x="581,375" y="509,625" width="39,75" height="55,25" xoffset="-5,125" yoffset="5,75" xadvance="28,875" page="0" chnl="15" />
<char id="51" x="961,25" y="447,125" width="39,375" height="56" xoffset="-5,5" yoffset="5,75" xadvance="28,875" page="0" chnl="15" />
<char id="52" x="131" y="625,875" width="42,625" height="54,5" xoffset="-7" yoffset="6,5" xadvance="28,875" page="0" chnl="15" />
<char id="53" x="660,375" y="506,375" width="39" height="55,25" xoffset="-4,75" yoffset="6,5" xadvance="28,875" page="0" chnl="15" />
<char id="54" x="879,375" y="447,75" width="41" height="56" xoffset="-5,75" yoffset="5,75" xadvance="28,875" page="0" chnl="15" />
<char id="55" x="341,375" y="624,125" width="40,5" height="54,5" xoffset="-5,375" yoffset="6,5" xadvance="28,875" page="0" chnl="15" />
<char id="56" x="497,625" y="453,625" width="41,125" height="56,125" xoffset="-6,125" yoffset="5,625" xadvance="28,875" page="0" chnl="15" />
<char id="57" x="838,25" y="448,375" width="41" height="56" xoffset="-6,25" yoffset="5,75" xadvance="28,875" page="0" chnl="15" />
<char id="58" x="723" y="670,25" width="22,125" height="44,875" xoffset="-1,75" yoffset="16,125" xadvance="18,75" page="0" chnl="15" />
<char id="59" x="640" y="619,625" width="27" height="54,5" xoffset="-4,875" yoffset="16,125" xadvance="18,75" page="0" chnl="15" />
<char id="60" x="354,625" y="678,75" width="43,75" height="45,625" xoffset="-2,75" yoffset="13,375" xadvance="38,5" page="0" chnl="15" />
<char id="61" x="294,125" y="725,875" width="44,625" height="31" xoffset="-3" yoffset="20,625" xadvance="38,5" page="0" chnl="15" />
<char id="62" x="310,75" y="678,75" width="43,75" height="45,625" xoffset="-2,375" yoffset="13,375" xadvance="38,5" page="0" chnl="15" />
<char id="63" x="775,125" y="506" width="36,75" height="55,25" xoffset="-5,125" yoffset="5,75" xadvance="25,125" page="0" chnl="15" />
<char id="64" x="708,375" y="271,375" width="57,75" height="61,125" xoffset="-4,625" yoffset="5,75" xadvance="48,125" page="0" chnl="15" />
<char id="65" x="550,625" y="565" width="48,25" height="54,5" xoffset="-8,25" yoffset="6,5" xadvance="31,75" page="0" chnl="15" />
<char id="66" x="216,5" y="625,5" width="42,125" height="54,5" xoffset="-4,125" yoffset="6,5" xadvance="31,25" page="0" chnl="15" />
<char id="67" x="750,625" y="449,875" width="45,25" height="56" xoffset="-6,25" yoffset="5,75" xadvance="31,875" page="0" chnl="15" />
<char id="68" x="836,375" y="560,125" width="46,375" height="54,5" xoffset="-4,125" yoffset="6,5" xadvance="36" page="0" chnl="15" />
<char id="69" x="422,5" y="622,875" width="40,125" height="54,5" xoffset="-4,125" yoffset="6,5" xadvance="29,75" page="0" chnl="15" />
<char id="70" x="462,75" y="622,875" width="39,125" height="54,5" xoffset="-4,125" yoffset="6,5" xadvance="27,625" page="0" chnl="15" />
<char id="71" x="703,375" y="450,25" width="47,125" height="56" xoffset="-6,25" yoffset="5,75" xadvance="35,375" page="0" chnl="15" />
<char id="72" x="0" y="626,375" width="44" height="54,5" xoffset="-4,125" yoffset="6,5" xadvance="35,75" page="0" chnl="15" />
<char id="73" x="579" y="619,625" width="30,875" height="54,5" xoffset="-5,5" yoffset="6,5" xadvance="19,75" page="0" chnl="15" />
<char id="74" x="901,75" y="503,875" width="34,25" height="55,125" xoffset="-7,75" yoffset="6,5" xadvance="22,125" page="0" chnl="15" />
<char id="75" x="975,25" y="558,125" width="44,125" height="54,5" xoffset="-4,125" yoffset="6,5" xadvance="31,125" page="0" chnl="15" />
<char id="76" x="540,5" y="619,875" width="38,375" height="54,5" xoffset="-4,125" yoffset="6,5" xadvance="26,375" page="0" chnl="15" />
<char id="77" x="501,375" y="565,25" width="49,125" height="54,5" xoffset="-4,125" yoffset="6,5" xadvance="40,875" page="0" chnl="15" />
<char id="78" x="44,125" y="626" width="43,625" height="54,5" xoffset="-4,125" yoffset="6,5" xadvance="35,375" page="0" chnl="15" />
<char id="79" x="653,25" y="450,25" width="50" height="56" xoffset="-6,25" yoffset="5,75" xadvance="37,5" page="0" chnl="15" />
<char id="80" x="382" y="624" width="40,375" height="54,5" xoffset="-4,125" yoffset="6,5" xadvance="29,25" page="0" chnl="15" />
<char id="81" x="213,125" y="207,75" width="50,125" height="65,375" xoffset="-6,25" yoffset="5,75" xadvance="37,5" page="0" chnl="15" />
<char id="82" x="929,25" y="559,125" width="45,875" height="54,5" xoffset="-4,125" yoffset="6,5" xadvance="32,875" page="0" chnl="15" />
<char id="83" x="796" y="448,75" width="42,125" height="56" xoffset="-6" yoffset="5,75" xadvance="29,5" page="0" chnl="15" />
<char id="84" x="789,125" y="561,375" width="47,125" height="54,5" xoffset="-8,125" yoffset="6,5" xadvance="31" page="0" chnl="15" />
<char id="85" x="455,125" y="511" width="43,75" height="55,25" xoffset="-4,5" yoffset="6,5" xadvance="34,75" page="0" chnl="15" />
<char id="86" x="599" y="565" width="48,125" height="54,5" xoffset="-8,25" yoffset="6,5" xadvance="31,625" page="0" chnl="15" />
<char id="87" x="163,125" y="570,875" width="62,5" height="54,5" xoffset="-7,375" yoffset="6,5" xadvance="47,75" page="0" chnl="15" />
<char id="88" x="882,875" y="559,75" width="46,25" height="54,5" xoffset="-7,75" yoffset="6,5" xadvance="30,75" page="0" chnl="15" />
<char id="89" x="741,875" y="561,75" width="47,125" height="54,5" xoffset="-8,25" yoffset="6,5" xadvance="30,5" page="0" chnl="15" />
<char id="90" x="87,875" y="626" width="43" height="54,5" xoffset="-6,5" yoffset="6,5" xadvance="29,625" page="0" chnl="15" />
<char id="91" x="824,75" y="139" width="29,5" height="66,375" xoffset="-3,75" yoffset="4,75" xadvance="20,25" page="0" chnl="15" />
<char id="92" x="43,875" y="274,625" width="35,5" height="64,625" xoffset="-6,625" yoffset="4,75" xadvance="20,25" page="0" chnl="15" />
<char id="93" x="854,375" y="139" width="29,5" height="66,375" xoffset="-5,5" yoffset="4,75" xadvance="20,25" page="0" chnl="15" />
<char id="94" x="137,125" y="727,125" width="47,625" height="36,875" xoffset="-4,5" yoffset="6,5" xadvance="38,5" page="0" chnl="15" />
<char id="95" x="706,25" y="719,125" width="45,625" height="19,375" xoffset="-8,375" yoffset="49,375" xadvance="28,875" page="0" chnl="15" />
<char id="96" x="495,375" y="722,5" width="26,875" height="25,625" xoffset="-1,625" yoffset="1,625" xadvance="28,875" page="0" chnl="15" />
<char id="97" x="101,625" y="680,625" width="39" height="46,375" xoffset="-6,5" yoffset="15,375" xadvance="27,875" page="0" chnl="15" />
<char id="98" x="690,375" y="393,125" width="40,25" height="57" xoffset="-4,5" yoffset="4,75" xadvance="29,25" page="0" chnl="15" />
<char id="99" x="181,75" y="680,125" width="38,125" height="46,25" xoffset="-6,5" yoffset="15,375" xadvance="24,5" page="0" chnl="15" />
<char id="100" x="650" y="393,125" width="40,25" height="57" xoffset="-6,5" yoffset="4,75" xadvance="29,25" page="0" chnl="15" />
<char id="101" x="140,75" y="680,5" width="40,875" height="46,25" xoffset="-6,5" yoffset="15,375" xadvance="27,875" page="0" chnl="15" />
<char id="102" x="966" y="390,5" width="34" height="56,5" xoffset="-7,25" yoffset="4,5" xadvance="16,875" page="0" chnl="15" />
<char id="103" x="772,875" y="392,125" width="40,25" height="56,5" xoffset="-6,5" yoffset="15,375" xadvance="29,25" page="0" chnl="15" />
<char id="104" x="324,125" y="457,125" width="38,625" height="56,25" xoffset="-4,5" yoffset="4,75" xadvance="29,5" page="0" chnl="15" />
<char id="105" x="1000,75" y="446,125" width="21,5" height="54,75" xoffset="-4,625" yoffset="6,25" xadvance="12,125" page="0" chnl="15" />
<char id="106" x="159,125" y="208" width="29,75" height="65,625" xoffset="-10,375" yoffset="6,25" xadvance="14,875" page="0" chnl="15" />
<char id="107" x="284" y="457,5" width="40" height="56,25" xoffset="-4,5" yoffset="4,75" xadvance="26,375" page="0" chnl="15" />
<char id="108" x="1000,125" y="389,75" width="20,875" height="56,25" xoffset="-4,375" yoffset="4,75" xadvance="12,125" page="0" chnl="15" />
<char id="109" x="257" y="680,125" width="53,625" height="45,625" xoffset="-4,5" yoffset="15,375" xadvance="44,5" page="0" chnl="15" />
<char id="110" x="437,25" y="677,5" width="38,625" height="45,625" xoffset="-4,5" yoffset="15,375" xadvance="29,5" page="0" chnl="15" />
<char id="111" x="59,75" y="680,625" width="41,75" height="46,375" xoffset="-6,5" yoffset="15,375" xadvance="28,75" page="0" chnl="15" />
<char id="112" x="203,25" y="458,125" width="40,25" height="56,25" xoffset="-4,5" yoffset="15,375" xadvance="29,25" page="0" chnl="15" />
<char id="113" x="243,625" y="457,625" width="40,25" height="56,25" xoffset="-6,5" yoffset="15,375" xadvance="29,25" page="0" chnl="15" />
<char id="114" x="691,5" y="674,125" width="31,375" height="44,875" xoffset="-4,5" yoffset="16,125" xadvance="19,125" page="0" chnl="15" />
<char id="115" x="220" y="680,125" width="36,875" height="46,25" xoffset="-6,25" yoffset="15,375" xadvance="23,625" page="0" chnl="15" />
<char id="116" x="710,875" y="616,375" width="33" height="53,75" xoffset="-7,375" yoffset="7,875" xadvance="17,75" page="0" chnl="15" />
<char id="117" x="398,5" y="678,625" width="38,625" height="45,625" xoffset="-4,625" yoffset="16,125" xadvance="29,5" page="0" chnl="15" />
<char id="118" x="530" y="674,5" width="42,125" height="44,875" xoffset="-7,875" yoffset="16,125" xadvance="26,375" page="0" chnl="15" />
<char id="119" x="476" y="677,5" width="53,875" height="44,875" xoffset="-7,25" yoffset="16,125" xadvance="39,375" page="0" chnl="15" />
<char id="120" x="572,25" y="674,5" width="41,75" height="44,875" xoffset="-7,75" yoffset="16,125" xadvance="26,25" page="0" chnl="15" />
<char id="121" x="71,875" y="515,625" width="42,125" height="55,5" xoffset="-7,875" yoffset="16,125" xadvance="26,375" page="0" chnl="15" />
<char id="122" x="654,25" y="674,25" width="37,125" height="44,875" xoffset="-6,75" yoffset="16,125" xadvance="23,5" page="0" chnl="15" />
<char id="123" x="749,75" y="139" width="37,375" height="66,375" xoffset="-6,5" yoffset="4,75" xadvance="25,5" page="0" chnl="15" />
<char id="124" x="884" y="139" width="20,375" height="66,375" xoffset="0" yoffset="4,75" xadvance="20,25" page="0" chnl="15" />
<char id="125" x="787,25" y="139" width="37,375" height="66,375" xoffset="-5,5" yoffset="4,75" xadvance="25,5" page="0" chnl="15" />
<char id="126" x="392,125" y="724,5" width="47,5" height="29,75" xoffset="-4,5" yoffset="21" xadvance="38,5" page="0" chnl="15" />
<char id="160" x="1003,5" y="501" width="16,125" height="16,125" xoffset="-8" yoffset="45" xadvance="16,625" page="0" chnl="15" />
<char id="161" x="689" y="619,5" width="21,75" height="54,5" xoffset="-2,125" yoffset="6,5" xadvance="17,625" page="0" chnl="15" />
<char id="162" x="592,125" y="271,625" width="38,25" height="63,5" xoffset="-5" yoffset="6,875" xadvance="28,875" page="0" chnl="15" />
<char id="163" x="540,875" y="509,625" width="40,375" height="55,25" xoffset="-5,75" yoffset="5,75" xadvance="28,875" page="0" chnl="15" />
<char id="164" x="810,25" y="668,25" width="41,625" height="41,75" xoffset="-6,25" yoffset="15,125" xadvance="28,875" page="0" chnl="15" />
<char id="165" x="258,75" y="624,75" width="41,875" height="54,5" xoffset="-6,625" yoffset="6,5" xadvance="28,875" page="0" chnl="15" />
<char id="166" x="904,5" y="139" width="20,375" height="66,375" xoffset="0" yoffset="4,75" xadvance="20,25" page="0" chnl="15" />
<char id="167" x="701,875" y="206" width="38,75" height="65,25" xoffset="-4,875" yoffset="5,75" xadvance="28,875" page="0" chnl="15" />
<char id="168" x="566,875" y="719,5" width="31,875" height="21" xoffset="-1,5" yoffset="6,25" xadvance="28,875" page="0" chnl="15" />
<char id="169" x="766,25" y="271,375" width="60,75" height="60,75" xoffset="-5,75" yoffset="5,75" xadvance="49,25" page="0" chnl="15" />
<char id="170" x="970,875" y="660,875" width="35,625" height="41,25" xoffset="-5" yoffset="5,75" xadvance="26,125" page="0" chnl="15" />
<char id="171" x="852" y="665" width="40,375" height="41,375" xoffset="-5,375" yoffset="15,375" xadvance="30,375" page="0" chnl="15" />
<char id="172" x="220,75" y="726,5" width="46,125" height="34,25" xoffset="-3,875" yoffset="25,25" xadvance="38,5" page="0" chnl="15" />
<char id="173" x="629,625" y="719,25" width="30,625" height="20,625" xoffset="-5,625" yoffset="25,75" xadvance="19,25" page="0" chnl="15" />
<char id="174" x="827,125" y="270,75" width="60,75" height="60,75" xoffset="-5,75" yoffset="5,75" xadvance="49,25" page="0" chnl="15" />
<char id="175" x="660,375" y="719,25" width="45,75" height="19,375" xoffset="-8,375" yoffset="-1,25" xadvance="28,875" page="0" chnl="15" />
<char id="176" x="184,875" y="726,5" width="35,75" height="35,625" xoffset="-5,375" yoffset="5,75" xadvance="25" page="0" chnl="15" />
<char id="177" x="865,875" y="614,75" width="46,5" height="48,25" xoffset="-4" yoffset="8,625" xadvance="38,5" page="0" chnl="15" />
<char id="178" x="33" y="727,5" width="33,625" height="40,625" xoffset="-3,25" yoffset="5,75" xadvance="26,125" page="0" chnl="15" />
<char id="179" x="0" y="727,5" width="32,875" height="41,25" xoffset="-3,25" yoffset="5,75" xadvance="26,125" page="0" chnl="15" />
<char id="180" x="468,375" y="723,25" width="26,875" height="25,625" xoffset="3,625" yoffset="1,625" xadvance="28,875" page="0" chnl="15" />
<char id="181" x="156" y="515,25" width="39,125" height="55,5" xoffset="-4,5" yoffset="16,125" xadvance="30,125" page="0" chnl="15" />
<char id="182" x="519,125" y="272" width="39,875" height="63,875" xoffset="-6,5" yoffset="6,5" xadvance="28,875" page="0" chnl="15" />
<char id="183" x="544,625" y="719,5" width="22,125" height="23,375" xoffset="-1,75" yoffset="16,125" xadvance="18,75" page="0" chnl="15" />
<char id="184" x="439,75" y="723,25" width="28,5" height="27,375" xoffset="-0,5" yoffset="44,5" xadvance="28,875" page="0" chnl="15" />
<char id="185" x="106,25" y="727,125" width="30,75" height="39,875" xoffset="-1,625" yoffset="6,5" xadvance="26,125" page="0" chnl="15" />
<char id="186" x="933" y="660,875" width="37,75" height="41,25" xoffset="-5,75" yoffset="5,75" xadvance="26,125" page="0" chnl="15" />
<char id="187" x="892,5" y="663,125" width="40,375" height="41,375" xoffset="-4,625" yoffset="15,375" xadvance="30,375" page="0" chnl="15" />
<char id="188" x="287,75" y="569,5" width="59,25" height="54,5" xoffset="-3,5" yoffset="6,5" xadvance="53" page="0" chnl="15" />
<char id="189" x="225,75" y="570,125" width="61,875" height="54,5" xoffset="-3,5" yoffset="6,5" xadvance="53" page="0" chnl="15" />
<char id="190" x="393,375" y="512,875" width="61,625" height="55,25" xoffset="-4,375" yoffset="5,75" xadvance="53" page="0" chnl="15" />
<char id="191" x="738,25" y="506,375" width="36,75" height="55,25" xoffset="-6,5" yoffset="6,5" xadvance="25,125" page="0" chnl="15" />
<char id="192" x="62,625" y="70,25" width="48,25" height="69" xoffset="-8,25" yoffset="-8" xadvance="31,75" page="0" chnl="15" />
<char id="193" x="111" y="70,25" width="48,25" height="69" xoffset="-8,25" yoffset="-8" xadvance="31,75" page="0" chnl="15" />
<char id="194" x="141,25" y="139,375" width="48,25" height="68,5" xoffset="-8,25" yoffset="-7,5" xadvance="31,75" page="0" chnl="15" />
<char id="195" x="597,5" y="139" width="48,25" height="66,875" xoffset="-8,25" yoffset="-5,875" xadvance="31,75" page="0" chnl="15" />
<char id="196" x="430,5" y="272,5" width="48,25" height="63,875" xoffset="-8,25" yoffset="-2,875" xadvance="31,75" page="0" chnl="15" />
<char id="197" x="403,875" y="139" width="48,25" height="67,5" xoffset="-8,25" yoffset="-6,5" xadvance="31,75" page="0" chnl="15" />
<char id="198" x="99,375" y="571,25" width="63,625" height="54,5" xoffset="-9" yoffset="6,5" xadvance="48,375" page="0" chnl="15" />
<char id="199" x="972,25" y="138,875" width="45,25" height="66,125" xoffset="-6,25" yoffset="5,75" xadvance="31,875" page="0" chnl="15" />
<char id="200" x="778,25" y="69,875" width="40,125" height="69" xoffset="-4,125" yoffset="-8" xadvance="29,75" page="0" chnl="15" />
<char id="201" x="738" y="69,875" width="40,125" height="69" xoffset="-4,125" yoffset="-8" xadvance="29,75" page="0" chnl="15" />
<char id="202" x="657,5" y="69,875" width="40,125" height="69" xoffset="-4,125" yoffset="-8" xadvance="29,75" page="0" chnl="15" />
<char id="203" x="245,75" y="273,25" width="40,125" height="64,375" xoffset="-4,125" yoffset="-3,375" xadvance="29,75" page="0" chnl="15" />
<char id="204" x="960,5" y="69,75" width="30,875" height="69" xoffset="-5,5" yoffset="-8" xadvance="19,75" page="0" chnl="15" />
<char id="205" x="929,5" y="69,75" width="30,875" height="69" xoffset="-5,5" yoffset="-8" xadvance="19,75" page="0" chnl="15" />
<char id="206" x="895,75" y="69,875" width="33,625" height="69" xoffset="-6,75" yoffset="-8" xadvance="19,75" page="0" chnl="15" />
<char id="207" x="286" y="272,75" width="31,875" height="64,375" xoffset="-6" yoffset="-3,375" xadvance="19,75" page="0" chnl="15" />
<char id="208" x="399,875" y="568,25" width="50,625" height="54,5" xoffset="-7,375" yoffset="6,5" xadvance="37" page="0" chnl="15" />
<char id="209" x="487,75" y="139" width="43,625" height="67,375" xoffset="-4,125" yoffset="-6,375" xadvance="35,375" page="0" chnl="15" />
<char id="210" x="298,875" y="0" width="50" height="69,75" xoffset="-6,25" yoffset="-8" xadvance="37,5" page="0" chnl="15" />
<char id="211" x="248,75" y="0" width="50" height="69,75" xoffset="-6,25" yoffset="-8" xadvance="37,5" page="0" chnl="15" />
<char id="212" x="198,625" y="0" width="50" height="69,75" xoffset="-6,25" yoffset="-8" xadvance="37,5" page="0" chnl="15" />
<char id="213" x="233,5" y="139" width="50" height="68,125" xoffset="-6,25" yoffset="-6,375" xadvance="37,5" page="0" chnl="15" />
<char id="214" x="771,75" y="205,5" width="50" height="65,125" xoffset="-6,25" yoffset="-3,375" xadvance="37,5" page="0" chnl="15" />
<char id="215" x="766,25" y="670,25" width="43,875" height="43,875" xoffset="-2,625" yoffset="14,25" xadvance="38,5" page="0" chnl="15" />
<char id="216" x="705,125" y="332,875" width="50" height="59,875" xoffset="-6,25" yoffset="4,125" xadvance="37,5" page="0" chnl="15" />
<char id="217" x="670,25" y="0" width="43,75" height="69,75" xoffset="-4,5" yoffset="-8" xadvance="34,75" page="0" chnl="15" />
<char id="218" x="626,375" y="0" width="43,75" height="69,75" xoffset="-4,5" yoffset="-8" xadvance="34,75" page="0" chnl="15" />
<char id="219" x="758" y="0" width="43,75" height="69,75" xoffset="-4,5" yoffset="-8" xadvance="34,75" page="0" chnl="15" />
<char id="220" x="914,5" y="205,5" width="43,75" height="65,125" xoffset="-4,5" yoffset="-3,375" xadvance="34,75" page="0" chnl="15" />
<char id="221" x="206,625" y="69,875" width="47,125" height="69" xoffset="-8,25" yoffset="-8" xadvance="30,5" page="0" chnl="15" />
<char id="222" x="300,75" y="624,125" width="40,5" height="54,5" xoffset="-4,125" yoffset="6,5" xadvance="30" page="0" chnl="15" />
<char id="223" x="512,375" y="396,25" width="40,125" height="57,125" xoffset="-4,5" yoffset="4,5" xadvance="29" page="0" chnl="15" />
<char id="224" x="120,875" y="338,625" width="39" height="60,125" xoffset="-6,5" yoffset="1,625" xadvance="27,875" page="0" chnl="15" />
<char id="225" x="81,75" y="339,375" width="39" height="60,125" xoffset="-6,5" yoffset="1,625" xadvance="27,875" page="0" chnl="15" />
<char id="226" x="160" y="338,625" width="39" height="60,125" xoffset="-6,5" yoffset="1,625" xadvance="27,875" page="0" chnl="15" />
<char id="227" x="292,125" y="398" width="39" height="59" xoffset="-6,5" yoffset="2,75" xadvance="27,875" page="0" chnl="15" />
<char id="228" x="195,25" y="514,5" width="39" height="55,5" xoffset="-6,5" yoffset="6,25" xadvance="27,875" page="0" chnl="15" />
<char id="229" x="630,5" y="271,375" width="39" height="61,5" xoffset="-6,5" yoffset="0,25" xadvance="27,875" page="0" chnl="15" />
<char id="230" x="0" y="681" width="59,625" height="46,375" xoffset="-6,5" yoffset="15,375" xadvance="46,625" page="0" chnl="15" />
<char id="231" x="890,75" y="391,125" width="38,125" height="56,5" xoffset="-6,5" yoffset="15,375" xadvance="24,5" page="0" chnl="15" />
<char id="232" x="397,375" y="336,625" width="40,875" height="60" xoffset="-6,5" yoffset="1,625" xadvance="27,875" page="0" chnl="15" />
<char id="233" x="438,375" y="336,5" width="40,875" height="60" xoffset="-6,5" yoffset="1,625" xadvance="27,875" page="0" chnl="15" />
<char id="234" x="315,375" y="337,25" width="40,875" height="60" xoffset="-6,5" yoffset="1,625" xadvance="27,875" page="0" chnl="15" />
<char id="235" x="314,125" y="513,875" width="40,875" height="55,375" xoffset="-6,5" yoffset="6,25" xadvance="27,875" page="0" chnl="15" />
<char id="236" x="62,5" y="399,625" width="26,875" height="59,375" xoffset="-8,125" yoffset="1,625" xadvance="12,125" page="0" chnl="15" />
<char id="237" x="995" y="330,25" width="26,875" height="59,375" xoffset="-4,75" yoffset="1,625" xadvance="12,125" page="0" chnl="15" />
<char id="238" x="31,5" y="399,625" width="30,875" height="59,375" xoffset="-9,375" yoffset="1,625" xadvance="12,125" page="0" chnl="15" />
<char id="239" x="973,375" y="503,25" width="30" height="54,75" xoffset="-9" yoffset="6,25" xadvance="12,125" page="0" chnl="15" />
<char id="240" x="439,375" y="396,625" width="41,75" height="57,25" xoffset="-6,5" yoffset="4,5" xadvance="28,875" page="0" chnl="15" />
<char id="241" x="370" y="396,875" width="38,625" height="58,25" xoffset="-4,5" yoffset="2,75" xadvance="29,5" page="0" chnl="15" />
<char id="242" x="971,75" y="270" width="41,75" height="60,125" xoffset="-6,5" yoffset="1,625" xadvance="28,75" page="0" chnl="15" />
<char id="243" x="929,875" y="270,75" width="41,75" height="60,125" xoffset="-6,5" yoffset="1,625" xadvance="28,75" page="0" chnl="15" />
<char id="244" x="888" y="270,75" width="41,75" height="60,125" xoffset="-6,5" yoffset="1,625" xadvance="28,75" page="0" chnl="15" />
<char id="245" x="209,25" y="398,5" width="41,75" height="59" xoffset="-6,5" yoffset="2,75" xadvance="28,75" page="0" chnl="15" />
<char id="246" x="114,125" y="515,25" width="41,75" height="55,5" xoffset="-6,5" yoffset="6,25" xadvance="28,75" page="0" chnl="15" />
<char id="247" x="819,375" y="616" width="46,375" height="48,875" xoffset="-3,875" yoffset="11,625" xadvance="38,5" page="0" chnl="15" />
<char id="248" x="777,125" y="616,375" width="42,125" height="51,75" xoffset="-6,875" yoffset="13" xadvance="28,75" page="0" chnl="15" />
<char id="249" x="276,625" y="337,75" width="38,625" height="60,125" xoffset="-4,625" yoffset="1,625" xadvance="29,5" page="0" chnl="15" />
<char id="250" x="237,875" y="338,125" width="38,625" height="60,125" xoffset="-4,625" yoffset="1,625" xadvance="29,5" page="0" chnl="15" />
<char id="251" x="199,125" y="338,25" width="38,625" height="60,125" xoffset="-4,625" yoffset="1,625" xadvance="29,5" page="0" chnl="15" />
<char id="252" x="234,375" y="514,5" width="38,625" height="55,5" xoffset="-4,625" yoffset="6,25" xadvance="29,5" page="0" chnl="15" />
<char id="253" x="114,125" y="0" width="42,125" height="70" xoffset="-7,875" yoffset="1,625" xadvance="26,375" page="0" chnl="15" />
<char id="254" x="645,875" y="139" width="40,25" height="66,875" xoffset="-4,5" yoffset="4,75" xadvance="29,25" page="0" chnl="15" />
<char id="255" x="488,375" y="206,5" width="42,125" height="65,375" xoffset="-7,875" yoffset="6,25" xadvance="26,375" page="0" chnl="15" />
<char id="256" x="382,125" y="272,625" width="48,25" height="63,875" xoffset="-8,25" yoffset="-2,875" xadvance="31,75" page="0" chnl="15" />
<char id="257" x="621,25" y="509,5" width="39" height="55,25" xoffset="-6,5" yoffset="6,5" xadvance="27,875" page="0" chnl="15" />
<char id="258" x="283,625" y="139" width="48,25" height="68" xoffset="-8,25" yoffset="-7" xadvance="31,75" page="0" chnl="15" />
<char id="259" x="131,375" y="398,875" width="39" height="59,125" xoffset="-6,5" yoffset="2,625" xadvance="27,875" page="0" chnl="15" />
<char id="260" x="569,125" y="206,25" width="48,5" height="65,25" xoffset="-8,25" yoffset="6,5" xadvance="31,75" page="0" chnl="15" />
<char id="261" x="71,875" y="459,125" width="39,625" height="56,375" xoffset="-6,5" yoffset="15,375" xadvance="27,875" page="0" chnl="15" />
<char id="262" x="446,375" y="0" width="45,25" height="69,75" xoffset="-6,25" yoffset="-8" xadvance="31,875" page="0" chnl="15" />
<char id="263" x="479,375" y="336,125" width="38,125" height="60" xoffset="-6,5" yoffset="1,625" xadvance="24,5" page="0" chnl="15" />
<char id="264" x="491,75" y="0" width="45,25" height="69,75" xoffset="-6,25" yoffset="-8" xadvance="31,875" page="0" chnl="15" />
<char id="265" x="517,625" y="336,125" width="38,125" height="60" xoffset="-6,5" yoffset="1,625" xadvance="24,5" page="0" chnl="15" />
<char id="266" x="869,125" y="205,5" width="45,25" height="65,125" xoffset="-6,25" yoffset="-3,375" xadvance="31,875" page="0" chnl="15" />
<char id="267" x="355,125" y="513,5" width="38,125" height="55,375" xoffset="-6,5" yoffset="6,25" xadvance="24,5" page="0" chnl="15" />
<char id="268" x="537,125" y="0" width="45,25" height="69,75" xoffset="-6,25" yoffset="-8" xadvance="31,875" page="0" chnl="15" />
<char id="269" x="555,875" y="336" width="38,125" height="60" xoffset="-6,5" yoffset="1,625" xadvance="24,5" page="0" chnl="15" />
<char id="270" x="301,125" y="69,875" width="46,375" height="69" xoffset="-4,125" yoffset="-8" xadvance="36" page="0" chnl="15" />
<char id="271" x="552,625" y="396,25" width="52,625" height="57" xoffset="-6,5" yoffset="4,75" xadvance="36,375" page="0" chnl="15" />
<char id="272" x="450,625" y="568,25" width="50,625" height="54,5" xoffset="-7,375" yoffset="6,5" xadvance="37" page="0" chnl="15" />
<char id="273" x="605,375" y="395,375" width="44,5" height="57" xoffset="-6,5" yoffset="4,75" xadvance="30,375" page="0" chnl="15" />
<char id="274" x="478,875" y="272,125" width="40,125" height="63,875" xoffset="-4,125" yoffset="-2,875" xadvance="29,75" page="0" chnl="15" />
<char id="275" x="860,75" y="504,5" width="40,875" height="55,125" xoffset="-6,5" yoffset="6,5" xadvance="27,875" page="0" chnl="15" />
<char id="276" x="332" y="139" width="40,125" height="68" xoffset="-4,125" yoffset="-7" xadvance="29,75" page="0" chnl="15" />
<char id="277" x="251,125" y="398,375" width="40,875" height="59" xoffset="-6,5" yoffset="2,625" xadvance="27,875" page="0" chnl="15" />
<char id="278" x="205,5" y="273,625" width="40,125" height="64,375" xoffset="-4,125" yoffset="-3,375" xadvance="29,75" page="0" chnl="15" />
<char id="279" x="273,125" y="514" width="40,875" height="55,375" xoffset="-6,5" yoffset="6,25" xadvance="27,875" page="0" chnl="15" />
<char id="280" x="661,625" y="206" width="40,125" height="65,25" xoffset="-4,125" yoffset="6,5" xadvance="29,75" page="0" chnl="15" />
<char id="281" x="30,875" y="459,125" width="40,875" height="56,375" xoffset="-6,5" yoffset="15,375" xadvance="27,875" page="0" chnl="15" />
<char id="282" x="697,75" y="69,875" width="40,125" height="69" xoffset="-4,125" yoffset="-8" xadvance="29,75" page="0" chnl="15" />
<char id="283" x="356,375" y="336,75" width="40,875" height="60" xoffset="-6,5" yoffset="1,625" xadvance="27,875" page="0" chnl="15" />
<char id="284" x="399,125" y="0" width="47,125" height="69,75" xoffset="-6,25" yoffset="-8" xadvance="35,375" page="0" chnl="15" />
<char id="285" x="0" y="0" width="40,25" height="70,25" xoffset="-6,5" yoffset="1,625" xadvance="29,25" page="0" chnl="15" />
<char id="286" x="50,125" y="139,5" width="47,125" height="68,75" xoffset="-6,25" yoffset="-7" xadvance="35,375" page="0" chnl="15" />
<char id="287" x="965,25" y="0" width="40,25" height="69,25" xoffset="-6,5" yoffset="2,625" xadvance="29,25" page="0" chnl="15" />
<char id="288" x="821,875" y="205,5" width="47,125" height="65,125" xoffset="-6,25" yoffset="-3,375" xadvance="35,375" page="0" chnl="15" />
<char id="289" x="82,125" y="208,375" width="40,25" height="65,625" xoffset="-6,5" yoffset="6,25" xadvance="29,25" page="0" chnl="15" />
<char id="290" x="925" y="139" width="47,125" height="66,125" xoffset="-6,25" yoffset="5,75" xadvance="35,375" page="0" chnl="15" />
<char id="291" x="40,375" y="0" width="40,25" height="70,125" xoffset="-6,5" yoffset="1,75" xadvance="29,25" page="0" chnl="15" />
<char id="292" x="439,625" y="69,875" width="44" height="69" xoffset="-4,125" yoffset="-8" xadvance="35,75" page="0" chnl="15" />
<char id="293" x="818,5" y="69,875" width="38,625" height="69" xoffset="-4,5" yoffset="-8" xadvance="29,5" page="0" chnl="15" />
<char id="294" x="347,125" y="569,375" width="52,625" height="54,5" xoffset="-7,375" yoffset="6,5" xadvance="37,875" page="0" chnl="15" />
<char id="295" x="160,25" y="458,125" width="42,875" height="56,25" xoffset="-7,625" yoffset="4,75" xadvance="30,625" page="0" chnl="15" />
<char id="296" x="452,25" y="139" width="35,375" height="67,5" xoffset="-7,75" yoffset="-6,5" xadvance="19,75" page="0" chnl="15" />
<char id="297" x="481,25" y="396,25" width="31" height="57,25" xoffset="-9,375" yoffset="3,75" xadvance="12,125" page="0" chnl="15" />
<char id="298" x="559,125" y="272" width="32,875" height="63,875" xoffset="-6,5" yoffset="-2,875" xadvance="19,75" page="0" chnl="15" />
<char id="299" x="610" y="619,625" width="29,875" height="54,5" xoffset="-8,875" yoffset="6,5" xadvance="12,125" page="0" chnl="15" />
<char id="300" x="372,25" y="139" width="31,5" height="67,875" xoffset="-5,75" yoffset="-6,875" xadvance="19,75" page="0" chnl="15" />
<char id="301" x="408,75" y="396,75" width="30,5" height="57,75" xoffset="-9,25" yoffset="3,25" xadvance="12,125" page="0" chnl="15" />
<char id="302" x="740,75" y="206" width="30,875" height="65,25" xoffset="-5,5" yoffset="6,5" xadvance="19,75" page="0" chnl="15" />
<char id="303" x="189" y="208" width="24" height="65,5" xoffset="-6,75" yoffset="6,25" xadvance="12,125" page="0" chnl="15" />
<char id="304" x="318" y="272,625" width="30,875" height="64,375" xoffset="-5,5" yoffset="-3,375" xadvance="19,75" page="0" chnl="15" />
<char id="305" x="745,25" y="670,25" width="20,875" height="44,875" xoffset="-4,375" yoffset="16,125" xadvance="12,125" page="0" chnl="15" />
<char id="306" x="812" y="504,875" width="48,625" height="55,125" xoffset="-5,5" yoffset="6,5" xadvance="38,75" page="0" chnl="15" />
<char id="307" x="122,5" y="208,25" width="36,5" height="65,625" xoffset="-4,625" yoffset="6,25" xadvance="27,375" page="0" chnl="15" />
<char id="308" x="928,625" y="0" width="36,5" height="69,625" xoffset="-7,75" yoffset="-8" xadvance="22,125" page="0" chnl="15" />
<char id="309" x="80,75" y="0" width="33,25" height="70,125" xoffset="-10,375" yoffset="1,75" xadvance="14,875" page="0" chnl="15" />
<char id="310" x="356,625" y="207,125" width="44,125" height="65,375" xoffset="-4,125" yoffset="6,5" xadvance="31,125" page="0" chnl="15" />
<char id="311" x="531,5" y="139" width="40" height="67,125" xoffset="-4,5" yoffset="4,75" xadvance="26,375" page="0" chnl="15" />
<char id="312" x="614,125" y="674,25" width="40" height="44,875" xoffset="-4,5" yoffset="16,125" xadvance="26,375" page="0" chnl="15" />
<char id="313" x="857,25" y="69,875" width="38,375" height="69" xoffset="-4,125" yoffset="-8" xadvance="26,375" page="0" chnl="15" />
<char id="314" x="991,5" y="69,375" width="26,875" height="69" xoffset="-4,875" yoffset="-8" xadvance="12,125" page="0" chnl="15" />
<char id="315" x="530,625" y="206,5" width="38,375" height="65,375" xoffset="-4,125" yoffset="6,5" xadvance="26,375" page="0" chnl="15" />
<char id="316" x="571,625" y="139" width="25,75" height="67,125" xoffset="-6,125" yoffset="4,75" xadvance="12,125" page="0" chnl="15" />
<char id="317" x="362,875" y="456,5" width="38,375" height="56,25" xoffset="-4,125" yoffset="4,75" xadvance="26,375" page="0" chnl="15" />
<char id="318" x="434,75" y="454,625" width="33,25" height="56,25" xoffset="-4,5" yoffset="4,75" xadvance="19,125" page="0" chnl="15" />
<char id="319" x="502" y="619,875" width="38,375" height="54,5" xoffset="-4,125" yoffset="6,5" xadvance="26,375" page="0" chnl="15" />
<char id="320" x="401,375" y="455,25" width="33,25" height="56,25" xoffset="-4,5" yoffset="4,75" xadvance="23,625" page="0" chnl="15" />
<char id="321" x="173,75" y="625,5" width="42,625" height="54,5" xoffset="-7,375" yoffset="6,5" xadvance="27,375" page="0" chnl="15" />
<char id="322" x="468,125" y="454" width="29,375" height="56,25" xoffset="-7,375" yoffset="4,75" xadvance="14,5" page="0" chnl="15" />
<char id="323" x="527,5" y="69,875" width="43,625" height="69" xoffset="-4,125" yoffset="-8" xadvance="35,375" page="0" chnl="15" />
<char id="324" x="848" y="331,625" width="38,625" height="59,375" xoffset="-4,5" yoffset="1,625" xadvance="29,5" page="0" chnl="15" />
<char id="325" x="400,875" y="207" width="43,625" height="65,375" xoffset="-4,125" yoffset="6,5" xadvance="35,375" page="0" chnl="15" />
<char id="326" x="813,25" y="391,75" width="38,625" height="56,5" xoffset="-4,5" yoffset="15,375" xadvance="29,5" page="0" chnl="15" />
<char id="327" x="483,75" y="69,875" width="43,625" height="69" xoffset="-4,125" yoffset="-8" xadvance="35,375" page="0" chnl="15" />
<char id="328" x="809,25" y="332,25" width="38,625" height="59,375" xoffset="-4,5" yoffset="1,625" xadvance="29,5" page="0" chnl="15" />
<char id="329" x="111,625" y="458,875" width="48,5" height="56,25" xoffset="-7,125" yoffset="4,75" xadvance="36,75" page="0" chnl="15" />
<char id="330" x="444,625" y="206,625" width="43,625" height="65,375" xoffset="-4,125" yoffset="6,5" xadvance="35,375" page="0" chnl="15" />
<char id="331" x="852" y="391,125" width="38,625" height="56,5" xoffset="-4,5" yoffset="15,375" xadvance="29,5" page="0" chnl="15" />
<char id="332" x="958,375" y="205,25" width="50" height="64,625" xoffset="-6,25" yoffset="-2,875" xadvance="37,5" page="0" chnl="15" />
<char id="333" x="499" y="509,875" width="41,75" height="55,25" xoffset="-6,5" yoffset="6,5" xadvance="28,75" page="0" chnl="15" />
<char id="334" x="0" y="139,5" width="50" height="68,75" xoffset="-6,25" yoffset="-7" xadvance="37,5" page="0" chnl="15" />
<char id="335" x="89,5" y="399,625" width="41,75" height="59,125" xoffset="-6,5" yoffset="2,625" xadvance="28,75" page="0" chnl="15" />
<char id="336" x="349" y="0" width="50" height="69,75" xoffset="-6,25" yoffset="-8" xadvance="37,5" page="0" chnl="15" />
<char id="337" x="0" y="339,375" width="41,75" height="60,125" xoffset="-6,5" yoffset="1,625" xadvance="28,75" page="0" chnl="15" />
<char id="338" x="35" y="571,375" width="64,25" height="54,5" xoffset="-6,25" yoffset="6,5" xadvance="51,75" page="0" chnl="15" />
<char id="339" x="912,5" y="614,375" width="61,125" height="46,375" xoffset="-6,5" yoffset="15,375" xadvance="48,125" page="0" chnl="15" />
<char id="340" x="393,625" y="69,875" width="45,875" height="69" xoffset="-4,125" yoffset="-8" xadvance="32,875" page="0" chnl="15" />
<char id="341" x="0" y="399,625" width="31,375" height="59,375" xoffset="-4,5" yoffset="1,625" xadvance="19,125" page="0" chnl="15" />
<char id="342" x="310,625" y="207,125" width="45,875" height="65,375" xoffset="-4,125" yoffset="6,5" xadvance="32,875" page="0" chnl="15" />
<char id="343" x="0" y="515,75" width="32,25" height="55,75" xoffset="-5,375" yoffset="16,125" xadvance="19,125" page="0" chnl="15" />
<char id="344" x="347,625" y="69,875" width="45,875" height="69" xoffset="-4,125" yoffset="-8" xadvance="32,875" page="0" chnl="15" />
<char id="345" x="961,25" y="331" width="33,625" height="59,375" xoffset="-6,5" yoffset="1,625" xadvance="19,125" page="0" chnl="15" />
<char id="346" x="801,875" y="0" width="42,125" height="69,75" xoffset="-6" yoffset="-8" xadvance="29,5" page="0" chnl="15" />
<char id="347" x="594,125" y="335,25" width="36,875" height="60" xoffset="-6,25" yoffset="1,625" xadvance="23,625" page="0" chnl="15" />
<char id="348" x="886,375" y="0" width="42,125" height="69,75" xoffset="-6" yoffset="-8" xadvance="29,5" page="0" chnl="15" />
<char id="349" x="631,125" y="333" width="36,875" height="60" xoffset="-6,25" yoffset="1,625" xadvance="23,625" page="0" chnl="15" />
<char id="350" x="0" y="208,375" width="42,125" height="66,125" xoffset="-6" yoffset="5,75" xadvance="29,5" page="0" chnl="15" />
<char id="351" x="929" y="390,5" width="36,875" height="56,5" xoffset="-6,25" yoffset="15,375" xadvance="23,625" page="0" chnl="15" />
<char id="352" x="844,125" y="0" width="42,125" height="69,75" xoffset="-6" yoffset="-8" xadvance="29,5" page="0" chnl="15" />
<char id="353" x="668,125" y="333" width="36,875" height="60" xoffset="-6,25" yoffset="1,625" xadvance="23,625" page="0" chnl="15" />
<char id="354" x="263,375" y="207,25" width="47,125" height="65,375" xoffset="-8,125" yoffset="6,5" xadvance="31" page="0" chnl="15" />
<char id="355" x="349" y="272,625" width="33" height="64" xoffset="-7,375" yoffset="7,875" xadvance="17,75" page="0" chnl="15" />
<char id="356" x="253,875" y="69,875" width="47,125" height="69" xoffset="-8,125" yoffset="-8" xadvance="31" page="0" chnl="15" />
<char id="357" x="730,75" y="392,875" width="42" height="56,875" xoffset="-7,375" yoffset="4,75" xadvance="24,875" page="0" chnl="15" />
<char id="358" x="694,625" y="561,75" width="47,125" height="54,5" xoffset="-8,125" yoffset="6,5" xadvance="31" page="0" chnl="15" />
<char id="359" x="744" y="616,375" width="33" height="53,75" xoffset="-7,125" yoffset="7,875" xadvance="18" page="0" chnl="15" />
<char id="360" x="189,625" y="139,25" width="43,75" height="68,375" xoffset="-4,5" yoffset="-6,625" xadvance="34,75" page="0" chnl="15" />
<char id="361" x="331,25" y="397,375" width="38,625" height="59" xoffset="-4,625" yoffset="2,75" xadvance="29,5" page="0" chnl="15" />
<char id="362" x="0" y="274,625" width="43,75" height="64,625" xoffset="-4,5" yoffset="-2,875" xadvance="34,75" page="0" chnl="15" />
<char id="363" x="699,5" y="506,375" width="38,625" height="55,25" xoffset="-4,625" yoffset="6,5" xadvance="29,5" page="0" chnl="15" />
<char id="364" x="97,375" y="139,375" width="43,75" height="68,75" xoffset="-4,5" yoffset="-7" xadvance="34,75" page="0" chnl="15" />
<char id="365" x="170,5" y="398,875" width="38,625" height="59,125" xoffset="-4,625" yoffset="2,625" xadvance="29,5" page="0" chnl="15" />
<char id="366" x="582,5" y="0" width="43,75" height="69,75" xoffset="-4,5" yoffset="-8" xadvance="34,75" page="0" chnl="15" />
<char id="367" x="669,625" y="271,375" width="38,625" height="61,375" xoffset="-4,625" yoffset="0,375" xadvance="29,5" page="0" chnl="15" />
<char id="368" x="714,125" y="0" width="43,75" height="69,75" xoffset="-4,5" yoffset="-8" xadvance="34,75" page="0" chnl="15" />
<char id="369" x="41,875" y="339,375" width="39,75" height="60,125" xoffset="-4,625" yoffset="1,625" xadvance="29,5" page="0" chnl="15" />
<char id="370" x="617,75" y="206" width="43,75" height="65,25" xoffset="-4,5" yoffset="6,5" xadvance="34,75" page="0" chnl="15" />
<char id="371" x="32,375" y="515,625" width="39,375" height="55,625" xoffset="-4,625" yoffset="16,125" xadvance="29,5" page="0" chnl="15" />
<char id="372" x="0" y="70,375" width="62,5" height="69" xoffset="-7,375" yoffset="-8" xadvance="47,75" page="0" chnl="15" />
<char id="373" x="755,25" y="332,625" width="53,875" height="59,375" xoffset="-7,25" yoffset="1,625" xadvance="39,375" page="0" chnl="15" />
<char id="374" x="159,375" y="70,125" width="47,125" height="69" xoffset="-8,25" yoffset="-8" xadvance="30,5" page="0" chnl="15" />
<char id="375" x="156,375" y="0" width="42,125" height="70" xoffset="-7,875" yoffset="1,625" xadvance="26,375" page="0" chnl="15" />
<char id="376" x="115,125" y="274,125" width="47,125" height="64,375" xoffset="-8,25" yoffset="-3,375" xadvance="30,5" page="0" chnl="15" />
<char id="377" x="571,25" y="69,875" width="43" height="69" xoffset="-6,5" yoffset="-8" xadvance="29,625" page="0" chnl="15" />
<char id="378" x="924" y="331" width="37,125" height="59,375" xoffset="-6,75" yoffset="1,625" xadvance="23,5" page="0" chnl="15" />
<char id="379" x="162,375" y="273,75" width="43" height="64,375" xoffset="-6,5" yoffset="-3,375" xadvance="29,625" page="0" chnl="15" />
<char id="380" x="936,125" y="503,875" width="37,125" height="54,75" xoffset="-6,75" yoffset="6,25" xadvance="23,5" page="0" chnl="15" />
<char id="381" x="614,375" y="69,875" width="43" height="69" xoffset="-6,5" yoffset="-8" xadvance="29,625" page="0" chnl="15" />
<char id="382" x="886,75" y="331,625" width="37,125" height="59,375" xoffset="-6,75" yoffset="1,625" xadvance="23,5" page="0" chnl="15" />
<char id="383" x="0" y="459,125" width="30,75" height="56,5" xoffset="-4,375" yoffset="4,5" xadvance="13,5" page="0" chnl="15" />
</chars>
<kernings count="465">
<kerning first="191" second="74" amount="0,75" />
<kerning first="248" second="121" amount="-0,25" />
<kerning first="39" second="65" amount="-2,375" />
<kerning first="39" second="198" amount="-2,375" />
<kerning first="40" second="84" amount="0,5" />
<kerning first="40" second="106" amount="1,25" />
<kerning first="44" second="41" amount="-2,375" />
<kerning first="44" second="55" amount="-1,25" />
<kerning first="44" second="93" amount="-2,375" />
<kerning first="44" second="125" amount="-2,375" />
<kerning first="248" second="120" amount="-0,5" />
<kerning first="248" second="118" amount="-0,25" />
<kerning first="45" second="65" amount="-1,25" />
<kerning first="45" second="73" amount="-0,75" />
<kerning first="45" second="74" amount="-2,375" />
<kerning first="45" second="83" amount="-0,5" />
<kerning first="45" second="84" amount="-3,75" />
<kerning first="45" second="86" amount="-1,25" />
<kerning first="45" second="87" amount="-1,25" />
<kerning first="45" second="88" amount="-2" />
<kerning first="45" second="89" amount="-3,375" />
<kerning first="45" second="90" amount="-0,75" />
<kerning first="45" second="97" amount="-0,5" />
<kerning first="45" second="118" amount="-1" />
<kerning first="45" second="119" amount="-0,5" />
<kerning first="45" second="120" amount="-1,25" />
<kerning first="45" second="121" amount="-1" />
<kerning first="45" second="122" amount="-1" />
<kerning first="45" second="198" amount="-1,25" />
<kerning first="45" second="230" amount="-0,5" />
<kerning first="46" second="41" amount="-2,625" />
<kerning first="46" second="44" amount="-3,5" />
<kerning first="46" second="45" amount="-4,25" />
<kerning first="46" second="55" amount="-1,25" />
<kerning first="46" second="93" amount="-2,625" />
<kerning first="46" second="125" amount="-2,625" />
<kerning first="248" second="46" amount="-0,5" />
<kerning first="248" second="44" amount="-0,75" />
<kerning first="216" second="90" amount="-0,5" />
<kerning first="216" second="89" amount="-0,5" />
<kerning first="52" second="44" amount="-0,5" />
<kerning first="52" second="46" amount="-0,5" />
<kerning first="55" second="44" amount="-3,875" />
<kerning first="55" second="46" amount="-3,875" />
<kerning first="216" second="88" amount="-0,25" />
<kerning first="65" second="45" amount="-1,25" />
<kerning first="65" second="83" amount="-0,125" />
<kerning first="65" second="84" amount="-3" />
<kerning first="65" second="85" amount="-0,25" />
<kerning first="65" second="86" amount="-1,375" />
<kerning first="65" second="87" amount="-1,25" />
<kerning first="65" second="89" amount="-2" />
<kerning first="65" second="116" amount="-0,375" />
<kerning first="65" second="117" amount="-0,25" />
<kerning first="65" second="118" amount="-0,75" />
<kerning first="65" second="119" amount="-0,25" />
<kerning first="65" second="121" amount="-0,75" />
<kerning first="216" second="84" amount="-1,25" />
<kerning first="216" second="46" amount="-0,75" />
<kerning first="216" second="44" amount="-0,75" />
<kerning first="239" second="108" amount="0,25" />
<kerning first="239" second="102" amount="0,375" />
<kerning first="238" second="108" amount="0,25" />
<kerning first="66" second="44" amount="-0,5" />
<kerning first="66" second="45" amount="0,25" />
<kerning first="66" second="46" amount="-0,5" />
<kerning first="66" second="67" amount="0,25" />
<kerning first="66" second="71" amount="0,25" />
<kerning first="66" second="79" amount="0,25" />
<kerning first="66" second="81" amount="0,25" />
<kerning first="66" second="84" amount="-1,375" />
<kerning first="66" second="97" amount="0,25" />
<kerning first="66" second="101" amount="0,25" />
<kerning first="66" second="104" amount="0,25" />
<kerning first="66" second="105" amount="0,25" />
<kerning first="66" second="106" amount="0,25" />
<kerning first="66" second="108" amount="0,25" />
<kerning first="66" second="111" amount="0,25" />
<kerning first="66" second="114" amount="0,25" />
<kerning first="66" second="117" amount="0,25" />
<kerning first="66" second="119" amount="0,25" />
<kerning first="231" second="45" amount="-0,5" />
<kerning first="199" second="338" amount="-0,625" />
<kerning first="199" second="45" amount="-1,25" />
<kerning first="123" second="106" amount="1,25" />
<kerning first="67" second="45" amount="-1,25" />
<kerning first="67" second="338" amount="-0,625" />
<kerning first="123" second="84" amount="0,5" />
<kerning first="122" second="248" amount="-0,25" />
<kerning first="68" second="44" amount="-1,25" />
<kerning first="68" second="46" amount="-1,25" />
<kerning first="68" second="74" amount="-0,5" />
<kerning first="68" second="84" amount="-1,25" />
<kerning first="68" second="87" amount="-0,5" />
<kerning first="68" second="88" amount="-0,25" />
<kerning first="68" second="89" amount="-0,5" />
<kerning first="68" second="90" amount="-0,5" />
<kerning first="122" second="231" amount="-0,25" />
<kerning first="70" second="44" amount="-7,375" />
<kerning first="70" second="46" amount="-7,375" />
<kerning first="70" second="58" amount="-1,375" />
<kerning first="122" second="113" amount="-0,25" />
<kerning first="70" second="63" amount="1,375" />
<kerning first="70" second="65" amount="-2,375" />
<kerning first="70" second="74" amount="-1,5" />
<kerning first="70" second="84" amount="0,75" />
<kerning first="70" second="97" amount="-2,375" />
<kerning first="70" second="101" amount="-1,25" />
<kerning first="70" second="111" amount="-1,25" />
<kerning first="70" second="198" amount="-2,75" />
<kerning first="70" second="230" amount="-2,375" />
<kerning first="70" second="248" amount="-1,25" />
<kerning first="122" second="111" amount="-0,25" />
<kerning first="70" second="339" amount="-1,25" />
<kerning first="73" second="45" amount="-0,75" />
<kerning first="73" second="97" amount="-0,5" />
<kerning first="73" second="99" amount="-0,625" />
<kerning first="73" second="100" amount="-0,5" />
<kerning first="73" second="101" amount="-0,625" />
<kerning first="73" second="103" amount="-0,5" />
<kerning first="73" second="109" amount="-0,25" />
<kerning first="73" second="110" amount="-0,25" />
<kerning first="73" second="111" amount="-0,625" />
<kerning first="73" second="112" amount="-0,25" />
<kerning first="73" second="114" amount="-0,25" />
<kerning first="73" second="115" amount="-0,5" />
<kerning first="73" second="118" amount="-0,75" />
<kerning first="122" second="103" amount="-0,25" />
<kerning first="122" second="101" amount="-0,25" />
<kerning first="74" second="44" amount="-0,5" />
<kerning first="74" second="46" amount="-0,5" />
<kerning first="74" second="65" amount="-0,25" />
<kerning first="74" second="198" amount="-0,25" />
<kerning first="122" second="100" amount="-0,25" />
<kerning first="75" second="45" amount="-2,75" />
<kerning first="75" second="79" amount="-0,5" />
<kerning first="75" second="97" amount="-1,125" />
<kerning first="75" second="101" amount="-1,5" />
<kerning first="75" second="111" amount="-1,5" />
<kerning first="75" second="117" amount="-1" />
<kerning first="75" second="118" amount="-1,375" />
<kerning first="75" second="119" amount="-1,5" />
<kerning first="75" second="121" amount="-1,375" />
<kerning first="75" second="216" amount="-0,5" />
<kerning first="75" second="230" amount="-1,375" />
<kerning first="75" second="248" amount="-1,75" />
<kerning first="75" second="338" amount="-0,5" />
<kerning first="75" second="339" amount="-1,75" />
<kerning first="122" second="99" amount="-0,25" />
<kerning first="122" second="45" amount="-0,5" />
<kerning first="76" second="39" amount="-3" />
<kerning first="76" second="45" amount="-3,875" />
<kerning first="76" second="65" amount="-1" />
<kerning first="76" second="67" amount="-0,5" />
<kerning first="76" second="71" amount="-0,5" />
<kerning first="76" second="74" amount="2,375" />
<kerning first="76" second="79" amount="-0,5" />
<kerning first="76" second="81" amount="-0,5" />
<kerning first="76" second="84" amount="-4,25" />
<kerning first="76" second="86" amount="-2,75" />
<kerning first="76" second="87" amount="-2,375" />
<kerning first="76" second="89" amount="-3,875" />
<kerning first="76" second="118" amount="-2,75" />
<kerning first="76" second="121" amount="-2,75" />
<kerning first="76" second="199" amount="-0,5" />
<kerning first="76" second="198" amount="-1" />
<kerning first="76" second="216" amount="-0,5" />
<kerning first="76" second="338" amount="-0,5" />
<kerning first="121" second="339" amount="-0,25" />
<kerning first="121" second="248" amount="-0,375" />
<kerning first="121" second="230" amount="-1" />
<kerning first="121" second="231" amount="-0,375" />
<kerning first="79" second="44" amount="-0,75" />
<kerning first="79" second="46" amount="-0,75" />
<kerning first="79" second="74" amount="-0,25" />
<kerning first="79" second="84" amount="-1,25" />
<kerning first="79" second="88" amount="-0,25" />
<kerning first="79" second="89" amount="-0,5" />
<kerning first="79" second="90" amount="-0,5" />
<kerning first="121" second="113" amount="-0,25" />
<kerning first="80" second="44" amount="-7,375" />
<kerning first="80" second="46" amount="-7,375" />
<kerning first="80" second="65" amount="-1,25" />
<kerning first="80" second="74" amount="-1,75" />
<kerning first="80" second="89" amount="0,5" />
<kerning first="80" second="97" amount="-1,25" />
<kerning first="80" second="101" amount="-1,25" />
<kerning first="80" second="111" amount="-1,25" />
<kerning first="80" second="198" amount="-1,75" />
<kerning first="80" second="230" amount="-1,25" />
<kerning first="80" second="248" amount="-1,25" />
<kerning first="121" second="111" amount="-0,375" />
<kerning first="80" second="339" amount="-1,25" />
<kerning first="81" second="44" amount="-0,75" />
<kerning first="81" second="46" amount="-0,75" />
<kerning first="121" second="103" amount="-0,25" />
<kerning first="82" second="45" amount="-2,375" />
<kerning first="82" second="84" amount="-1,375" />
<kerning first="82" second="89" amount="-0,5" />
<kerning first="82" second="97" amount="-0,5" />
<kerning first="82" second="101" amount="-1" />
<kerning first="82" second="111" amount="-1" />
<kerning first="82" second="117" amount="-0,25" />
<kerning first="82" second="121" amount="-1,25" />
<kerning first="82" second="230" amount="-1,25" />
<kerning first="82" second="248" amount="-1,25" />
<kerning first="82" second="339" amount="-1,375" />
<kerning first="121" second="101" amount="-0,375" />
<kerning first="121" second="100" amount="-0,25" />
<kerning first="121" second="99" amount="-0,375" />
<kerning first="121" second="97" amount="-1" />
<kerning first="83" second="44" amount="-0,5" />
<kerning first="83" second="46" amount="-0,5" />
<kerning first="83" second="65" amount="-0,375" />
<kerning first="83" second="83" amount="-0,625" />
<kerning first="83" second="99" amount="0,125" />
<kerning first="83" second="101" amount="0,125" />
<kerning first="83" second="111" amount="0,125" />
<kerning first="83" second="113" amount="0,125" />
<kerning first="83" second="118" amount="-0,75" />
<kerning first="83" second="119" amount="-0,5" />
<kerning first="83" second="121" amount="-0,75" />
<kerning first="83" second="198" amount="-0,5" />
<kerning first="121" second="46" amount="-4,625" />
<kerning first="84" second="41" amount="0,5" />
<kerning first="84" second="44" amount="-7,125" />
<kerning first="84" second="45" amount="-3,75" />
<kerning first="84" second="46" amount="-7,125" />
<kerning first="84" second="58" amount="-4,875" />
<kerning first="121" second="45" amount="-1" />
<kerning first="84" second="63" amount="1,375" />
<kerning first="84" second="65" amount="-3" />
<kerning first="84" second="67" amount="-1" />
<kerning first="84" second="71" amount="-1" />
<kerning first="84" second="74" amount="-1,5" />
<kerning first="84" second="79" amount="-1,25" />
<kerning first="84" second="83" amount="-0,25" />
<kerning first="84" second="84" amount="-2,625" />
<kerning first="84" second="89" amount="-1,75" />
<kerning first="84" second="93" amount="0,5" />
<kerning first="84" second="97" amount="-5,875" />
<kerning first="84" second="99" amount="-5,375" />
<kerning first="84" second="101" amount="-5,375" />
<kerning first="84" second="103" amount="-5,25" />
<kerning first="84" second="111" amount="-5,375" />
<kerning first="84" second="114" amount="-4,875" />
<kerning first="84" second="115" amount="-4,375" />
<kerning first="84" second="117" amount="-4,875" />
<kerning first="84" second="118" amount="-4,875" />
<kerning first="84" second="119" amount="-4,875" />
<kerning first="84" second="121" amount="-4,875" />
<kerning first="84" second="122" amount="-4,25" />
<kerning first="84" second="125" amount="0,5" />
<kerning first="84" second="199" amount="-1" />
<kerning first="84" second="198" amount="-3,125" />
<kerning first="84" second="216" amount="-1,25" />
<kerning first="84" second="230" amount="-5,875" />
<kerning first="84" second="248" amount="-5,375" />
<kerning first="121" second="44" amount="-4,625" />
<kerning first="84" second="338" amount="-1,25" />
<kerning first="84" second="339" amount="-5,375" />
<kerning first="120" second="339" amount="-0,5" />
<kerning first="120" second="248" amount="-0,625" />
<kerning first="85" second="44" amount="-0,5" />
<kerning first="85" second="46" amount="-0,5" />
<kerning first="85" second="65" amount="-0,25" />
<kerning first="85" second="198" amount="-0,5" />
<kerning first="120" second="231" amount="-0,5" />
<kerning first="86" second="44" amount="-7,125" />
<kerning first="86" second="45" amount="-1,25" />
<kerning first="86" second="46" amount="-7,125" />
<kerning first="86" second="58" amount="-2" />
<kerning first="120" second="111" amount="-0,625" />
<kerning first="86" second="65" amount="-1,375" />
<kerning first="86" second="97" amount="-2,375" />
<kerning first="86" second="101" amount="-2,375" />
<kerning first="86" second="111" amount="-2,375" />
<kerning first="86" second="117" amount="-1,375" />
<kerning first="86" second="121" amount="-1,625" />
<kerning first="86" second="198" amount="-1,75" />
<kerning first="86" second="230" amount="-2,375" />
<kerning first="86" second="248" amount="-2,375" />
<kerning first="120" second="103" amount="-0,25" />
<kerning first="86" second="339" amount="-2,375" />
<kerning first="120" second="101" amount="-0,625" />
<kerning first="120" second="100" amount="-0,25" />
<kerning first="87" second="44" amount="-7,125" />
<kerning first="87" second="45" amount="-1,25" />
<kerning first="87" second="46" amount="-5,375" />
<kerning first="87" second="58" amount="-2" />
<kerning first="120" second="99" amount="-0,5" />
<kerning first="87" second="65" amount="-1,25" />
<kerning first="87" second="97" amount="-2" />
<kerning first="87" second="101" amount="-2" />
<kerning first="87" second="111" amount="-2" />
<kerning first="87" second="114" amount="-1" />
<kerning first="87" second="117" amount="-1" />
<kerning first="87" second="121" amount="-1,375" />
<kerning first="87" second="198" amount="-1" />
<kerning first="87" second="230" amount="-2" />
<kerning first="87" second="248" amount="-2" />
<kerning first="120" second="45" amount="-1,25" />
<kerning first="87" second="339" amount="-2" />
<kerning first="119" second="230" amount="-0,5" />
<kerning first="119" second="97" amount="-0,5" />
<kerning first="88" second="45" amount="-2" />
<kerning first="88" second="67" amount="-0,25" />
<kerning first="88" second="71" amount="-0,25" />
<kerning first="88" second="79" amount="-0,25" />
<kerning first="88" second="97" amount="-1" />
<kerning first="88" second="101" amount="-1,125" />
<kerning first="88" second="111" amount="-1,125" />
<kerning first="88" second="117" amount="-0,75" />
<kerning first="88" second="121" amount="-1,75" />
<kerning first="88" second="199" amount="-0,25" />
<kerning first="88" second="216" amount="-0,25" />
<kerning first="88" second="230" amount="-1,25" />
<kerning first="88" second="248" amount="-1,375" />
<kerning first="88" second="338" amount="-0,25" />
<kerning first="88" second="339" amount="-1,375" />
<kerning first="119" second="46" amount="-1,75" />
<kerning first="119" second="45" amount="-0,5" />
<kerning first="89" second="44" amount="-7,125" />
<kerning first="89" second="45" amount="-3,375" />
<kerning first="89" second="46" amount="-7,125" />
<kerning first="89" second="58" amount="-4,875" />
<kerning first="119" second="44" amount="-1,75" />
<kerning first="89" second="65" amount="-2" />
<kerning first="89" second="74" amount="-1,5" />
<kerning first="89" second="79" amount="-0,5" />
<kerning first="89" second="97" amount="-3,375" />
<kerning first="89" second="100" amount="-3" />
<kerning first="89" second="101" amount="-3,125" />
<kerning first="89" second="103" amount="-3,125" />
<kerning first="89" second="109" amount="-2,375" />
<kerning first="89" second="110" amount="-2,375" />
<kerning first="89" second="111" amount="-3,125" />
<kerning first="89" second="112" amount="-2,375" />
<kerning first="89" second="113" amount="-3,125" />
<kerning first="89" second="114" amount="-2,375" />
<kerning first="89" second="115" amount="-2,75" />
<kerning first="89" second="117" amount="-2,75" />
<kerning first="89" second="118" amount="-2,375" />
<kerning first="89" second="198" amount="-2" />
<kerning first="89" second="216" amount="-0,5" />
<kerning first="89" second="230" amount="-3,375" />
<kerning first="89" second="248" amount="-3,125" />
<kerning first="118" second="339" amount="-0,25" />
<kerning first="89" second="338" amount="-0,5" />
<kerning first="89" second="339" amount="-3,125" />
<kerning first="118" second="248" amount="-0,375" />
<kerning first="118" second="230" amount="-1" />
<kerning first="90" second="45" amount="-1,375" />
<kerning first="90" second="67" amount="-0,5" />
<kerning first="90" second="71" amount="-0,5" />
<kerning first="90" second="79" amount="-0,5" />
<kerning first="90" second="90" amount="-0,25" />
<kerning first="90" second="97" amount="-1,25" />
<kerning first="90" second="101" amount="-1,375" />
<kerning first="90" second="111" amount="-1,375" />
<kerning first="90" second="119" amount="-1" />
<kerning first="90" second="121" amount="-1,625" />
<kerning first="90" second="199" amount="-0,5" />
<kerning first="90" second="216" amount="-0,5" />
<kerning first="90" second="230" amount="-1,25" />
<kerning first="90" second="248" amount="-1,375" />
<kerning first="90" second="338" amount="-0,5" />
<kerning first="90" second="339" amount="-1,375" />
<kerning first="118" second="111" amount="-0,375" />
<kerning first="118" second="101" amount="-0,375" />
<kerning first="91" second="84" amount="0,5" />
<kerning first="91" second="106" amount="1,25" />
<kerning first="97" second="118" amount="-0,375" />
<kerning first="97" second="119" amount="-0,25" />
<kerning first="97" second="121" amount="-0,375" />
<kerning first="98" second="44" amount="-0,75" />
<kerning first="98" second="46" amount="-0,5" />
<kerning first="98" second="121" amount="-0,125" />
<kerning first="118" second="97" amount="-1" />
<kerning first="99" second="45" amount="-0,5" />
<kerning first="99" second="84" amount="-2,5" />
<kerning first="99" second="99" amount="-0,125" />
<kerning first="99" second="231" amount="-0,125" />
<kerning first="118" second="46" amount="-4,375" />
<kerning first="118" second="45" amount="-1" />
<kerning first="101" second="84" amount="-3,375" />
<kerning first="102" second="34" amount="2,25" />
<kerning first="102" second="39" amount="2,25" />
<kerning first="102" second="41" amount="2,625" />
<kerning first="102" second="42" amount="1,75" />
<kerning first="102" second="44" amount="-3,875" />
<kerning first="102" second="45" amount="-1,75" />
<kerning first="102" second="46" amount="-3,875" />
<kerning first="102" second="63" amount="3" />
<kerning first="102" second="92" amount="2,375" />
<kerning first="102" second="93" amount="2,625" />
<kerning first="102" second="97" amount="-0,625" />
<kerning first="102" second="99" amount="-0,5" />
<kerning first="102" second="101" amount="-0,5" />
<kerning first="102" second="102" amount="-0,375" />
<kerning first="102" second="103" amount="-0,25" />
<kerning first="102" second="106" amount="-0,5" />
<kerning first="102" second="109" amount="-0,25" />
<kerning first="102" second="110" amount="-0,25" />
<kerning first="102" second="111" amount="-0,5" />
<kerning first="102" second="112" amount="-0,25" />
<kerning first="102" second="113" amount="-0,25" />
<kerning first="102" second="114" amount="-0,25" />
<kerning first="102" second="115" amount="-0,625" />
<kerning first="102" second="117" amount="-0,5" />
<kerning first="102" second="121" amount="-0,625" />
<kerning first="102" second="125" amount="2,625" />
<kerning first="102" second="233" amount="-0,5" />
<kerning first="102" second="238" amount="3,125" />
<kerning first="102" second="230" amount="-0,625" />
<kerning first="102" second="248" amount="-0,5" />
<kerning first="118" second="44" amount="-4,375" />
<kerning first="116" second="121" amount="-0,5" />
<kerning first="116" second="118" amount="-0,5" />
<kerning first="116" second="116" amount="-0,375" />
<kerning first="116" second="45" amount="-1" />
<kerning first="103" second="106" amount="0,25" />
<kerning first="104" second="118" amount="-0,5" />
<kerning first="104" second="119" amount="-0,25" />
<kerning first="104" second="121" amount="-0,5" />
<kerning first="105" second="102" amount="0,125" />
<kerning first="114" second="339" amount="-0,25" />
<kerning first="114" second="248" amount="-0,25" />
<kerning first="105" second="116" amount="0,125" />
<kerning first="107" second="45" amount="-2,375" />
<kerning first="107" second="101" amount="-0,5" />
<kerning first="107" second="111" amount="-0,5" />
<kerning first="107" second="248" amount="-0,5" />
<kerning first="107" second="339" amount="-0,5" />
<kerning first="114" second="230" amount="-1" />
<kerning first="114" second="233" amount="-0,25" />
<kerning first="114" second="231" amount="-0,25" />
<kerning first="114" second="113" amount="-0,25" />
<kerning first="108" second="108" amount="0,125" />
<kerning first="108" second="116" amount="0,125" />
<kerning first="108" second="238" amount="0,25" />
<kerning first="108" second="239" amount="0,25" />
<kerning first="114" second="111" amount="-0,25" />
<kerning first="109" second="118" amount="-0,5" />
<kerning first="109" second="119" amount="-0,25" />
<kerning first="109" second="121" amount="-0,5" />
<kerning first="110" second="118" amount="-0,5" />
<kerning first="110" second="119" amount="-0,25" />
<kerning first="110" second="121" amount="-0,5" />
<kerning first="111" second="44" amount="-0,75" />
<kerning first="111" second="46" amount="-0,5" />
<kerning first="111" second="118" amount="-0,25" />
<kerning first="111" second="120" amount="-0,5" />
<kerning first="111" second="121" amount="-0,25" />
<kerning first="114" second="103" amount="-0,25" />
<kerning first="112" second="44" amount="-0,75" />
<kerning first="112" second="46" amount="-0,5" />
<kerning first="112" second="121" amount="-0,125" />
<kerning first="114" second="101" amount="-0,25" />
<kerning first="114" second="44" amount="-7,125" />
<kerning first="114" second="45" amount="-0,625" />
<kerning first="114" second="46" amount="-7,125" />
<kerning first="114" second="97" amount="-0,875" />
<kerning first="114" second="99" amount="-0,25" />
<kerning first="114" second="100" amount="-0,25" />
</kernings>
</font>

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 KiB

40
rainbow/CoreGl/Gl.h Normal file
View file

@ -0,0 +1,40 @@
#ifndef _CoreGl_Gl_h_
#define _CoreGl_Gl_h_
#ifdef flagLINUXGL
#define Time XTime
#define Font XFont
#define Display XDisplay
#define Picture XPicture
#define Screen XScreen
#define Window XWindow
#define Complex XComplex
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#endif
#include <CoreGl/glew.h>
#ifdef flagWINGL
#include <CoreGl/wglew.h>
#endif
#include <GL/gl.h>
#include <GL/glu.h>
#ifdef flagLINUXGL
#include <GL/glx.h>
#endif
#ifdef flagLINUXGL
#undef Picture
#undef Time
#undef Font
#undef Display
#undef Screen
#undef Window
#undef Complex
#endif
#endif

90
rainbow/CoreGl/Image.cpp Normal file
View file

@ -0,0 +1,90 @@
#if defined(flagWINGL) || defined(flagLINUXGL)
#include <CtrlLib/CtrlLib.h>
NAMESPACE_UPP
#define LTIMING(x) // RTIMING(x)
void SetSurface(SystemDraw& w, int x, int y, int cx, int cy, const RGBA *pixels)
{
GuiLock __;
}
void SetSurface(SystemDraw& w, const Rect& dest, const RGBA *pixels, Size psz, Point poff)
{
GuiLock __;
}
Image ImageDraw::Get(bool pm) const
{
ImageBuffer result(image.GetSize());
const RGBA *e = image.End();
const RGBA *p = ~image;
RGBA *t = ~result;
if(has_alpha) {
const RGBA *a = ~alpha;
while(p < e) {
*t = *p++;
(t++)->a = (a++)->r;
}
if(pm)
Premultiply(result);
result.SetKind(IMAGE_ALPHA);
}
else {
while(p < e) {
*t = *p++;
(t++)->a = 255;
}
}
return result;
}
Draw& ImageDraw::Alpha()
{
has_alpha = true;
return alpha_painter;
}
ImageDraw::ImageDraw(Size sz)
: ImageDraw__(sz.cx, sz.cy),
BufferPainter(image),
alpha_painter(alpha)
{
has_alpha = false;
}
ImageDraw::ImageDraw(int cx, int cy)
: ImageDraw__(cx, cy),
BufferPainter(image),
alpha_painter(alpha)
{
has_alpha = false;
}
#define IMAGECLASS CoreGlImg
#define IMAGEFILE <CoreGl/CoreGl.iml>
#include <Draw/iml_source.h>
Image Image::Arrow() { return CoreGlImg::arrow(); }
Image Image::Wait() { return CoreGlImg::wait(); }
Image Image::IBeam() { return CoreGlImg::ibeam(); }
Image Image::No() { return CoreGlImg::no(); }
Image Image::SizeAll() { return CoreGlImg::sizeall(); }
Image Image::SizeHorz() { return CoreGlImg::sizehorz(); }
Image Image::SizeVert() { return CoreGlImg::sizevert(); }
Image Image::SizeTopLeft() { return CoreGlImg::sizetopleft(); }
Image Image::SizeTop() { return CoreGlImg::sizetop(); }
Image Image::SizeTopRight() { return CoreGlImg::sizetopright(); }
Image Image::SizeLeft() { return CoreGlImg::sizeleft(); }
Image Image::SizeRight() { return CoreGlImg::sizeright(); }
Image Image::SizeBottomLeft() { return CoreGlImg::sizebottomleft(); }
Image Image::SizeBottom() { return CoreGlImg::sizebottom(); }
Image Image::SizeBottomRight() { return CoreGlImg::sizebottomright(); }
Image Image::Hand() { return CoreGlImg::hand(); }
END_UPP_NAMESPACE
#endif

103
rainbow/CoreGl/ResGl.h Normal file
View file

@ -0,0 +1,103 @@
#ifndef _CoreGl_ResGl_h_
#define _CoreGl_ResGl_h_
struct TextureResource : Moveable<TextureResource>
{
int64 serialId;
int64 atlasSerialId;
int realWidth;
int realHeight;
int width;
int height;
int x;
int y;
TextureResource(int w = 0, int h = 0)
{
serialId = -1;
atlasSerialId = -1;
realWidth = w;
realHeight = h;
width = w;
height = h;
x = 0;
y = 0;
}
String ToString() const
{
return Format("x: %d, y: %d, w: %d, h:%d (%d, %d) - %ld", x, y, width, height, realWidth, realHeight, serialId);
}
};
struct AtlasResource : Moveable<AtlasResource>
{
int width;
int height;
bool linear;
Vector<Image> parts;
Image Make(ArrayMap<int64, TextureResource>& textures);
};
struct ImageResource : Moveable<ImageResource>
{
int type;
bool linear;
//direct image
Image img;
//brc image
const byte* data;
int length;
//disk image
String fileName;
};
struct Resources
{
enum {
NEAREST_FILTERING = 1,
LINEAR_FILTERING = 2,
FORCE_FILTERING = 4,
AUTO_ATLAS = 8,
FORCE_BIND = 16
};
Vector<ImageResource> staticImages;
VectorMap<String, AtlasResource> staticAtlases;
Vector<Font> staticFonts;
TextureResource autoAtlas;
ImageBuffer autoAtlasBuffer;
Image autoAtlasImage;
int px, py, maxh;
int bindedTextures;
int64 currentSerialId;
ArrayMap<int64, TextureResource> textures;
ArrayMap<String, OpenGLFont> fonts;
const TextureResource& CreateTexture(const Image& img, int width = -1, int height = -1);
void CreateSubTexture(const TextureResource& t, const Image& img, int x, int y);
const TextureResource& Bind(const Image& img, int opts = NEAREST_FILTERING);
bool Bind(int64 serialId, int opts = NEAREST_FILTERING);
void Add(const Image& img, bool linear = false);
void Add(Iml* images, bool linear = false);
void Add(const Font& fnt);
void AddAtlas(const char* atlasName, const Image& img);
void AddAtlas(const char* atlasName, Iml* images);
OpenGLFont& GetFont(const char* fontName, int fontHeight, bool preload = false, const byte* fontDef = NULL, const byte** imagesData = NULL, const int* imagesSize = NULL, int imagesCount = 0);
OpenGLFont& GetFont(const Font& font, bool preload = false);
void SetTextureFiltring(int opts);
void BindStatic();
Resources();
};
extern Resources resources;
#endif

View file

@ -0,0 +1,8 @@
BINARY(alphaMagFrag, "AlphaMag.frag")
BINARY(alphaMagVert, "AlphaMag.vert")
BINARY(blurVert, "Blur.vert")
BINARY(blurFrag, "Blur.frag")
BINARY(tahomaNFontDef, "Fonts/TahomaN.fnt")
BINARY_ARRAY(tahomaNFontImg, 0, "Fonts/TahomaN_0.png")
BINARY(tahomaBFontDef, "Fonts/TahomaB.fnt")
BINARY_ARRAY(tahomaBFontImg, 0, "Fonts/TahomaB_0.png")

View file

@ -0,0 +1,362 @@
#if defined(flagWINGL) || defined(flagLINUXGL)
#include "CoreGl.h"
#include <plugin/png/png.h>
NAMESPACE_UPP
Resources resources;
Resources::Resources() : autoAtlas(1024, 1024)
{
px = 0;
py = 0;
maxh = 0;
currentSerialId = -1;
bindedTextures = 0;
}
void Resources::SetTextureFiltring(int opts)
{
if(opts & LINEAR_FILTERING)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
else if(opts & NEAREST_FILTERING)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
}
const TextureResource& Resources::CreateTexture(const Image& img, int width, int height)
{
int64 serialId = img.GetSerialId();
TextureResource& t = textures.Add(serialId);
t.serialId = serialId;
t.atlasSerialId = -1;
t.width = width > 0 ? width : img.GetWidth();
t.height = height > 0 ? height : img.GetHeight();
t.realWidth = t.width;
t.realHeight = t.height;
t.x = 0;
t.y = 0;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, t.width, t.height, 0, GL_BGRA, GL_UNSIGNED_BYTE, img);
++bindedTextures;
return t;
}
void Resources::CreateSubTexture(const TextureResource& t, const Image& img, int x, int y)
{
Bind(autoAtlas.serialId, 0);
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, img.GetWidth(), img.GetHeight(), GL_BGRA, GL_UNSIGNED_BYTE, img);
}
const TextureResource& Resources::Bind(const Image& img, int opts)
{
int64 serialId = img.GetSerialId();
const TextureResource* texture = textures.FindPtr(serialId);
if(texture)
{
if(texture->atlasSerialId >= 0)
serialId = texture->atlasSerialId;
}
else if(opts & AUTO_ATLAS)
{
int w = img.GetWidth();
int h = img.GetHeight();
if(w <= autoAtlas.width && h <= autoAtlas.height && w <= 64 && h <= 64)
{
bool add = px + w <= autoAtlas.width && py + h <= autoAtlas.height;
if(!add)
{
if(py + maxh + h > autoAtlas.height)
{
add = false;
}
else
{
px = 0;
py += maxh;
maxh = 0;
add = true;
}
}
if(add)
{
if(h > maxh)
maxh = h;
TextureResource& t = textures.Add(img.GetSerialId());
t.atlasSerialId = autoAtlas.serialId;
t.width = w;
t.height = h;
t.realWidth = autoAtlas.width;
t.realHeight = autoAtlas.height;
t.x = px;
t.y = py;
CreateSubTexture(autoAtlas, img, px, py);
Copy(autoAtlasImage, Point(px, py), img, img.GetSize());
px += w;
texture = &t;
serialId = autoAtlas.serialId;
}
}
}
if(!Bind(serialId, opts))
return *texture;
if(!texture)
{
texture = &CreateTexture(img);
}
return *texture;
}
bool Resources::Bind(int64 serialId, int opts)
{
if(!(opts & FORCE_BIND) && serialId == currentSerialId)
{
if(opts & FORCE_FILTERING)
SetTextureFiltring(opts);
return false;
}
currentSerialId = serialId;
glBindTexture(GL_TEXTURE_2D, (GLuint) serialId);
SetTextureFiltring(opts);
return true;
}
void Resources::BindStatic()
{
if(autoAtlas.serialId < 0)
{
autoAtlasBuffer.Create(autoAtlas.width, autoAtlas.height);
Fill(autoAtlasBuffer, RGBAZero(), autoAtlasBuffer.GetLength());
autoAtlasImage = autoAtlasBuffer;
Bind(autoAtlasImage.GetSerialId());
autoAtlas = CreateTexture(autoAtlasImage);
}
if(!staticImages.IsEmpty())
{
for(int i = 0; i < staticImages.GetCount(); i++)
Bind(staticImages[i].img, staticImages[i].linear ? Resources::LINEAR_FILTERING : Resources::NEAREST_FILTERING);
staticImages.Clear();
}
if(!staticAtlases.IsEmpty())
{
for(int i = 0; i < staticAtlases.GetCount(); i++)
Bind(staticAtlases[i].Make(textures), staticAtlases[i].linear ? Resources::LINEAR_FILTERING : Resources::NEAREST_FILTERING);
staticAtlases.Clear();
}
if(!staticFonts.IsEmpty())
{
for(int i = 0; i < staticFonts.GetCount(); i++)
GetFont(staticFonts[i], true);
staticFonts.Clear();
}
}
void Resources::Add(const Image& img, bool linear)
{
ImageResource& ir = staticImages.Add();
ir.img = img;
ir.linear = linear;
}
void Resources::Add(const Font& fnt)
{
Font& f = staticFonts.Add(fnt);
}
void Resources::Add(Iml* images, bool linear)
{
for(int i = 0; i < images->GetCount(); i++)
Add(images->Get(i), linear);
}
void Resources::AddAtlas(const char* atlasName, const Image& img)
{
AtlasResource& atlas = staticAtlases.GetAdd(atlasName);
atlas.linear = false;
atlas.parts.Add(img);
}
void Resources::AddAtlas(const char* atlasName, Iml* images)
{
AtlasResource& atlas = staticAtlases.GetAdd(atlasName);
atlas.linear = false;
for(int i = 0; i < images->GetCount(); i++)
atlas.parts.Add(images->Get(i));
}
Image AtlasResource::Make(ArrayMap<int64, TextureResource>& textures)
{
width = 512;
height = 512;
ImageBuffer ib(width, height);
Fill(ib, RGBAZero(), ib.GetLength());
Point p(0, 0);
int maxh = 0;
int tidx = textures.GetCount();
for(int i = 0; i < parts.GetCount(); i++)
{
Image& img = parts[i];
int w = img.GetWidth();
int h = img.GetHeight();
if(w > width || h > height)
continue;
if(p.x + w > width)
{
if(p.y + maxh + h > height)
continue;
p.x = 0;
p.y += maxh;
maxh = 0;
}
if(h > maxh)
maxh = h;
TextureResource& t = textures.Add(img.GetSerialId());
t.width = w;
t.height = h;
t.realWidth = width;
t.realHeight = height;
t.x = p.x;
t.y = p.y;
Copy(ib, p, img, img.GetSize());
p.x += w;
}
Image finalImg(ib);
int64 finalSerialId = finalImg.GetSerialId();
for(int i = tidx; i < textures.GetCount(); i++)
textures[i].atlasSerialId = finalSerialId;
return finalImg;
}
OpenGLFont& Resources::GetFont(const char* fontName, int fontHeight, bool preload, const byte* fontDef, const byte** imagesData, const int* imagesSize, int imagesCount)
{
int n = fonts.Find(fontName);
OpenGLFont* fgl = NULL;
if(n >= 0)
fgl = &fonts[n];
else
{
fgl = &fonts.Add(fontName);
fgl->preload = preload;
if(fontDef)
fgl->LoadBrc(fontDef, imagesData, imagesSize, imagesCount);
else
fgl->Load(fontName);
}
fgl->scale = (fontHeight * 96.f / 72.f) / 72.f;
return *fgl;
}
OpenGLFont& Resources::GetFont(const Font& font, bool preload)
{
if(font.IsBold())
return GetFont("TahomaB", font.GetHeight(), preload,
tahomaBFontDef, (const byte**) tahomaBFontImg, tahomaBFontImg_length, tahomaBFontImg_count);
else
return GetFont("TahomaN", font.GetHeight(), preload,
tahomaNFontDef, (const byte**) tahomaNFontImg, tahomaNFontImg_length, tahomaNFontImg_count);
}
int64 GetHighTickCount()
{
#ifdef PLATFORM_WIN32
static int64 counterFreq = 0;
if(counterFreq == 0)
{
if(!QueryPerformanceFrequency((LARGE_INTEGER*) &counterFreq))
counterFreq = 0;
}
if(counterFreq > 0)
{
int64 counter;
QueryPerformanceCounter((LARGE_INTEGER*) &counter);
return counter * 1000 / counterFreq;
}
else
{
return GetTickCount();
}
#else
return GetTickCount();
#endif
}
float GetFps()
{
static float fps = 0.0f;
static int64 updateInterval = 1000;
static int64 timeSinceLastUpdate = 0;
static int64 frameCount = 0;
static int64 currentTick;
static int64 lastTick;
static bool isFirst = true;
if(isFirst)
{
currentTick = frameInfo.curr_tick_count;
lastTick = currentTick;
isFirst = false;
}
frameCount++;
currentTick = frameInfo.curr_tick_count;
int64 elapsed = currentTick - lastTick;
lastTick = currentTick;
timeSinceLastUpdate += elapsed;
if (timeSinceLastUpdate > updateInterval)
{
if (timeSinceLastUpdate)
{
fps = (frameCount / float(timeSinceLastUpdate)) * 1000.f;
frameCount = 0;
timeSinceLastUpdate -= updateInterval;
}
}
return fps;
}
END_UPP_NAMESPACE
#endif

View file

@ -0,0 +1,10 @@
#if defined(flagWINGL) || defined(flagLINUXGL)
#include "SceneGraph.h"
/*
GraphNode::GraphNode() : next(NULL), prev(NULL)
{
}
*/
#endif

View file

@ -0,0 +1,24 @@
#ifndef _WinGl_SceneGraph_h_
#define _WinGl_SceneGraph_h_
/*
struct GraphNode : Moveable<GraphNode>
{
RGBA color;
double x, y, z;
GraphNode* prev;
GraphNode* next;
GraphNode();
};
class SceneGraph
{
private:
GraphNode* root;
public:
};
*/
#endif

View file

@ -0,0 +1,332 @@
#if defined(flagWINGL) || defined(flagLINUXGL)
#include "Scrollbar.h"
NAMESPACE_UPP
void AlignedFrame::FrameLayout(Rect &r)
{
switch(layout)
{
case LEFT:
LayoutFrameLeft(r, this, framesize);
break;
case TOP:
LayoutFrameTop(r, this, framesize);
break;
case RIGHT:
LayoutFrameRight(r, this, framesize);
break;
case BOTTOM:
LayoutFrameBottom(r, this, framesize);
break;
}
r.top += border;
r.left += border;
r.right -= border;
r.bottom -= border;
}
void AlignedFrame::FrameAddSize(Size& sz)
{
sz += border * 2;
IsVert() ? sz.cx += framesize : sz.cy += framesize;
}
void AlignedFrame::FramePaint(Draw& w, const Rect& r)
{
if(border > 0)
{
Rect n = r;
switch(layout)
{
case LEFT:
n.left += framesize;
break;
case TOP:
n.top += framesize;
break;
case RIGHT:
n.right -= framesize;
break;
case BOTTOM:
n.bottom -= framesize;
break;
}
ViewFrame().FramePaint(w, n);
}
else
FrameCtrl<Ctrl>::FramePaint(w, r);
}
AlignedFrame& AlignedFrame::SetFrameSize(int sz, bool refresh)
{
framesize = sz;
if (refresh) RefreshParentLayout();
return *this;
}
void AlignedFrame::Fix(Size& sz)
{
if(IsVert())
Swap(sz.cx, sz.cy);
}
void AlignedFrame::Fix(Point& p)
{
if(IsVert())
Swap(p.x, p.y);
}
Size AlignedFrame::Fixed(const Size& sz)
{
return IsVert() ? Size(sz.cy, sz.cx) : Size(sz.cx, sz.cy);
}
Point AlignedFrame::Fixed(const Point& p)
{
return IsVert() ? Point(p.y, p.x) : Point(p.x, p.y);
}
// SlimScrollBar
SlimScrollBar::SlimScrollBar()
{
Clear();
}
void SlimScrollBar::Clear()
{
total = 0;
t = 0;
pos = 0;
prev_ps = 0;
ps = 0;
start_pos = 0;
new_pos = 0;
old_pos = 0;
isend = true;
isbegin = true;
sz.Clear();
ready = false;
}
void SlimScrollBar::UpdatePos(bool update, bool whenscroll)
{
sz = GetSize();
Fix(sz);
if(total <= 0 || sz.cx <= 0)
{
cs = ics = 0;
}
else
{
cs = sz.cx / double(t + 0.5);
ics = t / double(sz.cx);
}
size = max(0.0, sz.cx * cs);
if(update)
pos = new_pos - start_pos;
isbegin = t < sz.cx;
isend = t < sz.cx;
if(pos <= 0)
{
pos = 0;
isbegin = true;
}
else if(pos + size >= sz.cx)
{
pos = sz.cx - size;
isend = true;
}
ps = t > sz.cx ? pos * ics : 0;
if(whenscroll && int(ps) != int(prev_ps))
WhenScroll();
prev_ps = ps;
}
void SlimScrollBar::Paint(Draw &w)
{
if(!ready)
{
UpdatePos();
ready = true;
}
Ctrl* q = GetParent();
if(!q)
return;
Size sz = GetSize();
Size psz = q->GetSize();
if(IsHorz() && total > psz.cx || IsVert() && total > psz.cy) {
Point p(int(pos), 0);
Size rsz(int(size), IsVert() ? sz.cx : sz.cy);
Fix(p);
Fix(rsz);
#ifdef COLOR_ALPHA
w.DrawRect(p.x, p.y, rsz.cx, rsz.cy, White().Alpha(150));
#else
SystemDraw& sw = (SystemDraw&) w;
sw.alpha = 150.f;
w.DrawRect(p.x, p.y, rsz.cx, rsz.cy, White);
sw.alpha = 255.f;
#endif
}
}
void SlimScrollBar::Layout()
{
Size csz = GetSize();
Fix(csz);
if(ready && csz != sz)
{
sz = csz;
UpdatePos(false);
}
}
void SlimScrollBar::LeftDown(Point p, dword keyflags)
{
SetCapture();
Fix(p);
old_pos = new_pos = p.x;
if(p.x < pos || p.x > pos + size)
start_pos = size / 2;
else
start_pos = tabs(p.x - pos);
UpdatePos();
UpdateActionRefresh();
}
void SlimScrollBar::LeftUp(Point p, dword keyflags)
{
ReleaseCapture();
Fix(p);
old_pos = p.x;
}
void SlimScrollBar::MouseMove(Point p, dword keyflags)
{
if(!HasCapture())
return;
Fix(p);
new_pos = p.x;
UpdatePos();
UpdateActionRefresh();
}
void SlimScrollBar::MouseWheel(Point p, int zdelta, dword keyflags)
{
AddPos(-zdelta / 4, true);
UpdateActionRefresh();
}
int SlimScrollBar::GetPos() const
{
return int(ps);
}
void SlimScrollBar::SetPos(int p, bool dontscale, bool whenscroll)
{
pos = total > 0 ? dontscale ? p : iscale(p, sz.cx, t) : 0;
UpdatePos(false, whenscroll);
Refresh();
}
void SlimScrollBar::AddPos(int p, bool dontscale, bool whenscroll)
{
pos += total > 0 ? dontscale ? p : iscale(p, sz.cx, t) : 0;
UpdatePos(false, whenscroll);
Refresh();
}
int SlimScrollBar::GetTotal() const
{
return total;
}
void SlimScrollBar::SetTotal(int total, bool whenscroll)
{
Ctrl* q = GetParent();
Size sz = GetSize();
Size psz = q ? q->GetSize() : Size(0, 0);
Fix(sz);
Fix(psz);
this->total = total;
this->t = total;
if(q)
this->t -= psz.cx - sz.cx;
UpdatePos(false, whenscroll);
Refresh();
}
void SlimScrollBar::AddTotal(int t)
{
sz = GetSize();
Fix(sz);
total += t;
if(total <= 0 || sz.cx <= 0)
cs = ics = 0;
else
cs = sz.cx / ((double) t + 0.5);
size = int(sz.cx * cs);
ps = min(ps, (double)(t - sz.cx));
pos = (int)(ps * cs);
old_pos = new_pos = (int)(pos - start_pos);
Refresh();
}
void SlimScrollBar::GoEnd(bool whenscroll)
{
pos = total;
UpdatePos(false, whenscroll);
Refresh();
}
void SlimScrollBar::GoBegin(bool whenscroll)
{
pos = 0;
UpdatePos(false, whenscroll);
Refresh();
}
bool SlimScrollBar::IsEnd()
{
return isend;
}
bool SlimScrollBar::IsBegin()
{
return isbegin;
}
void SlimScrollBar::Set(const SlimScrollBar& t)
{
total = t.total;
pos = t.pos;
ps = t.ps;
Refresh();
}
bool SlimScrollBar::IsScrollable() const
{
return t > sz.cx && sz.cx > 0;
}
END_UPP_NAMESPACE
#endif

100
rainbow/CoreGl/Scrollbar.h Normal file
View file

@ -0,0 +1,100 @@
#ifndef _CoreGl_Scrollbar_h_
#define _CoreGl_Scrollbar_h_
#include <CtrlLib/CtrlLib.h>
NAMESPACE_UPP
struct AlignedFrame : FrameCtrl<Ctrl>
{
int layout;
int framesize;
int border;
public:
enum
{
LEFT = 0,
TOP = 1,
RIGHT = 2,
BOTTOM = 3
};
AlignedFrame() : layout(TOP), framesize(0), border(0) {}
virtual void FrameAddSize(Size& sz);
virtual void FramePaint(Draw& w, const Rect& r);
virtual void FrameLayout(Rect& r);
bool IsVert() const { return (layout & 1) == 0; }
bool IsHorz() const { return layout & 1; }
bool IsTL() const { return layout < 2; }
bool IsBR() const { return layout >= 2; }
AlignedFrame& SetAlign(int align) { layout = align; FrameSet(); RefreshParentLayout(); return *this; }
AlignedFrame& SetLeft() { return SetAlign(LEFT); }
AlignedFrame& SetTop() { return SetAlign(TOP); }
AlignedFrame& SetRight() { return SetAlign(RIGHT); }
AlignedFrame& SetBottom() { return SetAlign(BOTTOM); }
AlignedFrame& SetFrameSize(int sz, bool refresh = true);
int GetAlign() const { return layout; }
int GetFrameSize() const { return framesize; }
int GetBorder() const { return border; }
protected:
void Fix(Size& sz);
void Fix(Point& p);
Size Fixed(const Size& sz);
Point Fixed(const Point& p);
bool HasBorder() { return border >= 0; }
AlignedFrame& SetBorder(int _border) { border = _border; return *this; }
virtual void FrameSet() { }
};
class SlimScrollBar : public AlignedFrame
{
private:
int total;
int t;
bool isend;
bool isbegin;
double pos, prev_ps, ps;
int new_pos;
int old_pos;
double start_pos;
double size;
double cs, ics;
virtual void UpdatePos(bool update = true, bool whenscroll = true);
void RefreshScroll();
bool ready;
Size sz;
public:
SlimScrollBar();
virtual void Paint(Draw& w);
virtual void LeftDown(Point p, dword keyflags);
virtual void LeftUp(Point p, dword keyflags);
virtual void MouseMove(Point p, dword keyflags);
virtual void MouseWheel(Point p, int zdelta, dword keyflags);
virtual void Layout();
int GetPos() const;
void SetPos(int p, bool dontscale = false, bool whenscroll = true);
void AddPos(int p, bool dontscale = false, bool whenscroll = true);
int GetTotal() const;
void AddTotal(int t);
void SetTotal(int t, bool whenscroll = true);
void GoEnd(bool whenscroll = true);
void GoBegin(bool whenscroll = true);
bool IsEnd();
bool IsBegin();
void Clear();
void Set(const SlimScrollBar& t);
bool IsScrollable() const;
Callback WhenScroll;
};
END_UPP_NAMESPACE
#endif

387
rainbow/CoreGl/Shaders.cpp Normal file
View file

@ -0,0 +1,387 @@
#if defined(flagWINGL) || defined(flagLINUXGL)
#include "Shaders.h"
NAMESPACE_UPP
void Shader::PrintShaderInfoLog(GLuint obj, const char* fileName)
{
int infoLength = 0;
int charsWritten = 0;
glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &infoLength);
if(infoLength > 0)
{
char* info = new char[infoLength];
glGetShaderInfoLog(obj, infoLength, &charsWritten, info);
if(charsWritten > 0)
{
compileError = info;
FileOut f(fileName);
f.Put(info);
}
delete[] info;
}
}
void Shader::PrintProgramInfoLog(GLuint obj, const char* fileName)
{
int infoLength = 0;
int charsWritten = 0;
glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &infoLength);
if(infoLength > 0)
{
char* info = new char[infoLength];
glGetShaderInfoLog(obj, infoLength, &charsWritten, info);
if(charsWritten > 0)
{
FileOut f(fileName);
f.Put(info);
}
delete[] info;
}
}
void Shader::PrintProgramValidationLog(GLuint obj, const char* fileName)
{
char log[1024];
int len = 0;
glValidateProgram(obj);
glGetProgramInfoLog(obj, 1024, &len, log);
if(len > 0)
{
FileOut f(fileName);
f.Put(log);
}
}
bool Shader::CheckGLError()
{
unsigned int lastError = glGetError();
if(GL_NO_ERROR != lastError)
{
error = (const char*) gluErrorString(lastError);
return false;
}
return true;
}
bool Shader::IsProgramCompiled(int program)
{
GLint result = GL_FALSE;
glGetShaderiv(program, GL_COMPILE_STATUS, &result);
return result == GL_TRUE;
}
bool Shader::IsProgramLinked(int program)
{
GLint result = GL_FALSE;
glGetProgramiv(program, GL_LINK_STATUS, &result);
return result == GL_TRUE;
}
int Shader::CompileProgram(const char* vs, const char* fs, const char* gs)
{
vertSrc = vs;
fragSrc = fs;
geomSrc = gs;
const GLchar* vertexShaderSrc = (const GLchar*) vertSrc;
const GLchar* fragmentShaderSrc = (const GLchar*) fragSrc;
const GLchar* geometryShaderSrc = (const GLchar*) geomSrc;
DeleteFile("shader_vertex.log");
DeleteFile("shader_fragment.log");
DeleteFile("shader_geometry.log");
DeleteFile("shader_link.log");
DeleteFile("shader_validation.log");
GLenum vertexShader = 0;
GLenum fragmentShader = 0;
GLenum geometryShader = 0;
if(!vertSrc.IsEmpty())
{
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSrc, NULL);
glCompileShader(vertexShader);
if(!IsProgramCompiled(vertexShader))
{
PrintShaderInfoLog(vertexShader, "shader_vertex.log");
error = "Vertex shader compilation error:\n\n" + compileError;
glDeleteShader(vertexShader);
return -1;
}
}
if(!fragSrc.IsEmpty())
{
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSrc, NULL);
glCompileShader(fragmentShader);
if(!IsProgramCompiled(fragmentShader))
{
PrintShaderInfoLog(fragmentShader, "shader_fragment.log");
error = "Fragment shader compilation error:\n\n" + compileError;
glDeleteShader(fragmentShader);
return -1;
}
}
if(!geomSrc.IsEmpty())
{
geometryShader = glCreateShader(GL_GEOMETRY_SHADER);
glShaderSource(geometryShader, 1, &geometryShaderSrc, NULL);
glCompileShader(geometryShader);
if(!IsProgramCompiled(geometryShader))
{
PrintShaderInfoLog(geometryShader, "shader_geometry.log");
error = "Geometry shader compilation error:\n\n" + compileError;
glDeleteShader(geometryShader);
return -1;
}
}
program = glCreateProgram();
if(program > 0)
{
if(vertexShader > 0)
glAttachShader(program, vertexShader);
if(fragmentShader > 0)
glAttachShader(program, fragmentShader);
if(geometryShader > 0)
glAttachShader(program, geometryShader);
glLinkProgram(program);
if(!IsProgramLinked(program))
{
PrintProgramInfoLog(program, "shader_link.log");
PrintProgramValidationLog(program, "shader_validation.log");
glDeleteProgram(program);
program = -1;
}
}
else
program = -1;
return program;
}
int Shader::CompileProgram(const byte* vs, const byte* fs, const byte* gs)
{
return CompileProgram((const char*) vs, (const char*) fs, (const char*) gs);
}
int Shader::GetProgram()
{
return program;
}
String Shader::GetError()
{
return error;
}
int Shader::GetUniformId(const char* var)
{
int n = uniforms.Find(var);
if(n < 0)
{
int id = glGetUniformLocation(program, var);
CheckGLError();
if(id >= 0)
uniforms.Add(var, id);
return id;
}
else
return uniforms[n];
}
int Shader::GetAttributeId(const char* var)
{
int n = attributes.Find(var);
if(n < 0)
{
int id = glGetAttribLocation(program, var);
CheckGLError();
if(id >= 0)
attributes.Add(var, id);
return id;
}
else
return attributes[n];
}
void Shader::SetUniform(const char* var, float v)
{
int id = GetUniformId(var);
if(id >= 0)
glUniform1f(id, v);
}
void Shader::SetUniform(const char* var, bool v)
{
int id = GetUniformId(var);
if(id >= 0)
glUniform1i(id, int(v));
}
void Shader::SetUniform(const char* var, int v)
{
int id = GetUniformId(var);
if(id >= 0)
glUniform1i(id, v);
}
void Shader::SetUniform(const char* var, float v0, float v1)
{
int id = GetUniformId(var);
if(id >= 0)
glUniform2f(id, v0, v1);
}
void Shader::SetUniform(const char* var, float v0, float v1, float v2)
{
int id = GetUniformId(var);
if(id >= 0)
glUniform3f(id, v0, v1, v2);
}
void Shader::SetUniform(const char* var, float v0, float v1, float v2, float v3)
{
int id = GetUniformId(var);
if(id >= 0)
glUniform4f(id, v0, v1, v2, v3);
}
void Shader::SetUniform(const char* var, float* v, int size, int count)
{
int id = GetUniformId(var);
if(id >= 0)
{
if(size == 2)
glUniform2fv(id, count, v);
else if(size == 3)
glUniform3fv(id, count, v);
else if(size == 4)
glUniform4fv(id, count, v);
else if(size == 16)
glUniformMatrix4fv(id, count, GL_FALSE, v);
}
}
void Shader::SetMatrixUniform(const char* var, float* v, int size, int count)
{
int id = GetUniformId(var);
if(id >= 0)
{
if(size == 2)
glUniform2fv(id, count, v);
else if(size == 3)
glUniform3fv(id, count, v);
else if(size == 4)
glUniform4fv(id, count, v);
else if(size == 16)
glUniformMatrix4fv(id, count, GL_FALSE, v);
}
}
void Shader::EnableAttribute(const char* var, bool b)
{
int id = GetAttributeId(var);
if(id >= 0)
{
if(b)
glEnableVertexAttribArray(id);
else
glDisableVertexAttribArray(id);
}
}
void Shader::DisableAttribute(const char* var)
{
EnableAttribute(var, false);
}
void Shader::DisableAllAtrributes()
{
for(int i = 0; i < attributes.GetCount(); i++)
{
int id = attributes[i];
if(id >= 0)
glDisableVertexAttribArray(id);
}
}
void Shader::SetAttribute(const char* var, float v)
{
int id = GetAttributeId(var);
if(id >= 0)
glVertexAttrib1f(id, v);
}
void Shader::SetAttribute(const char* var, float v0, float v1)
{
int id = GetAttributeId(var);
if(id >= 0)
glVertexAttrib2f(id, v0, v1);
}
void Shader::SetAttribute(const char* var, float v0, float v1, float v2)
{
int id = GetAttributeId(var);
if(id >= 0)
glVertexAttrib3f(id, v0, v1, v2);
}
void Shader::SetAttribute(const char* var, float v0, float v1, float v2, float v3)
{
int id = GetAttributeId(var);
if(id >= 0)
glVertexAttrib4f(id, v0, v1, v2, v3);
}
void Shader::SetAttribute(const char* var, float* v, int size)
{
int id = GetAttributeId(var);
if(id >= 0)
{
if(size == 2)
glVertexAttrib2fv(id, v);
else if(size == 3)
glVertexAttrib3fv(id, v);
else if(size == 4)
glVertexAttrib4fv(id, v);
}
}
void Shader::Start()
{
glUseProgram(program);
CheckGLError();
}
void Shader::Stop()
{
glUseProgram(0);
}
void Shader::Release()
{
if(program >= 0)
glDeleteProgram(program);
}
Shader::Shader() : program(-1)
{}
END_UPP_NAMESPACE
#endif

65
rainbow/CoreGl/Shaders.h Normal file
View file

@ -0,0 +1,65 @@
#ifndef _CoreGl_Shaders_h_
#define _CoreGl_Shaders_h_
#include <Core/Core.h>
#include <Draw/Draw.h>
#include "Gl.h"
NAMESPACE_UPP
class Shader
{
private:
int program;
String error;
String compileError;
String fragSrc;
String vertSrc;
String geomSrc;
VectorMap<String, int> uniforms;
VectorMap<String, int> attributes;
void PrintShaderInfoLog(GLuint obj, const char* fileName);
void PrintProgramInfoLog(GLuint obj, const char* fileName);
void PrintProgramValidationLog(GLuint obj, const char* fileName);
bool CheckGLError();
bool IsProgramCompiled(int program);
bool IsProgramLinked(int program);
public:
int GetUniformId(const char* var);
int GetAttributeId(const char* var);
int CompileProgram(const char* vs, const char* fs, const char* gs = NULL);
int CompileProgram(const byte* vs, const byte* fs, const byte* gs = NULL);
int GetProgram();
void SetUniform(const char* var, float v);
void SetUniform(const char* var, bool v);
void SetUniform(const char* var, int v);
void SetUniform(const char* var, float v0, float v1);
void SetUniform(const char* var, float v0, float v1, float v2);
void SetUniform(const char* var, float v0, float v1, float v2, float v3);
void SetUniform(const char* var, float* v, int size, int count = 1);
void SetMatrixUniform(const char* var, float* v, int size, int count = 1);
void EnableAttribute(const char* var, bool b = true);
void DisableAttribute(const char* var);
void DisableAllAtrributes();
void SetAttribute(const char* var, float v);
void SetAttribute(const char* var, float v0, float v1);
void SetAttribute(const char* var, float v0, float v1, float v2);
void SetAttribute(const char* var, float v0, float v1, float v2, float v3);
void SetAttribute(const char* var, float* v, int size);
void Start();
void Stop();
String GetError();
void Release();
Shader();
};
END_UPP_NAMESPACE
#endif

149
rainbow/CoreGl/Top.cpp Normal file
View file

@ -0,0 +1,149 @@
#if defined(flagWINGL) || defined(flagLINUXGL)
#include "TopFrame.h"
NAMESPACE_UPP
#define LLOG(x) // LOG(x)
void TopWindow::SyncFrameRect(const Rect& r)
{
frame->SetClient(r);
}
void TopWindow::DestroyFrame()
{
if(frame->IsOpen())
frame->DestroyWnd();
}
void TopWindow::GripResize()
{
frame->GripResize();
}
void TopWindow::SyncSizeHints()
{
SyncCaption();
}
void TopWindow::SyncTitle()
{
SyncCaption();
}
void TopWindow::SyncCaption()
{
GuiLock __;
frame->title = title.ToString();
frame->minsize = minsize;
frame->close.Show(!noclosebox);
frame->maximize.Show(maximizebox);
frame->sizeable = sizeable;
frame->RefreshLayout();
frame->Refresh();
frame->close <<= Proxy(WhenClose);
frame->icon = icon;
frame->Enable(IsEnabled());
}
void TopWindow::State(int reason)
{
SyncCaption();
}
void TopWindow::SyncRect()
{
frame->SyncRect();
Rect r = frame->GetClient();
if(r != GetRect()) {
SetRect(r);
}
}
void TopWindow::Open(Ctrl *owner)
{
GuiLock __;
Rect r = GetRect();
if(r.IsEmpty())
SetRect(GetDefaultWindowRect());
else
if(r.left == 0 && r.top == 0)
if(owner && center == 1)
SetRect(owner->GetRect().CenterRect(r.GetSize()));
else
if(center)
SetRect(GetWorkArea().CenterRect(r.GetSize()));
frame->SetClient(GetRect());
frame->window = this;
frame->PopUp(owner, false, true);
PopUp(frame, false, true);
popup = false;
SetRect(frame->GetClient());
SyncCaption();
if(state == MAXIMIZED)
frame->Maximize();
}
void TopWindow::Open()
{
Open(GetActiveCtrl());
}
void TopWindow::OpenMain()
{
Open(NULL);
}
void TopWindow::Minimize(bool effect)
{
// state = MINIMIZED;
}
TopWindow& TopWindow::FullScreen(bool b)
{
return *this;
}
void TopWindow::Maximize(bool effect)
{
state = MAXIMIZED;
frame->Maximize();
}
void TopWindow::Overlap(bool effect)
{
GuiLock __;
state = OVERLAPPED;
frame->Overlap();
}
TopWindow& TopWindow::TopMost(bool b, bool stay_top)
{
GuiLock __;
return *this;
}
bool TopWindow::IsTopMost() const
{
return true;
}
void TopWindow::GuiPlatformConstruct()
{
frame = new TopWindowFrame;
}
void TopWindow::GuiPlatformDestruct()
{
delete frame;
}
void TopWindow::SerializePlacement(Stream& s, bool reminimize)
{
GuiLock __;
}
END_UPP_NAMESPACE
#endif

16
rainbow/CoreGl/Top.h Normal file
View file

@ -0,0 +1,16 @@
//$ class TopWindow {
public:
virtual void State(int reason);
private:
TopWindowFrame *frame;
void SyncRect();
void SyncFrameRect(const Rect& r);
void DestroyFrame();
friend class Ctrl;
public:
void GripResize();
//$ };

209
rainbow/CoreGl/TopFrame.cpp Normal file
View file

@ -0,0 +1,209 @@
#if defined(flagWINGL) || defined(flagLINUXGL)
#include "TopFrame.h"
NAMESPACE_UPP
#define LLOG(x) // LOG(x)
TopWindowFrame::TopWindowFrame()
{
close.SetImage(CoreGlImg::close());
close.EdgeStyle();
Add(close);
maximize.SetImage(CoreGlImg::maximize());
maximize.EdgeStyle();
Add(maximize);
maximize <<= THISBACK(ToggleMaximize);
maximized = false;
sizeable = false;
holding = false;
}
void TopWindowFrame::SyncRect()
{
if(maximized) {
Size sz = screenRect.GetSize();
if(GetRect().GetSize() != sz)
SetRect(sz);
}
}
void TopWindowFrame::Maximize()
{
if(!maximized && maximize.IsShown()) {
maximized = true;
overlapped = GetRect();
SetRect(screenRect);
maximize.SetImage(CoreGlImg::overlap());
}
}
void TopWindowFrame::Overlap()
{
if(maximized && maximize.IsShown()) {
maximized = false;
SetRect(overlapped);
maximize.SetImage(CoreGlImg::maximize());
}
}
void TopWindowFrame::ToggleMaximize()
{
if(maximized)
Overlap();
else
Maximize();
}
Rect TopWindowFrame::Margins() const
{
return maximized ? Rect(0, 0, 0, 0) : ChMargins(CoreGlImg::border());
}
void TopWindowFrame::Paint(Draw& w)
{
Size sz = GetSize();
Rect m = Margins();
int c = GetStdFontCy() + 4;
ChPaintEdge(w, sz, CoreGlImg::border());
Image img = window->IsForeground() ? CoreGlImg::title() : CoreGlImg::bgtitle();
resources.Bind(img, Resources::FORCE_FILTERING | Resources::LINEAR_FILTERING);
ChPaint(w, m.left, m.top, sz.cx - m.left - m.right, GetStdFontCy() + 4, img);
int tx = m.left + 2;
int tcx = sz.cx - m.left - m.right - 4 - c * (close.IsShown() + maximize.IsShown());
if(!IsNull(icon)) {
Image h = icon;
if(h.GetWidth() > c || h.GetHeight() > c)
h = Rescale(h, GetFitSize(h.GetSize(), Size(c)));
w.DrawImage(tx, m.top + 2, h);
tx += c;
tcx -= c;
}
DrawTextEllipsis(w, tx, m.top + 2, tcx, title, "..", StdFont(), SColorHighlightText());
}
void TopWindowFrame::Layout()
{
Size sz = GetSize();
Rect m = Margins();
int c = GetStdFontCy() + 4;
int x = sz.cx - m.right;
if(close.IsShown())
close.SetRect(x -= c, m.top, c, c);
if(maximize.IsShown())
maximize.SetRect(x -= c, m.top, c, c);
}
Rect TopWindowFrame::GetClient() const
{
Rect r = GetRect();
Rect m = Margins();
r.left += m.left;
r.right -= m.right;
r.top += m.top;
r.bottom -= m.bottom;
r.top += GetStdFontCy() + 4;
return r;
}
Rect TopWindowFrame::ComputeClient(Rect r)
{
Rect m = Margins();
r.left -= m.left;
r.right += m.right;
r.top -= m.top;
r.bottom += m.bottom;
r.top -= GetStdFontCy() + 4;
return r;
}
void TopWindowFrame::SetClient(Rect r)
{
SetRect(ComputeClient(r));
}
Point TopWindowFrame::GetDragMode(Point p)
{
Size sz = GetSize();
Rect m = ChMargins(CoreGlImg::border());
Point dir;
dir.y = p.y < m.top ? -1 : p.y > sz.cy - m.top ? 1 : 0;
dir.x = p.x < m.left ? -1 : p.x > sz.cx - m.right ? 1 : 0;
return dir;
}
void TopWindowFrame::StartDrag()
{
if(maximized)
return;
if(!sizeable && (dir.x || dir.y))
return;
SetCapture();
startrect = GetRect();
startpos = GetMousePos();
}
void TopWindowFrame::GripResize()
{
dir = Point(1, 1);
StartDrag();
}
void TopWindowFrame::LeftDown(Point p, dword keyflags)
{
dir = GetDragMode(p);
StartDrag();
}
void TopWindowFrame::LeftDouble(Point p, dword keyflags)
{
ToggleMaximize();
IgnoreMouseUp();
}
void TopWindowFrame::LeftUp(Point p, dword keyflags)
{
ReleaseCapture();
}
void TopWindowFrame::MouseMove(Point, dword)
{
if(!HasCapture())
return;
Size msz = ComputeClient(minsize).GetSize();
Point p = GetMousePos() - startpos;
Rect r = startrect;
if(dir.x == -1)
r.left = min(r.left + p.x, startrect.right - msz.cx);
if(dir.x == 1)
r.right = max(r.right + p.x, startrect.left + msz.cx);
if(dir.y == -1)
r.top = min(r.top + p.y, startrect.bottom - msz.cy);
if(dir.y == 1)
r.bottom = max(r.bottom + p.y, startrect.top + msz.cy);
if(dir.y == 0 && dir.x == 0)
r.Offset(p);
SetRect(r);
}
Image TopWindowFrame::GetDragImage(Point dir)
{
static Image (*im[9])() = {
Image::SizeTopLeft, Image::SizeLeft, Image::SizeBottomLeft,
Image::SizeTop, Image::Arrow, Image::SizeBottom,
Image::SizeTopRight, Image::SizeRight, Image::SizeBottomRight,
};
return (*im[(dir.x + 1) * 3 + (dir.y + 1)])();
}
Image TopWindowFrame::CursorImage(Point p, dword)
{
if(!sizeable)
return Image::Arrow();
return GetDragImage(HasCapture() ? dir : GetDragMode(p));
}
END_UPP_NAMESPACE
#endif

62
rainbow/CoreGl/TopFrame.h Normal file
View file

@ -0,0 +1,62 @@
#ifndef _CoreGl_TopFrame_h_
#define _CoreGl_TopFrame_h_
#include <CtrlLib/CtrlLib.h>
NAMESPACE_UPP
class TopWindowFrame : public Ctrl {
public:
virtual void Layout();
virtual void Paint(Draw& w);
virtual Image CursorImage(Point p, dword keyflags);
virtual void LeftDown(Point p, dword keyflags);
virtual void LeftDouble(Point p, dword keyflags);
virtual void LeftUp(Point p, dword keyflags);
virtual void MouseMove(Point p, dword keyflags);
private:
Point dir;
Point startpos;
Rect startrect;
bool maximized;
Rect overlapped;
bool holding;
TimeCallback hold;
Point GetDragMode(Point p);
Image GetDragImage(Point dragmode);
void StartDrag();
Rect Margins() const;
Rect ComputeClient(Rect r);
void Hold();
typedef TopWindowFrame CLASSNAME;
public:
String title;
Button close, maximize;
Image icon;
Size minsize;
bool sizeable;
TopWindow *window;
void SetTitle(const String& s) { title = s; Refresh(); }
Rect GetClient() const;
void SetClient(Rect r);
void GripResize();
void Maximize();
void Overlap();
void ToggleMaximize();
bool IsMaximized() const { return maximized; }
void SyncRect();
TopWindowFrame();
};
END_UPP_NAMESPACE
#endif

87
rainbow/CoreGl/Util.cpp Normal file
View file

@ -0,0 +1,87 @@
#if defined(flagWINGL) || defined(flagLINUXGL)
#include <CtrlCore/CtrlCore.h>
NAMESPACE_UPP
void DDRect(RGBA *t, int dir, const byte *pattern, int pos, int count)
{
while(count-- > 0) {
byte p = pattern[7 & pos++];
t->r ^= p;
t->g ^= p;
t->b ^= p;
t += dir;
}
}
void DrawLine(const Vector<Rect>& clip, int x, int y, int cx, int cy, bool horz, const byte *pattern, int animation)
{
if(cx <= 0 || cy <= 0)
return;
/* Vector<Rect> rr = Intersection(clip, RectC(x, y, cx, cy));
for(int i = 0; i < rr.GetCount(); i++) {
Rect r = rr[i];
if(horz)
for(int y = r.top; y < r.bottom; y++)
DDRect(framebuffer[y] + r.left, 1, pattern, r.left + animation, r.GetWidth());
else
for(int x = r.left; x < r.right; x++)
DDRect(framebuffer[r.top] + x, framebuffer.GetWidth(), pattern, r.top + animation, r.GetHeight());
}*/
glColor4ub(255, 0, 0, 255);
//glEnable(GL_LINE_STIPPLE);
glBegin(GL_LINES);
glVertex2i(x, y);
glVertex2i(x + cx, y + cy);
//glVertex2i(10, 10);
//glVertex2i(100, 100);
glEnd();
//glDisable(GL_LINE_STIPPLE);
}
void DragRectDraw0(const Vector<Rect>& clip, const Rect& rect, int n, const byte *pattern, int animation)
{
int hn = min(rect.GetHeight(), n);
int vn = min(rect.GetWidth(), n);
DrawLine(clip, rect.left, rect.top, rect.GetWidth(), hn, true, pattern, animation);
DrawLine(clip, rect.left, rect.top + hn, vn, rect.GetHeight() - hn, false, pattern, animation);
DrawLine(clip, rect.right - vn, rect.top + hn, vn, rect.GetHeight() - hn, false, pattern, animation);
DrawLine(clip, rect.left + vn, rect.bottom - hn, rect.GetWidth() - 2 * vn, hn, true, pattern, animation);
}
void DrawDragRect(SystemDraw& w, const Rect& rect1, const Rect& rect2, const Rect& clip, int n, Color color, int type, int animation)
{
static byte solid[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
static byte normal[] = { 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00 };
static byte dashed[] = { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 };
Point p = Ctrl::screenRect.TopLeft();
Vector<Rect> pr;
if(type & Ctrl::DRAWDRAGRECT_SCREEN) {
pr.Add(Rect(Ctrl::screenRect.GetSize()));
type &= ~Ctrl::DRAWDRAGRECT_SCREEN;
p = Point(0, 0);
}
else
//pr = Intersection(screenRect, clip.Offseted(p));
pr.Add(clip.Offseted(p));
const byte *pattern = type == DRAWDRAGRECT_DASHED ? dashed :
type == DRAWDRAGRECT_NORMAL ? normal : solid;
DragRectDraw0(pr, rect1.Offseted(p), n, pattern, animation);
DragRectDraw0(pr, rect2.Offseted(p), n, pattern, animation);
}
void DrawDragRect(Ctrl& q, const Rect& rect1, const Rect& rect2, const Rect& clip, int n,
Color color, int type, int animation)
{
}
void FinishDragRect(Ctrl& q)
{
}
END_UPP_NAMESPACE
#endif

658
rainbow/CoreGl/Wnd.cpp Normal file
View file

@ -0,0 +1,658 @@
#if defined(flagWINGL) || defined(flagLINUXGL)
#include "TopFrame.h"
#include "ControlPanel.h"
#include "Console.h"
NAMESPACE_UPP
#define LLOG(x) DLOG(x)
#define LDUMP(x) DDUMP(x)
#define LDUMPC(x) DDUMPC(x)
Ptr<Ctrl> Ctrl::desktop;
Vector<Ctrl *> Ctrl::topctrl;
InfoPanel Ctrl::infoPanel;
Console Ctrl::console;
float Ctrl::angle = 0.f;
float Ctrl::scale = 1.f;
float Ctrl::alpha = 255.f;
Rect Ctrl::screenRect;
bool Ctrl::screenReady = false;
Point Ctrl::glCursorPos = Null;
Image Ctrl::glCursorImage;
Rect Ctrl::glCaretRect;
int Ctrl::glCaretTm;
int64 Ctrl::glEventLoop = 0;
int64 Ctrl::glEndSessionLoop = 0;
int Ctrl::PaintLock;
void GlLog(int line, const char* text, Color ink)
{
GuiLock __;
Ctrl::console.Log(line, text, ink);
}
void GlLog(const char* text, Color ink)
{
GuiLock __;
Ctrl::console.Log(text, ink);
}
void GlLogF(Color ink, const char* fmt, ...)
{
char buffer[1024];
va_list argptr;
va_start(argptr, fmt);
vsprintf(buffer, fmt, argptr);
va_end(argptr);
GlLog(buffer, ink);
}
void GlLogF(const char* fmt, ...)
{
char buffer[1024];
va_list argptr;
va_start(argptr, fmt);
vsprintf(buffer, fmt, argptr);
va_end(argptr);
GlLog(buffer);
}
void Ctrl::SetDesktop(Ctrl& q)
{
q.SetRect(screenRect.GetSize());
q.SetOpen(true);
q.StateH(OPEN);
q.NewTop();
desktop = &q;
}
void Ctrl::SetWindowSize(Size sz)
{
screenRect = sz;
if(desktop)
desktop->SetRect(screenRect);
}
void Ctrl::InitGl()
{
Ctrl::GlobalBackBuffer();
Ctrl::InitTimer();
ChStdSkin();
static StaticRect x;
x.Color(Cyan());
SetDesktop(x);
}
void Ctrl::EndSession()
{
GuiLock __;
glEndSession = true;
EndSessionLoopNo = EventLoopNo;
}
void Ctrl::ExitGl()
{
TopWindow::ShutdownWindows();
Ctrl::CloseTopCtrls();
if(glEndSession)
GlQuitSession();
}
int Ctrl::FindTopCtrl() const
{
for(int i = 0; i < topctrl.GetCount(); i++)
if(this == topctrl[i])
return i;
return -1;
}
bool Ctrl::IsAlphaSupported()
{
return false;
}
bool Ctrl::IsCompositedGui()
{
return false;
}
Vector<Ctrl *> Ctrl::GetTopCtrls()
{
Vector<Ctrl *> ctrl;
if(desktop)
ctrl.Add(desktop);
for(int i = 0; i < topctrl.GetCount(); i++)
if(!dynamic_cast<TopWindowFrame *>(topctrl[i]))
ctrl.Add(topctrl[i]);
return ctrl;
}
Ctrl *Ctrl::GetOwner()
{
GuiLock __;
int q = FindTopCtrl();
if(q > 0 && topctrl[q]->top) {
Ctrl *x = topctrl[q]->top->owner_window;
return dynamic_cast<TopWindowFrame *>(x) ? x->GetOwner() : x;
}
return NULL;
}
Ctrl *Ctrl::GetActiveCtrl()
{
GuiLock __;
if(focusCtrl == &infoPanel || focusCtrl == &console)
return desktop;
return focusCtrl ? focusCtrl->GetTopCtrl() : NULL;
}
// Vector<Callback> Ctrl::hotkey;
int Ctrl::RegisterSystemHotKey(dword key, Callback cb)
{
/* ASSERT(key >= K_DELTA);
int q = hotkey.GetCount();
for(int i = 0; i < hotkey.GetCount(); i++)
if(!hotkey[i]) {
q = i;
break;
}
hotkey.At(q) = cb;
dword mod = 0;
if(key & K_ALT)
mod |= MOD_ALT;
if(key & K_SHIFT)
mod |= MOD_SHIFT;
if(key & K_CTRL)
mod |= MOD_CONTROL;
return RegisterHotKey(NULL, q, mod, key & 0xffff) ? q : -1;*/
return -1;
}
void Ctrl::UnregisterSystemHotKey(int id)
{
/* if(id >= 0 && id < hotkey.GetCount()) {
UnregisterHotKey(NULL, id);
hotkey[id].Clear();
}*/
}
bool Ctrl::IsWaitingEvent()
{
return GlIsWaitingEvent();
}
void Ctrl::SyncTopWindows()
{
for(int i = 0; i < topctrl.GetCount(); i++) {
TopWindow *w = dynamic_cast<TopWindow *>(topctrl[i]);
if(w)
w->SyncRect();
}
}
bool Ctrl::ProcessEvent(bool *quit)
{
ASSERT(IsMainThread());
if(!GetMouseLeft() && !GetMouseRight() && !GetMouseMiddle())
ReleaseCtrlCapture();
if(GlProcessEvent(quit)) {
SyncTopWindows();
DefferedFocusSync();
SyncCaret();
return true;
}
else if(glDrawMode == DRAW_ON_IDLE && !Ctrl::painting)
{
GuiSleep(0);
TimerProc(GetTickCount());
SweepMkImageCache();
DrawScreen();
}
return false;
}
void Ctrl::DrawScreen()
{
#ifdef flagWINGL
if(hRC)
#endif
if(desktop && !painting) {
screenReady = true;
painting = true;
resources.BindStatic();
int64 t0 = GetHighTickCount();
frameInfo.curr_tick_count = t0;
desktop->ApplyLayout();
desktop->ApplyTransform(TS_BEFORE_SCREEN);
for(int i = 0; i < topctrl.GetCount(); i++) {
topctrl[i]->ApplyLayout();
topctrl[i]->ApplyTransform(TS_BEFORE_SCREEN);
}
Rect clip = desktop->GetRect();
SystemDraw draw(clip.GetSize());
infoPanel.Init(*desktop);
infoPanel.Show(controlPanelActive);
console.Init(*desktop);
console.Show(consoleActive);
draw.alpha = infoPanel.GetAlpha();
draw.angle = infoPanel.GetAngle();
draw.scale = infoPanel.GetScale();
draw.ViewPort();
draw.OrthogonalView();
draw.Clear(true);
screenFbo0.Bind();
screenFbo0.Clear();
desktop->ApplyTransform(TS_BEFORE_PAINT);
desktop->CtrlPaint(draw, clip);
screenFbo0.Unbind();
draw.OrthogonalView();
glDisable(GL_BLEND);
RectF drawRect(0.f, 0.f, (float) screenRect.GetWidth(), (float) screenRect.GetHeight());
float blur = SystemDraw::blurStrength;
float gray = SystemDraw::grayStrength;
if(blur > 0 || gray > 0)
{
float sigma = blur * 3.f;
float gx = 1.0f / (sqrt(2.0f * float(M_PI)) * sigma);
float gy = exp(-0.5f / (sigma * sigma));
float gz = gy * gy;
float blurSizeHorz = 1.f / (float) screenFbo0.width;
float blurSizeVert = 1.f / (float) screenFbo0.height;
blurProg.Start();
blurProg.SetUniform("blurSize", blurSizeHorz);
blurProg.SetUniform("gaussian", gx, gy, gz);
blurProg.SetUniform("blurMultiplyVec", 1, 0);
blurProg.SetUniform("blurStrength", blur);
blurProg.SetUniform("grayStrength", gray);
screenFbo1.Bind();
draw.DrawTextureOp(drawRect, screenFbo0.texId, screenFbo0.width, screenFbo0.height, drawRect);
screenFbo1.Unbind();
blurProg.SetUniform("blurSize", blurSizeVert);
blurProg.SetUniform("blurMultiplyVec", 0, 1);
blurProg.SetUniform("blurStrength", blur);
blurProg.SetUniform("grayStrength", gray);
draw.ApplyTransforms();
draw.DrawTextureOp(drawRect, screenFbo1.texId, screenFbo1.width, screenFbo1.height, drawRect);
blurProg.Stop();
}
else
{
draw.ApplyTransforms();
draw.DrawTextureOp(drawRect, screenFbo0.texId, screenFbo0.width, screenFbo0.height, drawRect);
//screenFbo0.BlitToScreen();
}
glEnable(GL_BLEND);
for(int i = 0; i < topctrl.GetCount(); i++) {
Ctrl* tq = topctrl[i];
if(tq == &infoPanel || tq == &console)
continue;
Rect r = tq->GetRect();
tq->ApplyTransform(TS_BEFORE_PAINT);
draw.Offset(r.left, r.top);
tq->CtrlPaint(draw, clip);
draw.End();
tq->ApplyTransform(TS_AFTER_PAINT);
}
CursorSync(draw);
desktop->PostPaint(draw);
desktop->ApplyTransform(TS_AFTER_PAINT);
glLoadIdentity();
#if CLIP_MODE == 2
//glDisable(GL_STENCIL_TEST);
#endif
draw.ImageColoring();
draw.alpha = 255.f;
if(controlPanelActive)
{
draw.Offset(infoPanel.GetRect().TopLeft());
infoPanel.CtrlPaint(draw, clip);
draw.End();
}
if(consoleActive)
{
draw.Offset(console.GetRect().TopLeft());
console.CtrlPaint(draw, clip);
draw.End();
}
#if CLIP_MODE == 2
//glEnable(GL_STENCIL_TEST);
#endif
MouseSync(draw);
#ifdef flagWINGL
SwapBuffers(hDC);
#endif
#ifdef flagLINUXGL
glXSwapBuffers(dpy, win);
#endif
int64 t1 = GetHighTickCount();
frameInfo.frame_time = t1 - t0;
frameInfo.frame_factor = frameInfo.frame_time * frameInfo.frame_skip / 1000.f;
frameInfo.fps = frameInfo.frame_time > 0.f ? 1000.f / (float)frameInfo.frame_time : 0.f;
//LOGF("ft: %d, t0: %d, t1: %d\n", frameInfo.frame_time, t0, t1);
painting = false;
}
}
bool Ctrl::ProcessEvents(bool *quit)
{
if(!ProcessEvent(quit))
return false;
while(ProcessEvent(quit) && (!LoopCtrl || LoopCtrl->InLoop()));
if(glDrawMode == DRAW_ON_TIMER)
{
TimerProc(GetTickCount());
SweepMkImageCache();
DrawScreen();
}
return true;
}
void Ctrl::EventLoop(Ctrl *ctrl)
{
GuiLock __;
ASSERT(IsMainThread());
ASSERT(LoopLevel == 0 || ctrl);
LoopLevel++;
Ptr<Ctrl> ploop;
if(ctrl) {
ploop = LoopCtrl;
LoopCtrl = ctrl;
ctrl->inloop = true;
}
bool quit = false;
int64 loopno = ++EventLoopNo;
ProcessEvents(&quit);
while(loopno > EndSessionLoopNo && !quit && (ctrl ? ctrl->IsOpen() && ctrl->InLoop() : GetTopCtrls().GetCount()))
{
SyncCaret();
//if(glDrawMode == DRAW_ON_TIMER)
// GuiSleep(20);
ProcessEvents(&quit);
}
if(ctrl)
LoopCtrl = ploop;
LoopLevel--;
}
void Ctrl::GuiSleep(int ms)
{
GuiLock __;
ASSERT(IsMainThread());
int level = LeaveGuiMutexAll();
GlSleep(ms);
EnterGuiMutex(level);
}
Rect Ctrl::GetWndScreenRect() const
{
GuiLock __;
return GetRect();
}
void Ctrl::WndShow(bool b)
{
GuiLock __;
}
void Ctrl::WndUpdate()
{
GuiLock __;
}
void Ctrl::WndUpdate(const Rect& r)
{
GuiLock __;
}
bool Ctrl::IsWndOpen() const {
GuiLock __;
return FindTopCtrl() >= 0 || this == desktop;
}
void Ctrl::SetAlpha(byte alpha)
{
GuiLock __;
}
Rect Ctrl::GetWorkArea() const
{
GuiLock __;
return screenRect;
}
void Ctrl::GetWorkArea(Array<Rect>& rc)
{
GuiLock __;
//Array<Rect> r;
rc.Add(screenRect.GetSize());
}
Rect Ctrl::GetVirtualWorkArea()
{
return screenRect;
}
Rect Ctrl::GetWorkArea(Point pt)
{
return screenRect;
}
Rect Ctrl::GetVirtualScreenArea()
{
return screenRect;
}
Rect Ctrl::GetPrimaryWorkArea()
{
return screenRect;
}
Rect Ctrl::GetPrimaryScreenArea()
{
return screenRect;
}
int Ctrl::GetKbdDelay()
{
GuiLock __;
return 500;
}
int Ctrl::GetKbdSpeed()
{
GuiLock __;
return 1000 / 32;
}
void Ctrl::DestroyWnd()
{
for(int i = 0; i < topctrl.GetCount(); i++)
if(topctrl[i]->top && topctrl[i]->top->owner_window == this)
topctrl[i]->WndDestroy();
int q = FindTopCtrl();
if(q >= 0) {
topctrl.Remove(q);
}
if(top) {
delete top;
top = NULL;
}
isopen = false;
TopWindow *win = dynamic_cast<TopWindow *>(this);
if(win)
win->DestroyFrame();
}
void Ctrl::WndDestroy()
{
DestroyWnd();
if(topctrl.GetCount())
topctrl.Top()->ActivateWnd();
}
void Ctrl::PutForeground()
{
int q = FindTopCtrl();
if(q >= 0) {
topctrl.Remove(q);
topctrl.Add(this);
}
Vector< Ptr<Ctrl> > fw;
for(int i = 0; i < topctrl.GetCount(); i++)
if(topctrl[i] && topctrl[i]->top && topctrl[i]->top->owner_window == this && topctrl[i] != this)
fw.Add(topctrl[i]);
for(int i = 0; i < fw.GetCount(); i++)
if(fw[i])
fw[i]->PutForeground();
}
void Ctrl::SetWndForeground()
{
GuiLock __;
ASSERT(IsOpen());
if(IsWndForeground())
return;
Ctrl *to = this;
while(to->top && to->top->owner_window)
to = to->top->owner_window;
to->PutForeground();
if(this != focusCtrl)
ActivateWnd();
}
bool Ctrl::IsWndForeground() const
{
GuiLock __;
bool b = false;
for(int i = 0; i < topctrl.GetCount(); i++) {
const TopWindow *tw = dynamic_cast<const TopWindow *>(topctrl[i]);
if(tw)
b = tw == this;
}
return b;
}
void Ctrl::WndEnable(bool b)
{
GuiLock __;
}
bool Ctrl::SetWndFocus()
{
GuiLock __;
return true;
}
bool Ctrl::HasWndFocus() const
{
GuiLock __;
return focusCtrl && focusCtrl->GetTopCtrl() == this;
}
bool Ctrl::SetWndCapture()
{
GuiLock __;
ASSERT(IsMainThread());
return true;
}
bool Ctrl::ReleaseWndCapture()
{
GuiLock __;
ASSERT(IsMainThread());
return true;
}
bool Ctrl::HasWndCapture() const
{
GuiLock __;
return captureCtrl && captureCtrl->GetTopCtrl() == this;
}
void Ctrl::WndInvalidateRect(const Rect& r)
{
GuiLock __;
//::InvalidateRect(glHwnd, NULL, false);
}
void Ctrl::WndSetPos(const Rect& rect)
{
GuiLock __;
TopWindow *w = dynamic_cast<TopWindow *>(this);
if(w)
w->SyncFrameRect(rect);
SetWndRect(rect);
}
void Ctrl::WndScrollView(const Rect& r, int dx, int dy)
{
GuiLock __;
}
void Ctrl::PopUp(Ctrl *owner, bool savebits, bool activate, bool dropshadow, bool topmost)
{
ASSERT(!IsChild() && !IsOpen() && FindTopCtrl() < 0);
NewTop();
if(owner) {
Ctrl *owner_window = owner->GetTopWindow();
if(!owner_window)
owner_window = owner->GetTopCtrl();
ASSERT(owner_window->IsOpen());
if(owner_window != desktop) {
owner_window->SetForeground();
top->owner_window = owner_window;
}
}
topctrl.Add(this);
popup = isopen = true;
StateH(OPEN);
if(activate) SetFocusWnd();
}
Rect Ctrl::GetDefaultWindowRect() {
GuiLock __;
int ii = 0;
Size sz = screenRect.GetSize();
Rect rect = sz;
rect.Deflate(sz / 8);
rect.Offset(Point(sz) / 16 * (ii % 8));
return rect;
}
Vector<WString> SplitCmdLine__(const char *cmd)
{
Vector<WString> out;
while(*cmd)
if((byte)*cmd <= ' ')
cmd++;
else if(*cmd == '\"') {
WString quoted;
while(*++cmd && (*cmd != '\"' || *++cmd == '\"'))
quoted.Cat(FromSystemCharset(String(cmd, 1)).ToWString());
out.Add(quoted);
}
else {
const char *begin = cmd;
while((byte)*cmd > ' ')
cmd++;
out.Add(String(begin, cmd).ToWString());
}
return out;
}
END_UPP_NAMESPACE
#endif

15483
rainbow/CoreGl/glew.c Normal file

File diff suppressed because it is too large Load diff

15507
rainbow/CoreGl/glew.h Normal file

File diff suppressed because it is too large Load diff

1568
rainbow/CoreGl/glxew.h Normal file

File diff suppressed because it is too large Load diff

4
rainbow/CoreGl/init Normal file
View file

@ -0,0 +1,4 @@
#ifndef _CoreGl_icpp_init_stub
#define _CoreGl_icpp_init_stub
#include "Painter/init"
#endif

1361
rainbow/CoreGl/wglew.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,10 @@
uses
Draw,
Gtk;
file
main.cpp;
mainconfig
"" = "GUI GTK";

5
rainbow/DevDraw/init Normal file
View file

@ -0,0 +1,5 @@
#ifndef _DevDraw_icpp_init_stub
#define _DevDraw_icpp_init_stub
#include "Draw/init"
#include "Gtk/init"
#endif

102
rainbow/DevDraw/main.cpp Normal file
View file

@ -0,0 +1,102 @@
#include <CtrlLib/CtrlLib.h>
#include <RichEdit/RichEdit.h>
using namespace Upp;
void TestDraw(Draw& w)
{
w.DrawRect(0, 0, 10000, 10000, WhiteGray());
w.DrawRect(0, 0, 100, 100, Yellow());
w.DrawLine(10, 40, 400, 20, 3, Blue());
w.DrawImage(0, 0, CtrlImg::exclamation());
w.Clipoff(50, 50, 30, 30);
w.DrawImage(0, 0, CtrlImg::exclamation());
w.End();
w.DrawImage(50, 50 + 32, CtrlImg::exclamation(), RectC(24, 24, 10, 10));
w.DrawImage(150, 50, CtrlImg::exclamation(), Red());
w.DrawImage(150, 50 + 32, CtrlImg::exclamation(), RectC(24, 24, 10, 10), Red());
// w.DrawText(20, 20, "Hello GTK!", Roman(50));
w.Offset(150, 50);
const char *text = "Programming is fun";
Font fnt(Roman(60));
FontInfo fi = fnt.Info();
int x = 0;
Vector<int> dx;
for(const char *s = text; *s; s++) {
int width = fi[*s];
w.DrawRect(x, 0, width - 1, fi.GetAscent(), Color(255, 255, 200));
w.DrawRect(x, fi.GetAscent(), width - 1, fi.GetDescent(), Color(255, 200, 255));
w.DrawRect(x + width - 1, 0, 1, fi.GetHeight(), Black());
dx.Add(width + 4);
x += width;
}
w.DrawRect(0, 0, 4, 4, Black());
w.DrawText(0, 0, text, fnt);
w.DrawText(0, 70, text, fnt, Blue(), dx.GetCount(), dx.Begin());
w.DrawRect(50, 400, 2, 2, Black());
w.DrawText(50, 400, 200, "Angled text", Arial(50).Underline(), Red());
w.DrawRect(600, 400, 2, 2, Black());
w.DrawText(600, 400, 1000, "Angled text", Arial(50).Underline(), Black());
w.End();
}
static gboolean on_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data)
{
SystemDraw w(gdk_cairo_create(widget->window));
TestDraw(w);
cairo_destroy(w);
return FALSE;
}
GUI_APP_MAIN
{
Ctrl myapp;
{
ImageDraw w(1000, 1000);
TestDraw(w);
PNGEncoder().SaveFile("/home/cxl/test.png", w);
}
{
ImageDraw w(1000, 1000);
TestDraw(w);
for(int i = 0; i < 100; i++)
w.Alpha().DrawRect(i * 10, 0, 10, 1000, GrayColor(255 - i));
PNGEncoder().SaveFile("/home/cxl/test_alpha.png", w);
}
GtkWidget *window;
// window = gtk_window_new(GTK_WINDOW_POPUP);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size((GtkWindow *)window, 1000, 600);
GtkWidget *darea = gtk_drawing_area_new();
gtk_container_add(GTK_CONTAINER (window), darea);
gtk_widget_set_events(darea, 0xffffffff);
g_signal_connect(darea, "expose-event", G_CALLBACK(on_expose_event), &myapp);
// g_signal_connect(window, "expose-event", G_CALLBACK(on_expose_event), NULL);
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_show_all(window);
Ctrl::EventLoop(&myapp);
// gtk_main();
}

View file

@ -0,0 +1,11 @@
uses
CtrlLib,
Framebuffer,
WinFb;
file
main.cpp;
mainconfig
"" = "GUI WINFB";

View file

@ -0,0 +1,6 @@
#ifndef _DrawDragRect_icpp_init_stub
#define _DrawDragRect_icpp_init_stub
#include "CtrlLib/init"
#include "Framebuffer/init"
#include "WinFb/init"
#endif

View file

@ -0,0 +1,87 @@
#include <CtrlLib/CtrlLib.h>
#include <RichEdit/RichEdit.h>
using namespace Upp;
void DDRect(RGBA *t, int dir, const byte *pattern, int pos, int count)
{
while(count-- > 0) {
byte p = pattern[7 & pos++];
*t->r ^= p;
*t->g ^= p;
*t->b ^= p;
t += dir;
}
}
struct App : public Ctrl {
uint64 pattern;
int pos;
int a;
int dir;
void Paint(Draw& w)
{
DDUMP(pattern);
Size sz = GetSize();
w.DrawRect(sz, White());
DrawDragRect((SystemDraw&)w,
Rect(0, 0, 0, 0),
RectC(10, 10, a, a / 3),
Size(800, 600),
1,
Black(),
pattern);
}
virtual Image CursorImage(Point p, dword keyflags) {
Animate();
return Image::Arrow();
}
void Animate() {
pattern = I64(0xf0f0) >> (pos++ & 7);
if(Random() % 100 == 0)
dir = (int)Random() % 3 - 1;
a += dir;
if(a < 0) {
a = 0;
dir = -dir;
}
if(a > 1000) {
a = 1000;
dir = -dir;
}
// if(++a > 900)
// a = 0;
DrawDragRect(*this,
Rect(0, 0, 0, 0),
RectC(10, 10, a, a / 3),
Size(800, 600),
1,
Black(),
pattern);
PostCallback(THISBACK(Animate));
}
typedef App CLASSNAME;
App()
{
pattern = I64(9732030564846854595);
pos = 0;
a = 200;
dir = 1;
// PostCallback(THISBACK(Animate));
SetCaret(0, 0, 20, 20);
}
};
GUI_APP_MAIN
{
App app;
Ctrl::SetDesktop(app);
app.SetFocus();
Ctrl::EventLoop();
}

236
rainbow/Events/Events.cpp Normal file
View file

@ -0,0 +1,236 @@
#include <CtrlLib/CtrlLib.h>
using namespace Upp;
class App : public TopWindow {
public:
typedef App CLASSNAME;
ArrayCtrl log;
void Log(const String& s)
{
log.Add(s);
log.GoEnd();
}
virtual void Activate()
{
Log("Activate");
}
virtual void Deactivate()
{
Log("Deactivate");
}
virtual Image FrameMouseEvent(int event, Point p, int zdelta, dword keyflags)
{
if(event != CURSORIMAGE)
Log(Format("FrameMouseEvent(%d, Point(%d, %d), %d, %x)",
event, p.x, p.y, zdelta, (int)keyflags));
return TopWindow::FrameMouseEvent(event, p, zdelta, keyflags);
}
virtual Image MouseEvent(int event, Point p, int zdelta, dword keyflags)
{
if(event != CURSORIMAGE)
Log(Format("MouseEvent(%d, Point(%d, %d), %d, %x)",
event, p.x, p.y, zdelta, (int)keyflags));
return TopWindow::MouseEvent(event, p, zdelta, keyflags);
}
virtual void MouseEnter(Point p, dword keyflags)
{
Log(Format("MouseEnter(Point(%d, %d), %x)", p.x, p.y, (int)keyflags));
}
virtual void MouseMove(Point p, dword keyflags)
{
Log(Format("MouseMove(Point(%d, %d), %x)", p.x, p.y, (int)keyflags));
}
virtual void LeftDown(Point p, dword keyflags)
{
Log(Format("LeftDown(Point(%d, %d), %x)", p.x, p.y, (int)keyflags));
SetFocus();
}
virtual void LeftDouble(Point p, dword keyflags)
{
Log(Format("LeftDouble(Point(%d, %d), %x)", p.x, p.y, (int)keyflags));
}
virtual void LeftTriple(Point p, dword keyflags)
{
Log(Format("LeftTriple(Point(%d, %d), %x)", p.x, p.y, (int)keyflags));
}
virtual void LeftDrag(Point p, dword keyflags) {
Log(Format("LeftDrag(Point(%d, %d), %x)", p.x, p.y, (int)keyflags));
}
virtual void LeftHold(Point p, dword keyflags) {
Log(Format("LeftHold(Point(%d, %d), %x)", p.x, p.y, (int)keyflags));
}
virtual void LeftRepeat(Point p, dword keyflags)
{
Log(Format("LeftRepeat(Point(%d, %d), %x)", p.x, p.y, (int)keyflags));
}
virtual void LeftUp(Point p, dword keyflags)
{
Log(Format("LeftUp(Point(%d, %d), %x)", p.x, p.y, (int)keyflags));
}
virtual void RightDown(Point p, dword keyflags)
{
Log(Format("RightDown(Point(%d, %d), %x)", p.x, p.y, (int)keyflags));
}
virtual void RightDouble(Point p, dword keyflags)
{
Log(Format("RightDouble(Point(%d, %d), %x)", p.x, p.y, (int)keyflags));
}
virtual void RightTriple(Point p, dword keyflags)
{
Log(Format("RightTriple(Point(%d, %d), %x)", p.x, p.y, (int)keyflags));
}
virtual void RightDrag(Point p, dword keyflags) {
Log(Format("RightDrag(Point(%d, %d), %x)", p.x, p.y, (int)keyflags));
}
virtual void RightHold(Point p, dword keyflags) {
Log(Format("RightHold(Point(%d, %d), %x)", p.x, p.y, (int)keyflags));
}
virtual void RightRepeat(Point p, dword keyflags)
{
Log(Format("RightRepeat(Point(%d, %d), %x)", p.x, p.y, (int)keyflags));
}
virtual void RightUp(Point p, dword keyflags)
{
Log(Format("RightUp(Point(%d, %d), %x)", p.x, p.y, (int)keyflags));
}
virtual void MiddleDown(Point p, dword keyflags)
{
Log(Format("MiddleDown(Point(%d, %d), %x)", p.x, p.y, (int)keyflags));
}
virtual void MiddleDouble(Point p, dword keyflags)
{
Log(Format("MiddleDouble(Point(%d, %d), %x)", p.x, p.y, (int)keyflags));
}
virtual void MiddleTriple(Point p, dword keyflags)
{
Log(Format("MiddleTriple(Point(%d, %d), %x)", p.x, p.y, (int)keyflags));
}
virtual void MiddleDrag(Point p, dword keyflags) {
Log(Format("MiddleDrag(Point(%d, %d), %x)", p.x, p.y, (int)keyflags));
}
virtual void MiddleHold(Point p, dword keyflags) {
Log(Format("MiddleHold(Point(%d, %d), %x)", p.x, p.y, (int)keyflags));
}
virtual void MiddleRepeat(Point p, dword keyflags)
{
Log(Format("MiddleRepeat(Point(%d, %d), %x)", p.x, p.y, (int)keyflags));
}
virtual void MiddleUp(Point p, dword keyflags)
{
Log(Format("MiddleUp(Point(%d, %d), %x)", p.x, p.y, (int)keyflags));
}
virtual void MouseWheel(Point p, int zdelta, dword keyflags)
{
Log(Format("MouseWheel(Point(%d, %d), %d, %x)", p.x, p.y, zdelta, (int)keyflags));
}
virtual void MouseLeave()
{
Log("MouseLeave");
}
virtual Image CursorImage(Point p, dword keyflags)
{
return keyflags & K_CTRL ? CtrlImg::swap_color_cursor() : Image::Arrow();
}
virtual bool Key(dword key, int count)
{
Log(Format("Key(%x, %d) ", (int)key, count) + GetKeyDesc(key));
return false;
}
virtual bool WKey(dword key, int count)
{
Log(Format("WKey(%x, %d) ", (int)key, count) + GetKeyDesc(key));
return false;
}
virtual void GotFocus()
{
Log("GotFocus");
}
virtual void LostFocus()
{
Log("LostFocus");
}
virtual bool HotKey(dword key)
{
Log(Format("HotKey(%x) ", (int)key) + GetKeyDesc(key));
return false;
}
virtual void ChildGotFocus()
{
Log("ChildGotFocus");
}
virtual void ChildLostFocus()
{
Log("ChildLostFocus");
}
virtual void Layout()
{
Log("Layout");
}
void OnTimer()
{
Log("Timer");
}
App()
{
SetFrame(InsetFrame());
AddFrame(InsetFrame());
AddFrame(InsetFrame());
AddFrame(InsetFrame());
log.AddColumn("");
log.NoHeader();
Add(log.HSizePos().BottomPos(0, 200));
SetTimeCallback(-1000, THISBACK(OnTimer));
}
~App()
{
Shutdown();
}
};
GUI_APP_MAIN
{
App().Run();
}

29
rainbow/Events/Events.upp Normal file
View file

@ -0,0 +1,29 @@
description "Demonstration of basic input events";
uses
CtrlLib;
uses(SKELETON) Skeleton;
uses(WINALT) WinAlt;
uses(WINFB) WinFb;
uses(LINUXFB) LinuxFb;
uses(SDLFB) SDLFb;
uses(WINGL) WinGl;
file
Events.cpp;
mainconfig
"" = "GUI SKELETON",
"" = "GUI WINALT",
"" = "GUI WINFB",
"" = "GUI LINUXFB",
"" = "GUI SDLFB",
"" = "GUI WINGL",
"" = "GUI";

View file

@ -0,0 +1,17 @@
class ViewDraw : public SystemDraw {
public:
ViewDraw(Ctrl *ctrl);
~ViewDraw();
};
/*
class ViewDraw : public SystemDraw {
Vector<Rect> dummy;
public:
ViewDraw(Ctrl *) : SystemDraw(Ctrl::framebuffer, dummy) { dummy.Add(Rect(10, 10, 100, 100)); }
};
*/
class DHCtrl : Ctrl {};
#include FRAMEBUFFER_INCLUDE

View file

@ -0,0 +1,21 @@
#include <CtrlLib/CtrlLib.h>
#ifdef GUI_FB
NAMESPACE_UPP
void ChSysInit()
{
CtrlImg::Reset();
CtrlsImg::Reset();
ChReset();
}
void ChHostSkin()
{
ChSysInit();
}
END_UPP_NAMESPACE
#endif

View file

@ -0,0 +1,238 @@
#include "Fb.h"
#ifdef GUI_FB
NAMESPACE_UPP
#define LLOG(x) // LOG(x)
static VectorMap<String, ClipData> fbClipboard;
void ClearClipboard()
{
GuiLock __;
fbClipboard.Clear();
}
void AppendClipboard(const char *format, const Value& data, String (*render)(const Value&))
{
GuiLock __;
ClipData& cd = fbClipboard.GetAdd(format);
cd.data = data;
cd.render = render;
}
static String sRawRender(const Value& v)
{
return v;
}
void AppendClipboard(const char *format, const String& data)
{
GuiLock __;
AppendClipboard(format, data, sRawRender);
}
void AppendClipboard(const char *format, const byte *data, int length)
{
GuiLock __;
AppendClipboard(format, String(data, length));
}
String ReadClipboard(const char *format)
{
GuiLock __;
int q = fbClipboard.Find(format);
return q >= 0 ? (*fbClipboard[q].render)(fbClipboard[q].data) : String();
}
void AppendClipboardText(const String& s)
{
AppendClipboard("text", ToSystemCharset(s));
}
void AppendClipboardUnicodeText(const WString& s)
{
AppendClipboard("wtext", (byte *)~s, 2 * s.GetLength());
}
const char *ClipFmtsText()
{
return "wtext;text";
}
String GetString(PasteClip& clip)
{
GuiLock __;
if(clip.Accept("wtext")) {
String s = ~clip;
return WString((const wchar *)~s, wstrlen((const wchar *)~s)).ToString();
}
if(clip.IsAvailable("text"))
return ~clip;
return Null;
}
WString GetWString(PasteClip& clip)
{
GuiLock __;
if(clip.Accept("wtext")) {
String s = ~clip;
return WString((const wchar *)~s, wstrlen((const wchar *)~s));
}
if(clip.IsAvailable("text"))
return (~clip).ToWString();
return Null;
}
bool AcceptText(PasteClip& clip)
{
return clip.Accept(ClipFmtsText());
}
static String sText(const Value& data)
{
return data;
}
static String sWText(const Value& data)
{
return Unicode__(WString(data));
}
void Append(VectorMap<String, ClipData>& data, const String& text)
{
data.GetAdd("text", ClipData(text, sText));
data.GetAdd("wtext", ClipData(text, sWText));
}
void Append(VectorMap<String, ClipData>& data, const WString& text)
{
data.GetAdd("text", ClipData(text, sText));
data.GetAdd("wtext", ClipData(text, sWText));
}
String GetTextClip(const WString& text, const String& fmt)
{
if(fmt == "text")
return text.ToString();
if(fmt == "wtext")
return Unicode__(text);
return Null;
}
String GetTextClip(const String& text, const String& fmt)
{
if(fmt == "text")
return text;
if(fmt == "wtext")
return Unicode__(text.ToWString());
return Null;
}
String ReadClipboardText()
{
String w = ReadClipboard("text");
return w.GetCount() ? w : ReadClipboardUnicodeText().ToString();
}
WString ReadClipboardUnicodeText()
{
String w = ReadClipboard("wtext");
if(w.GetCount())
return WString((const wchar *)~w, w.GetLength() / 2);
return ReadClipboard("text").ToWString();
}
bool IsClipboardAvailable(const char *id)
{
return fbClipboard.Find(id) >= 0;
}
bool IsClipboardAvailableText()
{
return IsClipboardAvailable("text") || IsClipboardAvailable("wtext");
}
const char *ClipFmtsImage()
{
static const char *q;
ONCELOCK {
static String s = "dib;" + ClipFmt<Image>();
q = s;
}
return q;
}
bool AcceptImage(PasteClip& clip)
{
GuiLock __;
return clip.Accept(ClipFmtsImage());
}
Image GetImage(PasteClip& clip)
{
GuiLock __;
Image m;
if(Accept<Image>(clip)) {
LoadFromString(m, ~clip);
if(!m.IsEmpty())
return m;
}
return Null;
}
Image ReadClipboardImage()
{
GuiLock __;
PasteClip d = Ctrl::Clipboard();
return GetImage(d);
}
String sImage(const Value& image)
{
Image img = image;
return StoreAsString(const_cast<Image&>(img));
}
String GetImageClip(const Image& img, const String& fmt)
{
GuiLock __;
if(img.IsEmpty()) return Null;
if(fmt == ClipFmt<Image>())
return sImage(img);
return Null;
}
void AppendClipboardImage(const Image& img)
{
GuiLock __;
if(img.IsEmpty()) return;
AppendClipboard(ClipFmt<Image>(), img, sImage);
}
bool AcceptFiles(PasteClip& clip)
{
if(clip.Accept("files")) {
clip.SetAction(DND_COPY);
return true;
}
return false;
}
bool IsAvailableFiles(PasteClip& clip)
{
return clip.IsAvailable("files");
}
Vector<String> GetFiles(PasteClip& clip)
{
GuiLock __;
Vector<String> f;
return f;
}
END_UPP_NAMESPACE
#endif

View file

@ -0,0 +1,81 @@
#include "Fb.h"
#ifdef GUI_FB
#define LLOG(x) // DLOG(x)
NAMESPACE_UPP
void Ctrl::GuiPlatformConstruct()
{
}
void Ctrl::GuiPlatformRemove()
{
}
void Ctrl::GuiPlatformGetTopRect(Rect& r) const
{
}
bool Ctrl::GuiPlatformRefreshFrameSpecial(const Rect& r)
{
return false;
}
bool Ctrl::GuiPlatformSetFullRefreshSpecial()
{
return false;
}
void Ctrl::PaintCaret(SystemDraw& w)
{
}
String GuiPlatformGetKeyDesc(dword key)
{
return Null;
}
void Ctrl::GuiPlatformSelection(PasteClip&)
{
}
void GuiPlatformAdjustDragImage(ImageBuffer&)
{
}
bool GuiPlatformHasSizeGrip()
{
return true;
}
void GuiPlatformGripResize(TopWindow *q)
{
q->GripResize();
}
Color GuiPlatformGetScreenPixel(int x, int y)
{
return Ctrl::GetFrameBuffer()[y][x];
}
void GuiPlatformAfterMenuPopUp()
{
}
String Ctrl::Name() const {
GuiLock __;
#ifdef CPU_64
String s = String(typeid(*this).name()) + " : 0x" + FormatIntHex(this);
#else
String s = String(typeid(*this).name()) + " : " + Format("0x%x", (int) this);
#endif
if(IsChild())
s << "(parent " << String(typeid(*parent).name()) << ")";
return s;
}
END_UPP_NAMESPACE
#endif

View file

@ -0,0 +1,86 @@
//$ class Ctrl {
private:
static Ptr<Ctrl> desktop;
static Vector<Ctrl *> topctrl;
static ImageBuffer framebuffer;
static Vector<Rect> invalid, update;
static Point fbCursorPos;
static Image fbCursorImage;
static Point fbCursorBakPos;
static Image fbCursorBak;
static Rect fbCaretRect;
static Image fbCaretBak;
static int fbCaretTm;
static int renderingMode;
static bool fbEndSession;
static int64 fbEventLoop;
static int64 fbEndSessionLoop;
static Image GetBak(Rect& tr);
static void RemoveCursor();
static void RemoveCaret();
static void CursorSync();
int FindTopCtrl() const;
static Rect GetClipBound(const Vector<Rect>& inv, const Rect& r);
static void DoPaint();
static void DoUpdate();
static void SyncTopWindows();
static void AddInvalid(const Rect& rect);
void DestroyWnd();
void NewTop() { top = new Top; top->owner_window = NULL; }
void PutForeground();
static void MouseEventFB(Ptr<Ctrl> t, int event, Point p, int zdelta);
Vector<Rect> GetPaintRects();
static void DrawLine(const Vector<Rect>& clip, int x, int y, int cx, int cy, bool horz,
const byte *pattern, int animation);
static void DragRectDraw0(const Vector<Rect>& clip, const Rect& rect, int n,
const byte *pattern, int animation);
friend struct PaintProxy__;
friend class TopWindowFrame;
friend class SystemDraw;
friend struct DnDLoop;
void SetOpen(bool b) { isopen = b; }
protected:
static int PaintLock;
public:
static void DoMouseFB(int event, Point p, int zdelta = 0);
static bool DoKeyFB(dword key, int cnt);
static void InitFB();
static void ExitFB();
static void EndSession();
static void SetDesktop(Ctrl& q);
static Ctrl *GetDesktop() { return desktop; }
static void SetFramebufferSize(Size sz);
static const ImageBuffer& GetFrameBuffer() { return framebuffer; }
static void SetRenderingMode(int mode);
static void AddUpdate(const Rect& rect);
void DragRectDraw(const Rect& rect1, const Rect& rect2, const Rect& clip, int n,
Color color, int type, int animation);
static Ctrl *FindMouseTopCtrl();
static bool FullWindowDrag;
enum { DRAWDRAGRECT_SCREEN = 0x8000 };
//$ };

150
rainbow/Framebuffer/DnD.cpp Normal file
View file

@ -0,0 +1,150 @@
#include "Fb.h"
#ifdef GUI_FB
NAMESPACE_UPP
#define LLOG(x) // DLOG(x)
// --------------------------------------------------------------------------------------------
Ptr<Ctrl> sDnDSource;
Ctrl * Ctrl::GetDragAndDropSource()
{
return sDnDSource;
}
struct DnDLoop : LocalLoop {
const VectorMap<String, ClipData> *data;
Vector<String> fmts;
Image move, copy, reject;
Ptr<Ctrl> target;
int action;
byte actions;
void Sync();
String GetData(const String& f);
void DnD(bool paste);
virtual void LeftUp(Point, dword);
virtual bool Key(dword, int);
virtual void MouseMove(Point p, dword);
virtual Image CursorImage(Point, dword);
};
Ptr<DnDLoop> dndloop;
bool PasteClip::IsAvailable(const char *fmt) const
{
GuiLock __;
return dnd ? dndloop && FindIndex(dndloop->fmts, fmt) >= 0
: IsClipboardAvailable(fmt);
}
String DnDLoop::GetData(const String& f)
{
GuiLock __;
int i = data->Find(f);
String d;
if(i >= 0)
d = (*data)[i].Render();
else
if(sDnDSource)
d = sDnDSource->GetDropData(f);
return d;
}
String PasteClip::Get(const char *fmt) const
{
return dnd ? dndloop ? dndloop->GetData(fmt) : String() : ReadClipboard(fmt);
}
void PasteClip::GuiPlatformConstruct()
{
dnd = false;
}
void DnDLoop::DnD(bool paste)
{
PasteClip d;
d.paste = paste;
d.accepted = false;
d.allowed = (byte)actions;
d.action = GetCtrl() ? DND_COPY : DND_MOVE;
d.dnd = true;
if(target)
target->DnD(GetMousePos(), d);
action = d.IsAccepted() ? d.GetAction() : DND_NONE;
}
void DnDLoop::Sync()
{
GuiLock __;
Ptr<Ctrl> t = FindMouseTopCtrl();
if(t != target)
if(target)
target->DnDLeave();
target = t;
DnD(false);
}
void DnDLoop::LeftUp(Point, dword)
{
GuiLock __;
LLOG("DnDLoop::LeftUp");
DnD(true);
EndLoop();
}
void DnDLoop::MouseMove(Point p, dword)
{
GuiLock __;
LLOG("DnDLoop::MouseMove");
Sync();
}
bool DnDLoop::Key(dword, int)
{
GuiLock __;
LLOG("DnDLoop::Key");
Sync();
return false;
}
Image DnDLoop::CursorImage(Point, dword)
{
GuiLock __;
return action == DND_MOVE ? move : action == DND_COPY ? copy : reject;
}
int Ctrl::DoDragAndDrop(const char *fmts, const Image& sample, dword actions,
const VectorMap<String, ClipData>& data)
{
GuiLock __;
DnDLoop d;
d.actions = (byte)actions;
d.reject = actions & DND_EXACTIMAGE ? CtrlCoreImg::DndNone() : MakeDragImage(CtrlCoreImg::DndNone(), sample);
if(actions & DND_COPY)
d.copy = actions & DND_EXACTIMAGE ? sample : MakeDragImage(CtrlCoreImg::DndCopy(), sample);
if(actions & DND_MOVE)
d.move = actions & DND_EXACTIMAGE ? sample : MakeDragImage(CtrlCoreImg::DndMoveX11(), sample);
d.SetMaster(*this);
d.data = &data;
d.action = DND_NONE;
d.fmts = Split(fmts, ';');
dndloop = &d;
sDnDSource = this;
d.Run();
sDnDSource = NULL;
SyncCaret();
LLOG("DoDragAndDrop finished");
return d.action;
}
void Ctrl::SetSelectionSource(const char *fmts) {}
END_UPP_NAMESPACE
#endif

View file

@ -0,0 +1,105 @@
#include <CtrlCore/CtrlCore.h>
#ifdef GUI_FB
NAMESPACE_UPP
#define LLOG(x) // LOG(x)
#define LTIMING(x) // RTIMING(x)
SystemDraw::SystemDraw()
: BufferPainter(Ctrl::framebuffer, Ctrl::renderingMode)
{
}
SystemDraw::~SystemDraw()
{
}
void SystemDraw::Push()
{
Point p = GetOffset();
offset.Add(p);
BufferPainter::BeginOp();
}
void SystemDraw::Pop()
{
if(offset.GetCount())
offset.Drop();
BufferPainter::EndOp();
}
Point SystemDraw::GetOffset() const
{
return offset.GetCount() ? offset.Top() : Point(0, 0);
}
void SystemDraw::BeginOp()
{
Push();
}
void SystemDraw::EndOp()
{
Pop();
}
void SystemDraw::OffsetOp(Point p)
{
Push();
offset.Top() += p;
Translate(p.x, p.y);
}
bool SystemDraw::ClipOp(const Rect& r)
{
Push();
RectPath(r);
Painter::Clip();
return true;
}
bool SystemDraw::ClipoffOp(const Rect& r)
{
Push();
offset.Top() += r.TopLeft();
RectPath(r);
Painter::Clip();
Translate(r.left, r.top);
return true;
}
bool SystemDraw::IsPaintingOp(const Rect& r) const
{
Rect rr = r + GetOffset();
for(int i = 0; i < Ctrl::invalid.GetCount(); i++)
if(Ctrl::invalid[i].Intersects(rr))
return true;
return true;
}
/*Rect SystemDraw::GetVirtualScreenArea()
{
GuiLock __;
}*/
/*
void BackDraw::Destroy()
{
GuiLock __;
}
void BackDraw::Create(SystemDraw& w, int cx, int cy) {
GuiLock __;
}
void BackDraw::Put(SystemDraw& w, int x, int y) {
GuiLock __;
}
*/
END_UPP_NAMESPACE
#endif

View file

@ -0,0 +1,189 @@
#include "Fb.h"
#ifdef GUI_FB
NAMESPACE_UPP
#define LLOG(x) //DLOG(x)
#define LDUMP(x) //DDUMP(x)
static Point fbmousepos;
Point GetMousePos() {
return fbmousepos;
}
void Ctrl::MouseEventFB(Ptr<Ctrl> t, int event, Point p, int zdelta)
{
if(!t->IsEnabled())
return;
Rect rr = t->GetRect();
if((event & Ctrl::ACTION) == DOWN) {
Ptr<Ctrl> q = t;
TopWindowFrame *wf = dynamic_cast<TopWindowFrame *>(~t);
if(wf)
q = wf->window;
if(q) q->ClickActivateWnd();
if(q) q->SetForeground();
if(ignoreclick)
return;
}
if(t)
t->DispatchMouse(event, p - rr.TopLeft(), zdelta);
if(t)
t->PostInput();
}
Ctrl *Ctrl::FindMouseTopCtrl()
{
for(int i = topctrl.GetCount() - 1; i >= 0; i--) {
Ctrl *t = topctrl[i];
if(t->GetRect().Contains(fbmousepos))
return t->IsEnabled() ? t : NULL;
}
return desktop->IsEnabled() ? desktop : NULL;
}
void Ctrl::DoMouseFB(int event, Point p, int zdelta)
{
fbmousepos = p;
int a = event & Ctrl::ACTION;
if(a == Ctrl::UP && Ctrl::ignoreclick) {
EndIgnore();
return;
}
else
if(a == Ctrl::DOWN && ignoreclick)
return;
LLOG("### Mouse event: " << event << " position " << p << " zdelta " << zdelta << ", capture " << Upp::Name(captureCtrl));
if(captureCtrl)
MouseEventFB(captureCtrl->GetTopCtrl(), event, p, zdelta);
else
for(int i = topctrl.GetCount() - 1; i >= 0; i--) {
Ptr<Ctrl> t = topctrl[i];
Rect rr = t->GetRect();
if(rr.Contains(p)) {
MouseEventFB(t, event, p, zdelta);
return;
}
}
Ctrl *desktop = GetDesktop();
if(desktop) {
desktop->DispatchMouse(event, p, zdelta);
desktop->PostInput();
}
}
bool Ctrl::DoKeyFB(dword key, int cnt)
{
bool b = DispatchKey(key, cnt);
SyncCaret();
Ctrl *desktop = GetDesktop();
if(desktop)
desktop->PostInput();
return b;
}
Image Ctrl::GetBak(Rect& tr)
{
Image bak;
tr.Intersect(framebuffer.GetSize());
if(!tr.IsEmpty()) {
Image h = framebuffer;
bak = CreateImage(tr.GetSize(), Black);
Copy(bak, Point(0, 0), h, tr);
framebuffer = h;
}
return bak;
}
void Ctrl::RemoveCursor()
{
if(!IsNull(fbCursorBakPos)) {
Copy(framebuffer, fbCursorBakPos, fbCursorBak, fbCursorBak.GetSize());
AddUpdate(Rect(fbCursorBakPos, fbCursorBak.GetSize()));
}
fbCursorPos = fbCursorBakPos = Null;
fbCursorBak = Null;
}
void Ctrl::RemoveCaret()
{
if(!IsNull(fbCaretRect)) {
Copy(framebuffer, fbCaretRect.TopLeft(), fbCaretBak, fbCaretBak.GetSize());
AddUpdate(fbCaretRect);
}
fbCaretRect = Null;
fbCaretBak = Null;
}
void Ctrl::SetCaret(int x, int y, int cx, int cy)
{
GuiLock __;
caretx = x;
carety = y;
caretcx = cx;
caretcy = cy;
fbCaretTm = GetTickCount();
SyncCaret();
}
void Ctrl::SyncCaret()
{
GuiLock __;
}
void Ctrl::CursorSync()
{
LLOG("@ CursorSync");
Point p = GetMousePos() - fbCursorImage.GetHotSpot();
Rect cr = Null;
if(focusCtrl && (((GetTickCount() - fbCaretTm) / 500) & 1) == 0)
cr = (RectC(focusCtrl->caretx, focusCtrl->carety, focusCtrl->caretcx, focusCtrl->caretcy)
+ focusCtrl->GetScreenView().TopLeft()) & focusCtrl->GetScreenView();
LDUMP(GetTickCount());
if(fbCursorPos != p || cr != fbCaretRect) {
LDUMP(fbCaretRect);
RemoveCursor();
RemoveCaret();
fbCursorPos = p;
Size sz = fbCursorImage.GetSize();
Rect tr(p, sz);
fbCursorBak = GetBak(tr);
fbCursorBakPos = tr.TopLeft();
fbCaretRect = cr;
if(!cr.IsEmpty()) {
fbCaretBak = GetBak(cr);
for(int y = cr.top; y < cr.bottom; y++) {
RGBA *s = framebuffer[y] + cr.left;
const RGBA *e = framebuffer[y] + cr.right;
while(s < e) {
s->r = ~s->r;
s->g = ~s->g;
s->b = ~s->b;
s++;
}
}
AddUpdate(fbCaretRect);
}
Over(framebuffer, p, fbCursorImage, sz);
LLOG("Cursor: " << p << ", rect " << tr);
AddUpdate(tr);
}
}
void Ctrl::SetMouseCursor(const Image& image)
{
GuiLock __;
if(image.GetSerialId() != fbCursorImage.GetSerialId()) {
fbCursorImage = image;
fbCursorPos = Null;
}
}
END_UPP_NAMESPACE
#endif

View file

@ -0,0 +1,59 @@
PREMULTIPLIED
IMAGE_ID(arrow)
IMAGE_ID(ibeam)
IMAGE_ID(wait)
IMAGE_ID(no)
IMAGE_ID(sizeall)
IMAGE_ID(sizehorz)
IMAGE_ID(sizeright)
IMAGE_ID(sizeleft)
IMAGE_ID(sizevert)
IMAGE_ID(sizetopleft)
IMAGE_ID(sizetop)
IMAGE_ID(sizetopright)
IMAGE_ID(sizebottomleft)
IMAGE_ID(sizebottom)
IMAGE_ID(sizebottomright)
IMAGE_ID(overlap)
IMAGE_ID(maximize)
IMAGE_ID(close)
IMAGE_ID(bgtitle)
IMAGE_ID(title)
IMAGE_ID(border)
IMAGE_ID(hand)
IMAGE_BEGIN_DATA
IMAGE_DATA(120,156,237,90,205,75,84,81,20,191,101,163,6,74,72,180,115,209,166,77,127,66,4,109,91,6,22,4,209,38,23,209)
IMAGE_DATA(162,93,45,162,204,9,34,130,8,13,178,36,44,45,11,212,172,197,108,68,84,212,133,31,8,126,224,7,12,162,8,34)
IMAGE_DATA(136,136,160,43,221,157,238,140,51,227,245,188,251,206,61,231,206,27,43,120,231,113,208,247,238,239,119,238,57,191,115,222)
IMAGE_DATA(123,227,135,170,82,23,84,198,202,213,169,204,23,80,50,3,33,7,0,68,28,56,56,184,8,251,251,151,184,28,216,219)
IMAGE_DATA(187,2,187,187,215,96,103,231,58,135,3,219,219,55,96,107,235,38,108,110,222,129,245,245,122,23,7,54,54,234,53,238)
IMAGE_DATA(62,172,173,61,132,213,213,71,144,78,63,165,56,176,178,242,24,150,151,159,104,92,35,44,46,190,130,249,249,183,48,59)
IMAGE_DATA(219,28,198,129,165,165,151,176,176,240,26,230,230,154,96,102,166,21,166,166,58,97,114,242,59,76,76,180,219,56,26,211)
IMAGE_DATA(12,211,211,239,53,174,13,198,199,187,97,100,100,36,231,191,96,120,184,19,115,116,172,86,141,107,131,177,177,78,24,29)
IMAGE_DATA(253,93,192,171,163,94,154,28,141,249,172,189,3,134,134,126,192,224,224,79,232,239,79,145,245,14,12,180,67,95,223,215)
IMAGE_DATA(66,156,84,170,155,196,167,82,95,2,57,118,117,125,11,213,199,166,65,71,199,39,10,111,221,183,165,229,157,104,14,155)
IMAGE_DATA(154,222,136,103,61,153,124,46,218,163,161,225,153,120,15,1,54,104,9,117,78,157,86,21,89,87,168,241,42,123,179,30)
IMAGE_DATA(26,250,190,176,57,58,255,239,175,133,212,27,208,69,85,105,225,18,90,180,196,113,225,184,158,229,212,246,124,32,221,192)
IMAGE_DATA(158,4,158,228,88,176,161,28,2,27,224,48,176,5,142,4,235,147,139,79,173,62,90,254,133,254,202,230,179,70,31,149)
IMAGE_DATA(185,131,18,206,226,92,227,222,36,28,126,49,235,146,60,139,229,7,26,200,136,97,127,250,248,243,195,242,146,242,185,49)
IMAGE_DATA(36,235,174,61,56,57,82,117,82,230,210,88,194,183,229,36,153,21,219,53,95,62,55,142,207,125,231,115,223,186,98,217)
IMAGE_DATA(141,249,64,58,140,26,124,189,139,204,124,253,23,195,207,187,52,14,230,251,196,1,195,208,169,51,6,198,217,244,160,98)
IMAGE_DATA(133,225,57,215,204,235,56,111,91,45,24,139,249,62,110,139,227,147,71,84,122,68,213,23,91,44,91,45,46,46,222,31)
IMAGE_DATA(187,36,134,45,142,148,143,227,248,242,81,28,218,106,244,199,254,74,85,150,117,76,118,5,160,48,220,34,194,112,212,208)
IMAGE_DATA(218,76,169,147,191,121,56,121,68,165,135,185,238,213,151,184,209,113,163,253,2,50,19,118,225,138,21,216,188,230,227,182)
IMAGE_DATA(56,62,121,68,165,135,185,238,213,151,10,221,234,178,92,171,45,27,178,19,193,194,186,4,183,9,132,206,157,133,255,235)
IMAGE_DATA(107,84,125,148,46,148,158,156,92,140,245,35,171,214,71,121,238,8,100,130,68,39,2,146,73,185,56,46,124,177,28,44)
IMAGE_DATA(182,139,131,155,197,221,47,108,239,98,121,146,62,72,106,53,121,170,132,189,240,157,17,235,44,198,79,166,210,173,81,245)
IMAGE_DATA(81,186,80,122,114,114,49,214,143,204,124,50,81,22,200,18,53,132,216,236,68,159,66,92,14,22,223,197,161,26,201,197)
IMAGE_DATA(227,117,28,75,146,3,7,111,114,212,9,235,207,205,77,58,83,241,192,198,3,91,18,14,55,55,241,192,198,175,210,210)
IMAGE_DATA(173,81,245,81,186,80,122,114,114,49,214,143,44,254,144,31,228,224,102,113,247,11,219,187,88,158,164,15,146,90,77,158)
IMAGE_DATA(42,97,47,124,103,196,58,139,85,250,136,200,172,119,154,225,54,60,21,203,23,207,201,3,227,93,123,70,133,231,232,83)
IMAGE_DATA(42,93,204,107,146,62,241,45,130,97,114,37,39,17,203,134,137,241,209,227,37,253,226,91,20,79,166,171,213,213,161,155)
IMAGE_DATA(227,181,204,121,222,109,88,219,154,237,58,21,7,175,187,176,97,28,10,43,197,75,242,145,212,235,171,39,149,39,85,7)
IMAGE_DATA(105,103,244,145,183,186,186,86,184,253,160,23,238,190,232,133,123,31,123,65,122,94,8,86,150,253,219,76,18,206,94,238)
IMAGE_DATA(129,243,183,150,160,182,49,243,18,22,158,103,198,60,161,143,220,207,178,220,251,233,216,155,223,101,230,255,83,231,207,41)
IMAGE_DATA(79,38,147,49,190,68,248,252,185,203,125,102,33,59,76,142,95,140,80,159,94,48,14,210,233,244,177,175,97,88,140,51)
IMAGE_DATA(240,214,79,32,97,120,180,79,33,6,23,239,194,217,240,121,151,226,195,28,213,44,197,59,57,148,166,76,44,11,255,7)
IMAGE_DATA(113,204,146,74,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
IMAGE_END_DATA(1056, 22)

64
rainbow/Framebuffer/Fb.h Normal file
View file

@ -0,0 +1,64 @@
#ifndef _Framebuffer_Fb_h_
#define _Framebuffer_Fb_h_
#include <CtrlLib/CtrlLib.h>
NAMESPACE_UPP
class TopWindowFrame : public Ctrl {
public:
virtual void Layout();
virtual void Paint(Draw& w);
virtual Image CursorImage(Point p, dword keyflags);
virtual void LeftDown(Point p, dword keyflags);
virtual void LeftHold(Point p, dword keyflags);
virtual void LeftDouble(Point p, dword keyflags);
virtual void MouseMove(Point p, dword keyflags);
virtual void CancelMode();
virtual void LeftUp(Point p, dword keyflags);
private:
Point dir;
Point startpos;
Rect startrect;
bool maximized;
Rect overlapped;
bool holding;
TimeCallback hold;
Point GetDragMode(Point p);
Image GetDragImage(Point dragmode);
void StartDrag();
Rect Margins() const;
Rect ComputeClient(Rect r);
void Hold();
typedef TopWindowFrame CLASSNAME;
public:
String title;
Button close, maximize;
Image icon;
Size minsize;
bool sizeable;
TopWindow *window;
void SetTitle(const String& s) { title = s; Refresh(); }
Rect GetClient() const;
void SetClient(Rect r);
void GripResize();
void Maximize();
void Overlap();
void ToggleMaximize();
bool IsMaximized() const { return maximized; }
void SyncRect();
TopWindowFrame();
};
END_UPP_NAMESPACE
#endif

View file

@ -0,0 +1,141 @@
#define GUI_FB
#include <Painter/Painter.h>
NAMESPACE_UPP
#define IMAGECLASS FBImg
#define IMAGEFILE <Framebuffer/FB.iml>
#include <Draw/iml_header.h>
class SystemDraw : public BufferPainter {
public:
virtual void BeginOp();
virtual void EndOp();
virtual void OffsetOp(Point p);
virtual bool ClipOp(const Rect& r);
virtual bool ClipoffOp(const Rect& r);
virtual bool IsPaintingOp(const Rect& r) const;
private:
Vector<Point> offset;
void Push();
void Pop();
public:
Point GetOffset() const;
bool CanSetSurface() { return false; }
bool Clip(const Rect& r) { return Draw::Clip(r); }
bool Clip(int x, int y, int cx, int cy) { return Draw::Clip(x, y, cx, cy); }
static void Flush() {}
SystemDraw();
~SystemDraw();
};
struct BackDraw__ : public SystemDraw {
BackDraw__() : SystemDraw() {}
};
class BackDraw : public BackDraw__ { // Dummy only, as we are running in GlobalBackBuffer mode
Size size;
Draw *painting;
Point painting_offset;
ImageBuffer ib;
public:
virtual bool IsPaintingOp(const Rect& r) const;
public:
void Put(SystemDraw& w, int x, int y) {}
void Put(SystemDraw& w, Point p) { Put(w, p.x, p.y); }
void Create(SystemDraw& w, int cx, int cy) {}
void Create(SystemDraw& w, Size sz) { Create(w, sz.cx, sz.cy); }
void Destroy() {}
void SetPaintingDraw(Draw& w, Point off) { painting = &w; painting_offset = off; }
BackDraw();
~BackDraw();
};
struct ImageDraw__ {
ImageBuffer image;
ImageBuffer alpha;
ImageDraw__(int cx, int cy) : image(cx, cy), alpha(cx, cy) {}
};
class ImageDraw : private ImageDraw__, public BufferPainter {
BufferPainter alpha_painter;
bool has_alpha;
Image Get(bool pm) const;
public:
Draw& Alpha();
operator Image() const { return Get(true); }
Image GetStraight() const { return Get(false); }
ImageDraw(Size sz);
ImageDraw(int cx, int cy);
};
void DrawDragRect(SystemDraw& w, const Rect& rect1, const Rect& rect2, const Rect& clip, int n,
Color color, uint64 pattern);
class TopWindowFrame;
#define GUIPLATFORM_CTRL_TOP_DECLS Ctrl *owner_window;
#define GUIPLATFORM_CTRL_DECLS_INCLUDE <Framebuffer/Ctrl.h>
#define GUIPLATFORM_PASTECLIP_DECLS \
bool dnd; \
friend struct DnDLoop; \
#define GUIPLATFORM_TOPWINDOW_DECLS_INCLUDE <Framebuffer/Top.h>
// to be implemented by final FB {
bool FBIsWaitingEvent();
bool FBProcessEvent(bool *quit);
void FBSleep(int ms);
void FBInitUpdate();
void FBUpdate(const Rect& area);
void FBFlush();
void FBQuitSession();
// }
class PrinterJob { // Dummy only...
NilDraw nil;
Vector<int> pages;
public:
Draw& GetDraw() { return nil; }
operator Draw&() { return GetDraw(); }
const Vector<int>& GetPages() const { return pages; }
int operator[](int i) const { return 0; }
int GetPageCount() const { return 0; }
bool Execute() { return false; }
PrinterJob& Landscape(bool b = true) { return *this; }
PrinterJob& MinMaxPage(int minpage, int maxpage) { return *this; }
PrinterJob& PageCount(int n) { return *this; }
PrinterJob& CurrentPage(int currentpage) { return *this; }
PrinterJob& Name(const char *_name) { return *this; }
PrinterJob(const char *name = NULL) {}
~PrinterJob() {}
};
END_UPP_NAMESPACE
#define GUIPLATFORM_INCLUDE_AFTER <Framebuffer/After.h>

View file

@ -0,0 +1,25 @@
description "Generic framebuffer GUI rainbow\377";
uses
Painter,
CtrlLib;
file
Framebuffer.h,
After.h,
Fb.h,
Draw.cpp,
Image.cpp,
Util.cpp,
FB.iml,
Ctrl.h,
Ctrl.cpp,
Wnd.cpp,
Event.cpp,
Top.h,
TopFrame.cpp,
Top.cpp,
Clip.cpp,
DnD.cpp,
ChSysInit.cpp;

358
rainbow/Framebuffer/Gui.h Normal file
View file

@ -0,0 +1,358 @@
#define GUI_FB
NAMESPACE_UPP
class SystemDraw : public Draw {
public:
virtual dword GetInfo() const;
virtual Size GetPageSize() const;
virtual void BeginOp();
virtual void EndOp();
virtual void OffsetOp(Point p);
virtual bool ClipOp(const Rect& r);
virtual bool ClipoffOp(const Rect& r);
virtual bool ExcludeClipOp(const Rect& r);
virtual bool IntersectClipOp(const Rect& r);
virtual bool IsPaintingOp(const Rect& r) const;
virtual Rect GetPaintRect() const;
virtual void DrawRectOp(int x, int y, int cx, int cy, Color color);
virtual void DrawImageOp(int x, int y, int cx, int cy, const Image& img, const Rect& src, Color color);
virtual void DrawLineOp(int x1, int y1, int x2, int y2, int width, Color color);
virtual void DrawPolyPolylineOp(const Point *vertices, int vertex_count,
const int *counts, int count_count,
int width, Color color, Color doxor);
virtual void DrawPolyPolyPolygonOp(const Point *vertices, int vertex_count,
const int *subpolygon_counts, int scc,
const int *disjunct_polygon_counts, int dpcc,
Color color, int width, Color outline,
uint64 pattern, Color doxor);
virtual void DrawArcOp(const Rect& rc, Point start, Point end, int width, Color color);
virtual void DrawEllipseOp(const Rect& r, Color color, int pen, Color pencolor);
virtual void DrawTextOp(int x, int y, int angle, const wchar *text, Font font,
Color ink, int n, const int *dx);
virtual Size GetNativeDpi() const;
virtual void BeginNative();
virtual void EndNative();
virtual int GetCloffLevel() const;
private:
Size pageSize;
Size nativeSize;
Size nativeDpi;
bool palette:1;
bool color16:1;
bool is_mono:1;
int native;
friend class ImageDraw;
friend class FontInfo;
friend class Font;
friend void StaticExitDraw_();
Point actual_offset_bak;
struct Cloff : Moveable<Cloff> {
Point org;
HRGN hrgn;
Rect drawingclip;
};
Array<Cloff> cloff;
Rect drawingclip;
COLORREF lastTextColor;
Color lastColor;
HBRUSH orgBrush;
HBRUSH actBrush;
HPEN orgPen;
HPEN actPen;
int lastPen;
Color lastPenColor;
void Unselect0();
void Cinit();
void LoadCaps();
void SetPrinterMode();
void Reset();
void SetOrg();
friend HPALETTE GetQlibPalette();
void DotsMode();
static void InitColors();
friend class BackDraw;
friend class ScreenDraw;
friend class PrintDraw;
protected:
dword style;
HDC handle;
Point actual_offset;
SystemDraw();
void Init();
void InitClip(const Rect& clip);
public:
static Rect GetVirtualScreenArea();
static void SetAutoPalette(bool ap);
static bool AutoPalette();
bool PaletteMode() { return palette; }
static void Flush() { GdiFlush(); }
COLORREF GetColor(Color color) const;
Point GetOffset() const { return actual_offset; }
#ifndef PLATFORM_WINCE
Point LPtoDP(Point p) const;
Point DPtoLP(Point p) const;
Rect LPtoDP(const Rect& r) const;
Rect DPtoLP(const Rect& r) const;
#endif
void SetColor(Color color);
void SetDrawPen(int width, Color color);
Size GetSizeCaps(int i, int j) const;
HDC BeginGdi();
void EndGdi();
HDC GetHandle() { return handle; }
operator HDC() const { return handle; }
void Unselect();
void Attach(HDC ahandle) { handle = ahandle; Init(); }
HDC Detach() { Unselect(); HDC h = handle; handle = NULL; return h; }
SystemDraw(HDC hdc);
virtual ~SystemDraw();
bool CanSetSurface() { return IsGui() && IsWinNT(); }
};
#ifndef PLATFORM_WINCE
class WinMetaFile {
Size size;
HENHMETAFILE hemf;
void Init();
public:
void Attach(HENHMETAFILE emf);
HENHMETAFILE Detach();
void Set(const void *data, dword len);
void Set(const String& data) { Set(~data, data.GetCount()); }
String Get() const;
operator bool() const { return hemf; }
void SetSize(const Size& sz) { size = sz; }
Size GetSize() const { return hemf ? size : Size(0, 0); }
void Clear();
void Paint(Draw& w, const Rect& r) const;
void Paint(Draw& w, int x, int y, int cx, int cy) const;
void Serialize(Stream& s);
void ReadClipboard();
void WriteClipboard() const;
void Load(const char *file) { Set(LoadFile(file)); }
WinMetaFile() { Init(); }
WinMetaFile(HENHMETAFILE hemf);
WinMetaFile(HENHMETAFILE hemf, Size sz);
WinMetaFile(const char *file);
WinMetaFile(void *data, int len);
WinMetaFile(const String& data);
~WinMetaFile() { Clear(); }
HENHMETAFILE GetHEMF() const { return hemf; }
};
class WinMetaFileDraw : public SystemDraw {
Size size;
public:
bool Create(HDC hdc, int cx, int cy, const char *app = NULL, const char *name = NULL, const char *file = NULL);
bool Create(int cx, int cy, const char *app = NULL, const char *name = NULL, const char *file = NULL);
WinMetaFile Close();
WinMetaFileDraw() {}
WinMetaFileDraw(HDC hdc, int cx, int cy, const char *app = NULL, const char *name = NULL, const char *file = NULL);
WinMetaFileDraw(int cx, int cy, const char *app = NULL, const char *name = NULL, const char *file = NULL);
~WinMetaFileDraw();
};
void DrawWMF(Draw& w, int x, int y, int cx, int cy, const String& wmf);
void DrawWMF(Draw& w, int x, int y, const String& wmf);
Drawing LoadWMF(const char *path, int cx, int cy);
Drawing LoadWMF(const char *path);
String AsWMF(const Drawing& iw);
#endif
class ScreenDraw : public SystemDraw {
public:
ScreenDraw(bool ic = false);
~ScreenDraw();
};
#ifndef PLATFORM_WINCE
class PrintDraw : public SystemDraw {
public:
virtual void StartPage();
virtual void EndPage();
private:
bool aborted;
void InitPrinter();
public:
PrintDraw(HDC hdc, const char *jobname);
~PrintDraw();
};
#endif
inline bool BitBlt(HDC ddc, Point d, HDC sdc, const Rect& s, dword rop = SRCCOPY)
{ return BitBlt(ddc, d.x, d.y, s.Width(), s.Height(), sdc, s.left, s.top, rop); }
inline bool StretchBlt(HDC ddc, const Rect& r, HDC sdc, const Rect& s, dword rop = SRCCOPY)
{ return StretchBlt(ddc, r.left, r.top, r.Width(), r.Height(), sdc, s.left, s.top, s.Width(), s.Height(), rop); }
inline bool PatBlt(HDC dc, const Rect& r, dword rop = PATCOPY)
{ return PatBlt(dc, r.left, r.top, r.Width(), r.Height(), rop); }
inline void MoveTo(HDC hdc, Point pt) { MoveToEx(hdc, pt.x, pt.y, 0); }
inline void LineTo(HDC hdc, Point pt) { LineTo(hdc, pt.x, pt.y); }
inline void DrawLine(HDC hdc, Point p, Point q) { MoveTo(hdc, p); LineTo(hdc, q); }
inline void DrawLine(HDC hdc, int px, int py, int qx, int qy) { MoveToEx(hdc, px, py, 0); LineTo(hdc, qx, qy); }
#ifndef PLATFORM_WINCE
inline void DrawArc(HDC hdc, const Rect& rc, Point p, Point q){ Arc(hdc, rc.left, rc.top, rc.right, rc.bottom, p.x, p.y, q.x, q.y); }
#endif
inline void DrawCircle(HDC hdc, int x, int y, int radius) { Ellipse(hdc, x - radius, y - radius, x + radius + 1, y + radius + 1); }
inline void DrawCircle(HDC hdc, Point centre, int radius) { DrawCircle(hdc, centre.x, centre.y, radius); }
inline void DrawEllipse(HDC hdc, const Rect& rc) { Ellipse(hdc, rc.left, rc.top, rc.right, rc.bottom); }
inline void DrawRect(HDC hdc, const Rect& rc) { Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom); }
HDC ScreenHDC();
HPALETTE GetQlibPalette();
Image Win32Icon(LPCSTR id, int iconsize = 0);
Image Win32Icon(int id, int iconsize = 0);
Image Win32Cursor(LPCSTR id);
Image Win32Cursor(int id);
HICON IconWin32(const Image& img, bool cursor = false);
Image Win32DllIcon(const char *dll, int ii, bool large);
class BackDraw : public SystemDraw {
public:
virtual bool IsPaintingOp(const Rect& r) const;
protected:
HBITMAP hbmpold;
HBITMAP hbmp;
Size size;
Draw *painting;
Point painting_offset;
public:
void Put(SystemDraw& w, int x, int y);
void Put(SystemDraw& w, Point p) { Put(w, p.x, p.y); }
void Create(SystemDraw& w, int cx, int cy);
void Create(SystemDraw& w, Size sz) { Create(w, sz.cx, sz.cy); }
void Destroy();
void SetPaintingDraw(Draw& w, Point off) { painting = &w; painting_offset = off; }
BackDraw();
~BackDraw();
};
class ImageDraw : public SystemDraw {
Size size;
struct Section {
HDC dc;
HBITMAP hbmp, hbmpOld;
RGBA *pixels;
void Init(int cx, int cy);
~Section();
};
Section rgb;
Section a;
SystemDraw alpha;
bool has_alpha;
void Init();
Image Get(bool pm) const;
public:
Draw& Alpha();
operator Image() const;
Image GetStraight() const;
ImageDraw(Size sz);
ImageDraw(int cx, int cy);
~ImageDraw();
};
END_UPP_NAMESPACE
#define GUIPLATFORM_KEYCODES_INCLUDE "Win32Keys.h"
#define GUIPLATFORM_CTRL_TOP_DECLS \
HWND hwnd; \
UDropTarget *dndtgt; \
#define GUIPLATFORM_CTRL_DECLS_INCLUDE "Win32Ctrl.h"
#define GUIPLATFORM_PASTECLIP_DECLS \
UDropTarget *dt; \
#define GUIPLATFORM_TOPWINDOW_DECLS_INCLUDE "Win32Top.h"
NAMESPACE_UPP
inline unsigned GetHashValue(const HWND& hwnd)
{
return (unsigned)(intptr_t)hwnd;
}
END_UPP_NAMESPACE
#ifdef PLATFORM_WIN32
#ifndef PLATFORM_WINCE
#include <ShellAPI.h>
#endif
#endif
#define GUIPLATFORM_INCLUDE_AFTER "Win32GuiA.h"

View file

@ -0,0 +1,92 @@
#include <CtrlCore/CtrlCore.h>
#ifdef GUI_FB
NAMESPACE_UPP
#define LTIMING(x) // RTIMING(x)
void SetSurface(SystemDraw& w, int x, int y, int cx, int cy, const RGBA *pixels)
{
GuiLock __;
// Empty as CanSetSurface is false
}
void SetSurface(SystemDraw& w, const Rect& dest, const RGBA *pixels, Size psz, Point poff)
{
GuiLock __;
// Empty as CanSetSurface is false
}
Image ImageDraw::Get(bool pm) const
{
ImageBuffer result(image.GetSize());
const RGBA *e = image.End();
const RGBA *p = ~image;
RGBA *t = ~result;
if(has_alpha) {
const RGBA *a = ~alpha;
while(p < e) {
*t = *p++;
(t++)->a = (a++)->r;
}
if(pm)
Premultiply(result);
result.SetKind(IMAGE_ALPHA);
}
else {
while(p < e) {
*t = *p++;
(t++)->a = 255;
}
}
return result;
}
Draw& ImageDraw::Alpha()
{
has_alpha = true;
return alpha_painter;
}
ImageDraw::ImageDraw(Size sz)
: ImageDraw__(sz.cx, sz.cy),
BufferPainter(image),
alpha_painter(alpha)
{
has_alpha = false;
}
ImageDraw::ImageDraw(int cx, int cy)
: ImageDraw__(cx, cy),
BufferPainter(image),
alpha_painter(alpha)
{
has_alpha = false;
}
#define IMAGECLASS FBImg
#define IMAGEFILE <Framebuffer/FB.iml>
#include <Draw/iml_source.h>
Image Image::Arrow() { return FBImg::arrow(); }
Image Image::Wait() { return FBImg::wait(); }
Image Image::IBeam() { return FBImg::ibeam(); }
Image Image::No() { return FBImg::no(); }
Image Image::SizeAll() { return FBImg::sizeall(); }
Image Image::SizeHorz() { return FBImg::sizehorz(); }
Image Image::SizeVert() { return FBImg::sizevert(); }
Image Image::SizeTopLeft() { return FBImg::sizetopleft(); }
Image Image::SizeTop() { return FBImg::sizetop(); }
Image Image::SizeTopRight() { return FBImg::sizetopright(); }
Image Image::SizeLeft() { return FBImg::sizeleft(); }
Image Image::SizeRight() { return FBImg::sizeright(); }
Image Image::SizeBottomLeft() { return FBImg::sizebottomleft(); }
Image Image::SizeBottom() { return FBImg::sizebottom(); }
Image Image::SizeBottomRight() { return FBImg::sizebottomright(); }
Image Image::Hand() { return FBImg::hand(); }
END_UPP_NAMESPACE
#endif

150
rainbow/Framebuffer/Top.cpp Normal file
View file

@ -0,0 +1,150 @@
#include "Fb.h"
#ifdef GUI_FB
NAMESPACE_UPP
#define LLOG(x) // LOG(x)
void TopWindow::SyncFrameRect(const Rect& r)
{
frame->SetClient(r);
}
void TopWindow::DestroyFrame()
{
if(frame->IsOpen())
frame->DestroyWnd();
}
void TopWindow::GripResize()
{
frame->GripResize();
}
void TopWindow::SyncSizeHints()
{
SyncCaption();
}
void TopWindow::SyncTitle()
{
SyncCaption();
}
void TopWindow::SyncCaption()
{
GuiLock __;
frame->title = title.ToString();
frame->minsize = minsize;
frame->close.Show(!noclosebox);
frame->maximize.Show(maximizebox);
frame->sizeable = sizeable;
frame->RefreshLayout();
frame->Refresh();
frame->close <<= Proxy(WhenClose);
frame->icon = icon;
frame->Enable(IsEnabled());
}
void TopWindow::State(int reason)
{
SyncCaption();
}
void TopWindow::SyncRect()
{
frame->SyncRect();
Rect r = frame->GetClient();
if(r != GetRect()) {
SetRect(r);
}
}
void TopWindow::Open(Ctrl *owner)
{
GuiLock __;
LLOG("Open " << Upp::Name(owner));
Rect r = GetRect();
if(r.IsEmpty())
SetRect(GetDefaultWindowRect());
else
if(r.left == 0 && r.top == 0)
if(owner && center == 1)
SetRect(owner->GetRect().CenterRect(r.GetSize()));
else
if(center)
SetRect(GetWorkArea().CenterRect(r.GetSize()));
frame->SetClient(GetRect());
frame->window = this;
frame->PopUp(owner, false, true);
PopUp(frame, false, true);
popup = false;
SetRect(frame->GetClient());
SyncCaption();
if(state == MAXIMIZED)
frame->Maximize();
}
void TopWindow::Open()
{
Open(GetActiveCtrl());
}
void TopWindow::OpenMain()
{
Open(NULL);
}
void TopWindow::Minimize(bool effect)
{
// state = MINIMIZED;
}
TopWindow& TopWindow::FullScreen(bool b)
{
return *this;
}
void TopWindow::Maximize(bool effect)
{
state = MAXIMIZED;
frame->Maximize();
}
void TopWindow::Overlap(bool effect)
{
GuiLock __;
state = OVERLAPPED;
frame->Overlap();
}
TopWindow& TopWindow::TopMost(bool b, bool stay_top)
{
GuiLock __;
return *this;
}
bool TopWindow::IsTopMost() const
{
return true;
}
void TopWindow::GuiPlatformConstruct()
{
frame = new TopWindowFrame;
}
void TopWindow::GuiPlatformDestruct()
{
delete frame;
}
void TopWindow::SerializePlacement(Stream& s, bool reminimize)
{
GuiLock __;
}
END_UPP_NAMESPACE
#endif

16
rainbow/Framebuffer/Top.h Normal file
View file

@ -0,0 +1,16 @@
//$ class TopWindow {
public:
virtual void State(int reason);
private:
TopWindowFrame *frame;
void SyncRect();
void SyncFrameRect(const Rect& r);
void DestroyFrame();
friend class Ctrl;
public:
void GripResize();
//$ };

View file

@ -0,0 +1,259 @@
#include "Fb.h"
#ifdef GUI_FB
NAMESPACE_UPP
#define LLOG(x) // LOG(x)
#define LDUMP(x) //DDUMP(x)
TopWindowFrame::TopWindowFrame()
{
close.SetImage(FBImg::close());
close.EdgeStyle();
Add(close);
maximize.SetImage(FBImg::maximize());
maximize.EdgeStyle();
Add(maximize);
maximize <<= THISBACK(ToggleMaximize);
maximized = false;
sizeable = false;
holding = false;
}
void TopWindowFrame::SyncRect()
{
if(maximized) {
Size sz = framebuffer.GetSize();
if(GetRect().GetSize() != sz)
SetRect(sz);
}
}
void TopWindowFrame::Maximize()
{
if(!maximized && maximize.IsShown()) {
maximized = true;
overlapped = GetRect();
SetRect(framebuffer.GetSize());
maximize.SetImage(FBImg::overlap());
}
}
void TopWindowFrame::Overlap()
{
if(maximized && maximize.IsShown()) {
maximized = false;
SetRect(overlapped);
maximize.SetImage(FBImg::maximize());
}
}
void TopWindowFrame::ToggleMaximize()
{
if(maximized)
Overlap();
else
Maximize();
}
Rect TopWindowFrame::Margins() const
{
return maximized ? Rect(0, 0, 0, 0) : ChMargins(FBImg::border());
}
void TopWindowFrame::Paint(Draw& w)
{
Size sz = GetSize();
Rect m = Margins();
int c = GetStdFontCy() + 4;
ChPaintEdge(w, sz, FBImg::border());
ChPaint(w, m.left, m.top, sz.cx - m.left - m.right, GetStdFontCy() + 4,
window->IsForeground() ? FBImg::title() : FBImg::bgtitle());
int tx = m.left + 2;
int tcx = sz.cx - m.left - m.right - 4 - c * (close.IsShown() + maximize.IsShown());
if(!IsNull(icon)) {
Image h = icon;
if(h.GetWidth() > c || h.GetHeight() > c)
h = Rescale(h, GetFitSize(h.GetSize(), Size(c)));
w.DrawImage(tx, m.top + 2, h);
tx += c;
tcx -= c;
}
DrawTextEllipsis(w, tx, m.top + 2, tcx, title, "..", StdFont(), SColorHighlightText());
}
void TopWindowFrame::Layout()
{
Size sz = GetSize();
Rect m = Margins();
int c = GetStdFontCy() + 4;
int x = sz.cx - m.right;
if(close.IsShown())
close.SetRect(x -= c, m.top, c, c);
if(maximize.IsShown())
maximize.SetRect(x -= c, m.top, c, c);
}
Rect TopWindowFrame::GetClient() const
{
Rect r = GetRect();
Rect m = Margins();
r.left += m.left;
r.right -= m.right;
r.top += m.top;
r.bottom -= m.bottom;
r.top += GetStdFontCy() + 4;
return r;
}
Rect TopWindowFrame::ComputeClient(Rect r)
{
Rect m = Margins();
r.left -= m.left;
r.right += m.right;
r.top -= m.top;
r.bottom += m.bottom;
r.top -= GetStdFontCy() + 4;
return r;
}
void TopWindowFrame::SetClient(Rect r)
{
SetRect(ComputeClient(r));
}
Point TopWindowFrame::GetDragMode(Point p)
{
Size sz = GetSize();
Rect m = ChMargins(FBImg::border());
Point dir;
dir.y = p.y < m.top ? -1 : p.y > sz.cy - m.top ? 1 : 0;
dir.x = p.x < m.left ? -1 : p.x > sz.cx - m.right ? 1 : 0;
return dir;
}
void TopWindowFrame::StartDrag()
{
if(maximized)
return;
if(!sizeable && (dir.x || dir.y))
return;
if(FullWindowDrag) {
SetCapture();
startrect = GetRect();
startpos = GetMousePos();
}
else {
Rect r = GetScreenRect();
RectTracker tr(*this);
tr.SetCursorImage(GetDragImage(dir))
.MaxRect(framebuffer.GetSize())
.MinSize(ComputeClient(minsize).GetSize())
.Pattern(DRAWDRAGRECT_DASHED | DRAWDRAGRECT_SCREEN)
.Width(2)
.Animation();
PaintLock++;
r = tr.Track(r, dir.x < 0 ? ALIGN_LEFT : dir.x > 0 ? ALIGN_RIGHT : ALIGN_CENTER,
dir.y < 0 ? ALIGN_TOP : dir.y > 0 ? ALIGN_BOTTOM : ALIGN_CENTER);
PaintLock--;
SetRect(r);
}
LLOG("START DRAG ---------------");
}
void TopWindowFrame::GripResize()
{
dir = Point(1, 1);
StartDrag();
}
void TopWindowFrame::LeftDown(Point p, dword keyflags)
{
dir = GetDragMode(p);
if(dir.x || dir.y || FullWindowDrag)
StartDrag();
else {
SetCapture();
holding = true;
hold.Set(GetKbdDelay() / 3, THISBACK(Hold));
}
}
void TopWindowFrame::CancelMode()
{
holding = false;
}
void TopWindowFrame::LeftUp(Point p, dword keyflags)
{
holding = false;
}
void TopWindowFrame::Hold()
{
if(HasCapture()) {
if(HasMouse() && GetMouseLeft() && holding)
StartDrag();
ReleaseCapture();
holding = false;
}
}
void TopWindowFrame::LeftHold(Point p, dword keyflags)
{
if(HasCapture() || FullWindowDrag)
return;
dir = GetDragMode(p);
if(!dir.x && !dir.y)
StartDrag();
}
void TopWindowFrame::LeftDouble(Point p, dword keyflags)
{
ToggleMaximize();
IgnoreMouseUp();
}
void TopWindowFrame::MouseMove(Point, dword)
{
LDUMP(HasWndCapture());
LDUMP(HasCapture());
if(!HasCapture() || holding)
return;
Size msz = ComputeClient(minsize).GetSize();
Point p = GetMousePos() - startpos;
Rect r = startrect;
if(dir.x == -1)
r.left = min(r.left + p.x, startrect.right - msz.cx);
if(dir.x == 1)
r.right = max(r.right + p.x, startrect.left + msz.cx);
if(dir.y == -1)
r.top = min(r.top + p.y, startrect.bottom - msz.cy);
if(dir.y == 1)
r.bottom = max(r.bottom + p.y, startrect.top + msz.cy);
if(dir.y == 0 && dir.x == 0)
r.Offset(p);
SetRect(r);
}
Image TopWindowFrame::GetDragImage(Point dir)
{
static Image (*im[9])() = {
Image::SizeTopLeft, Image::SizeLeft, Image::SizeBottomLeft,
Image::SizeTop, Image::Arrow, Image::SizeBottom,
Image::SizeTopRight, Image::SizeRight, Image::SizeBottomRight,
};
return (*im[(dir.x + 1) * 3 + (dir.y + 1)])();
}
Image TopWindowFrame::CursorImage(Point p, dword)
{
if(!sizeable)
return Image::Arrow();
return GetDragImage(HasCapture() ? dir : GetDragMode(p));
}
END_UPP_NAMESPACE
#endif

View file

@ -0,0 +1,75 @@
#include <CtrlCore/CtrlCore.h>
#ifdef GUI_FB
NAMESPACE_UPP
/*
static void sRenderLine(SystemDraw& w, int x, int y, int dx, int dy, int cx, int cy, int len, byte pattern)
{
DLOG(len);
for(int i = 0; i < len; i++)
if((128 >> (i & 7)) & pattern)
w.DrawRect(x + dx * i, y + dy * i, cx, cy, Black);
DDUMP("~sRenderLine");
}
static void sRenderRect(SystemDraw& w, const Rect& r, int n, byte pattern)
{
sRenderLine(w, r.left, r.top, 1, 0, 1, n, r.GetWidth(), pattern);
sRenderLine(w, r.left, r.bottom - 1, 1, 0, 1, n, r.GetWidth(), pattern);
sRenderLine(w, r.left, r.top, 0, 1, n, 1, r.GetHeight(), pattern);
sRenderLine(w, r.right - 1, r.top, 0, 1, n, 1, r.GetHeight(), pattern);
}
void DrawDragRect(SystemDraw& w, const Rect& rect1, const Rect& rect2,
const Rect& clip, int n, Color color, uint64 pattern)
{
DLOG("@ DrawDragRect " << rect1 << " " << rect2 << ", clip: " << clip << ", pattern: " << pattern);
TIMING("DrawDrawRect");
w.Clip(clip);
w.Invert();
sRenderRect(w, rect1, n, (byte)pattern);
sRenderRect(w, rect2, n, (byte)pattern);
Ctrl::AddUpdate((rect1 | rect2).Offseted(w.GetOffset()));
// MemoryProfile mem;
// DDUMP(mem);
w.End();
}
static uint64 sGetAniPat(uint64 src, int pos)
{
uint64 out = 0;
pos &= 7;
for(int i = 8; --i >= 0;) {
byte sr = (byte)(src >> (8 * ((7 - i - pos) & 7)));
out = (out << 8) | (byte)((sr | (sr << 8)) >> pos);
}
return out;
}
*/
/*
Size GetScreenSize()
{
return ScreenInfo().GetPageSize();
}
*/
void DrawDragRect(Ctrl& q, const Rect& rect1, const Rect& rect2, const Rect& clip, int n,
Color color, int type, int animation)
{
q.DragRectDraw(rect1, rect2, clip, n, color, type, animation);
}
void FinishDragRect(Ctrl& q)
{
}
END_UPP_NAMESPACE
#endif

766
rainbow/Framebuffer/Wnd.cpp Normal file
View file

@ -0,0 +1,766 @@
#include "Fb.h"
#ifdef GUI_FB
NAMESPACE_UPP
#define LLOG(x) //DLOG(x)
#define LDUMP(x) //DDUMP(x)
#define LDUMPC(x) //DDUMPC(x)
ImageBuffer Ctrl::framebuffer;
Vector<Rect> Ctrl::invalid;
Vector<Rect> Ctrl::update;
Ptr<Ctrl> Ctrl::desktop;
Vector<Ctrl *> Ctrl::topctrl;
Point Ctrl::fbCursorPos = Null;
Image Ctrl::fbCursorImage;
Point Ctrl::fbCursorBakPos = Null;
Image Ctrl::fbCursorBak;
Rect Ctrl::fbCaretRect;
Image Ctrl::fbCaretBak;
int Ctrl::fbCaretTm;
int Ctrl::renderingMode = MODE_ANTIALIASED;
bool Ctrl::fbEndSession;
bool Ctrl::FullWindowDrag;
int Ctrl::PaintLock;
void Ctrl::SetDesktop(Ctrl& q)
{
desktop = &q;
desktop->SetRect(framebuffer.GetSize());
desktop->SetOpen(true);
desktop->NewTop();
invalid.Add(framebuffer.GetSize());
}
void Ctrl::SetRenderingMode(int mode)
{
renderingMode = mode;
invalid.Add(framebuffer.GetSize());
}
void Ctrl::InitFB()
{
Ctrl::GlobalBackBuffer();
Ctrl::InitTimer();
framebuffer.Create(1, 1);
#ifdef PLATFORM_POSIX
SetStdFont(ScreenSans(12)); //FIXME general handling
#endif
ChStdSkin();
static StaticRect x;
x.Color(Cyan());
SetDesktop(x);
}
void Ctrl::EndSession()
{
GuiLock __;
LLOG("Ctrl::EndSession");
fbEndSession = true;
EndSessionLoopNo = EventLoopNo;
}
void Ctrl::ExitFB()
{
TopWindow::ShutdownWindows();
Ctrl::CloseTopCtrls();
if(fbEndSession)
FBQuitSession();
}
void Ctrl::SetFramebufferSize(Size sz)
{
framebuffer.Create(sz);
if(desktop)
desktop->SetRect(sz);
invalid.Add(sz);
SyncTopWindows();
}
int Ctrl::FindTopCtrl() const
{
for(int i = 0; i < topctrl.GetCount(); i++)
if(this == topctrl[i])
return i;
return -1;
}
bool Ctrl::IsAlphaSupported()
{
return false;
}
bool Ctrl::IsCompositedGui()
{
return false;
}
Vector<Ctrl *> Ctrl::GetTopCtrls()
{
Vector<Ctrl *> ctrl;
if(desktop)
ctrl.Add(desktop);
for(int i = 0; i < topctrl.GetCount(); i++)
if(!dynamic_cast<TopWindowFrame *>(topctrl[i]))
ctrl.Add(topctrl[i]);
return ctrl;
}
Ctrl *Ctrl::GetOwner()
{
GuiLock __;
int q = FindTopCtrl();
if(q > 0 && topctrl[q]->top) {
Ctrl *x = topctrl[q]->top->owner_window;
LDUMP(Upp::Name(x));
return dynamic_cast<TopWindowFrame *>(x) ? x->GetOwner() : x;
}
return NULL;
}
Ctrl *Ctrl::GetActiveCtrl()
{
GuiLock __;
return focusCtrl ? focusCtrl->GetTopCtrl() : NULL;
}
// Vector<Callback> Ctrl::hotkey;
int Ctrl::RegisterSystemHotKey(dword key, Callback cb)
{
/* ASSERT(key >= K_DELTA);
int q = hotkey.GetCount();
for(int i = 0; i < hotkey.GetCount(); i++)
if(!hotkey[i]) {
q = i;
break;
}
hotkey.At(q) = cb;
dword mod = 0;
if(key & K_ALT)
mod |= MOD_ALT;
if(key & K_SHIFT)
mod |= MOD_SHIFT;
if(key & K_CTRL)
mod |= MOD_CONTROL;
return RegisterHotKey(NULL, q, mod, key & 0xffff) ? q : -1;*/
return -1;
}
void Ctrl::UnregisterSystemHotKey(int id)
{
/* if(id >= 0 && id < hotkey.GetCount()) {
UnregisterHotKey(NULL, id);
hotkey[id].Clear();
}*/
}
bool Ctrl::IsWaitingEvent()
{
return FBIsWaitingEvent();
}
void Ctrl::AddUpdate(const Rect& rect)
{
LLOG("@AddUpdate " << rect);
AddRefreshRect(update, rect);
}
void Ctrl::AddInvalid(const Rect& rect)
{
LLOG("@AddInvalid " << rect);
AddRefreshRect(invalid, rect);
}
void Ctrl::SyncTopWindows()
{
for(int i = 0; i < topctrl.GetCount(); i++) {
TopWindow *w = dynamic_cast<TopWindow *>(topctrl[i]);
if(w)
w->SyncRect();
}
}
bool Ctrl::ProcessEvent(bool *quit)
{
LLOG("@ ProcessEvent");
ASSERT(IsMainThread());
if(!GetMouseLeft() && !GetMouseRight() && !GetMouseMiddle())
ReleaseCtrlCapture();
if(FBProcessEvent(quit)) {
LLOG("FBProcesEvent returned true");
SyncTopWindows();
DefferedFocusSync();
SyncCaret();
return true;
}
return false;
}
Rect Ctrl::GetClipBound(const Vector<Rect>& inv, const Rect& r)
{
Rect ri = Null;
for(int j = 0; j < inv.GetCount(); j++) {
Rect rr = inv[j] & r;
if(!rr.IsEmpty())
ri = IsNull(ri) ? rr : rr | ri;
}
return ri;
}
ViewDraw::ViewDraw(Ctrl *ctrl)
{
if(Ctrl::invalid.GetCount())
Ctrl::DoPaint();
Ctrl::invalid.Clear();
Ctrl::RemoveCursor();
Ctrl::RemoveCaret();
Rect r = ctrl->GetScreenView();
Ctrl::invalid.Add(r);
Ctrl::AddUpdate(r);
for(int i = max(ctrl->GetTopCtrl()->FindTopCtrl() + 1, 0); i < Ctrl::topctrl.GetCount(); i++) {
Rect rr = Ctrl::topctrl[i]->GetScreenRect();
ExcludeClip(rr);
Subtract(Ctrl::invalid, rr);
}
Offset(r.TopLeft());
}
ViewDraw::~ViewDraw()
{
FBInitUpdate();
Ctrl::DoUpdate();
FBFlush();
// Ctrl::invalid.Clear();
}
void Ctrl::DoUpdate()
{
LLOG("DoUpdate");
invalid.Clear();
CursorSync();
LDUMPC(update);
#if 0
FBUpdate(framebuffer.GetSize());
#else
for(int i = 0; i < update.GetCount(); i++) {
LDUMP(update[i]);
FBUpdate(update[i]);
}
#endif
update.Clear();
// Sleep(1000);
}
Vector<Rect> Ctrl::GetPaintRects()
{
Vector<Rect> r;
r.Add(GetScreenRect());
for(int i = max(FindTopCtrl() + 1, 0); i < topctrl.GetCount(); i++)
Subtract(r, topctrl[i]->GetScreenRect());
return r;
}
void DDRect(RGBA *t, int dir, const byte *pattern, int pos, int count)
{
while(count-- > 0) {
byte p = pattern[7 & pos++];
t->r ^= p;
t->g ^= p;
t->b ^= p;
t += dir;
}
}
void Ctrl::DrawLine(const Vector<Rect>& clip, int x, int y, int cx, int cy, bool horz, const byte *pattern, int animation)
{
if(cx <= 0 || cy <= 0)
return;
Vector<Rect> rr = Intersection(clip, RectC(x, y, cx, cy));
for(int i = 0; i < rr.GetCount(); i++) {
Rect r = rr[i];
AddUpdate(r);
if(horz)
for(int y = r.top; y < r.bottom; y++)
DDRect(framebuffer[y] + r.left, 1, pattern, r.left + animation, r.GetWidth());
else
for(int x = r.left; x < r.right; x++)
DDRect(framebuffer[r.top] + x, framebuffer.GetWidth(), pattern, r.top + animation, r.GetHeight());
}
}
void Ctrl::DragRectDraw0(const Vector<Rect>& clip, const Rect& rect, int n, const byte *pattern, int animation)
{
int hn = min(rect.GetHeight(), n);
int vn = min(rect.GetWidth(), n);
DrawLine(clip, rect.left, rect.top, rect.GetWidth(), hn, true, pattern, animation);
DrawLine(clip, rect.left, rect.top + hn, vn, rect.GetHeight() - hn, false, pattern, animation);
DrawLine(clip, rect.right - vn, rect.top + hn, vn, rect.GetHeight() - hn, false, pattern, animation);
DrawLine(clip, rect.left + vn, rect.bottom - hn, rect.GetWidth() - 2 * vn, hn, true, pattern, animation);
}
void Ctrl::DragRectDraw(const Rect& rect1, const Rect& rect2, const Rect& clip, int n,
Color color, int type, int animation)
{
static byte solid[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
static byte normal[] = { 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00 };
static byte dashed[] = { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 };
Point p = GetScreenView().TopLeft();
Vector<Rect> pr;
if(type & DRAWDRAGRECT_SCREEN) {
pr.Add(Rect(framebuffer.GetSize()));
type &= ~DRAWDRAGRECT_SCREEN;
p = Point(0, 0);
}
else
pr = Intersection(GetPaintRects(), clip.Offseted(p));
const byte *pattern = type == DRAWDRAGRECT_DASHED ? dashed :
type == DRAWDRAGRECT_NORMAL ? normal : solid;
RemoveCursor();
RemoveCaret();
DragRectDraw0(pr, rect1.Offseted(p), n, pattern, animation);
DragRectDraw0(pr, rect2.Offseted(p), n, pattern, animation);
}
void Ctrl::DoPaint()
{
LLOG("@ DoPaint");
if(!PaintLock) {
bool scroll = false;
if(desktop)
desktop->SyncScroll();
for(int i = 0; i < topctrl.GetCount(); i++)
topctrl[i]->SyncScroll();
if((invalid.GetCount() || scroll) && desktop) {
RemoveCursor();
RemoveCaret();
for(int phase = 0; phase < 2; phase++) {
LLOG("DoPaint invalid phase " << phase);
LDUMPC(invalid);
SystemDraw painter;
painter.Begin();
for(int i = 0; i < invalid.GetCount(); i++) {
painter.RectPath(invalid[i]);
AddUpdate(invalid[i]);
}
painter.Painter::Clip();
for(int i = topctrl.GetCount() - 1; i >= 0; i--) {
Rect r = topctrl[i]->GetRect();
Rect ri = GetClipBound(invalid, r);
if(!IsNull(ri)) {
painter.Clipoff(r);
topctrl[i]->UpdateArea(painter, ri - r.TopLeft());
painter.End();
Subtract(invalid, r);
painter.ExcludeClip(r);
}
}
Rect ri = GetClipBound(invalid, framebuffer.GetSize());
if(!IsNull(ri))
desktop->UpdateArea(painter, ri);
}
}
}
DoUpdate();
}
void Ctrl::WndUpdate(const Rect& r)
{
GuiLock __;
Rect rr = r + GetRect().TopLeft();
bool dummy;
Vector<Rect> h;
h <<= invalid;
invalid = Intersect(invalid, rr, dummy);
FBInitUpdate();
DoPaint();
invalid <<= h;
Subtract(invalid, rr);
FBFlush();
}
bool Ctrl::ProcessEvents(bool *quit)
{
//LOGBLOCK("@ ProcessEvents");
// MemoryCheckDebug();
if(!ProcessEvent(quit))
return false;
while(ProcessEvent(quit) && (!LoopCtrl || LoopCtrl->InLoop()));
TimeStop tm;
TimerProc(GetTickCount());
LLOG("TimerProc elapsed: " << tm);
SweepMkImageCache();
FBInitUpdate();
DoPaint();
FBFlush();
return true;
}
void Ctrl::EventLoop(Ctrl *ctrl)
{
GuiLock __;
ASSERT(IsMainThread());
ASSERT(LoopLevel == 0 || ctrl);
LoopLevel++;
LLOG("Entering event loop at level " << LoopLevel << LOG_BEGIN);
Ptr<Ctrl> ploop;
if(ctrl) {
ploop = LoopCtrl;
LoopCtrl = ctrl;
ctrl->inloop = true;
}
bool quit = false;
int64 loopno = ++EventLoopNo;
ProcessEvents(&quit);
while(loopno > EndSessionLoopNo && !quit && (ctrl ? ctrl->IsOpen() && ctrl->InLoop() : GetTopCtrls().GetCount()))
{
// LLOG(GetSysTime() << " % " << (unsigned)msecs() % 10000 << ": EventLoop / GuiSleep");
SyncCaret();
GuiSleep(20);
// LLOG(GetSysTime() << " % " << (unsigned)msecs() % 10000 << ": EventLoop / ProcessEvents");
ProcessEvents(&quit);
// LLOG(GetSysTime() << " % " << (unsigned)msecs() % 10000 << ": EventLoop / after ProcessEvents");
LDUMP(loopno);
LDUMP(fbEndSessionLoop);
}
if(ctrl)
LoopCtrl = ploop;
LoopLevel--;
LLOG(LOG_END << "Leaving event loop ");
}
void Ctrl::GuiSleep(int ms)
{
GuiLock __;
ASSERT(IsMainThread());
LLOG("GuiSleep");
int level = LeaveGuiMutexAll();
FBSleep(ms);
EnterGuiMutex(level);
}
Rect Ctrl::GetWndScreenRect() const
{
GuiLock __;
return GetRect();
}
void Ctrl::WndShow(bool b)
{
GuiLock __;
}
void Ctrl::WndUpdate()
{
GuiLock __;
}
bool Ctrl::IsWndOpen() const {
GuiLock __;
return FindTopCtrl() >= 0 || this == desktop;
}
void Ctrl::SetAlpha(byte alpha)
{
GuiLock __;
}
Rect Ctrl::GetWorkArea() const
{
GuiLock __;
return framebuffer.GetSize();
}
void Ctrl::GetWorkArea(Array<Rect>& rc)
{
GuiLock __;
Array<Rect> r;
r.Add(framebuffer.GetSize());
}
Rect Ctrl::GetVirtualWorkArea()
{
return framebuffer.GetSize();
}
Rect Ctrl::GetWorkArea(Point pt)
{
return framebuffer.GetSize();
}
Rect Ctrl::GetVirtualScreenArea()
{
GuiLock __;
return framebuffer.GetSize();
}
Rect Ctrl::GetPrimaryWorkArea()
{
Rect r;
return framebuffer.GetSize();
}
Rect Ctrl::GetPrimaryScreenArea()
{
return framebuffer.GetSize();
}
int Ctrl::GetKbdDelay()
{
GuiLock __;
return 500;
}
int Ctrl::GetKbdSpeed()
{
GuiLock __;
return 1000 / 32;
}
void Ctrl::DestroyWnd()
{
for(int i = 0; i < topctrl.GetCount(); i++)
if(topctrl[i]->top && topctrl[i]->top->owner_window == this)
topctrl[i]->WndDestroy();
int q = FindTopCtrl();
if(q >= 0) {
AddInvalid(GetRect());
topctrl.Remove(q);
}
if(top) {
delete top;
top = NULL;
}
isopen = false;
TopWindow *win = dynamic_cast<TopWindow *>(this);
if(win)
win->DestroyFrame();
}
void Ctrl::WndDestroy()
{
DestroyWnd();
if(topctrl.GetCount())
topctrl.Top()->ActivateWnd();
}
void Ctrl::PutForeground()
{
int q = FindTopCtrl();
if(q >= 0) {
AddInvalid(GetRect());
topctrl.Remove(q);
topctrl.Add(this);
}
Vector< Ptr<Ctrl> > fw;
for(int i = 0; i < topctrl.GetCount(); i++)
if(topctrl[i] && topctrl[i]->top && topctrl[i]->top->owner_window == this && topctrl[i] != this)
fw.Add(topctrl[i]);
for(int i = 0; i < fw.GetCount(); i++)
if(fw[i])
fw[i]->PutForeground();
}
void Ctrl::SetWndForeground()
{
GuiLock __;
ASSERT(IsOpen());
if(IsWndForeground())
return;
Ctrl *to = this;
while(to->top && to->top->owner_window)
to = to->top->owner_window;
to->PutForeground();
if(this != focusCtrl)
ActivateWnd();
}
bool Ctrl::IsWndForeground() const
{
GuiLock __;
bool b = false;
for(int i = 0; i < topctrl.GetCount(); i++) {
const TopWindow *tw = dynamic_cast<const TopWindow *>(topctrl[i]);
if(tw)
b = tw == this;
}
return b;
}
void Ctrl::WndEnable(bool b)
{
GuiLock __;
}
bool Ctrl::SetWndFocus()
{
GuiLock __;
return true;
}
bool Ctrl::HasWndFocus() const
{
GuiLock __;
return focusCtrl && focusCtrl->GetTopCtrl() == this;
}
bool Ctrl::SetWndCapture()
{
GuiLock __;
ASSERT(IsMainThread());
return true;
}
bool Ctrl::ReleaseWndCapture()
{
GuiLock __;
ASSERT(IsMainThread());
return true;
}
bool Ctrl::HasWndCapture() const
{
GuiLock __;
return captureCtrl && captureCtrl->GetTopCtrl() == this;
}
void Ctrl::WndInvalidateRect(const Rect& r)
{
GuiLock __;
int q = FindTopCtrl();
if(q >= 0)
AddInvalid(r + topctrl[q]->GetRect().TopLeft());
else
AddInvalid(r);
}
void Ctrl::WndSetPos(const Rect& rect)
{
GuiLock __;
TopWindow *w = dynamic_cast<TopWindow *>(this);
if(w)
w->SyncFrameRect(rect);
invalid.Add(GetRect());
SetWndRect(rect);
invalid.Add(rect);
}
void Ctrl::WndScrollView(const Rect& r, int dx, int dy)
{
GuiLock __;
if(dx == 0 && dy == 0)
return;
if(dx && dy) {
Refresh(r);
return;
}
RemoveCursor();
RemoveCaret();
Rect sr = r.Offseted(GetScreenRect().TopLeft());
Vector<Rect> pr = Intersection(GetPaintRects(), sr);
for(int i = 0; i < pr.GetCount(); i++) {
Rect r = pr[i];
if(dx) {
int n = r.GetWidth() - abs(dx);
if(n > 0) {
int to = r.left + dx * (dx > 0);
int from = r.left - dx * (dx < 0);
for(int y = r.top; y < r.bottom; y++)
memmove(framebuffer[y] + to, framebuffer[y] + from, n * sizeof(RGBA));
}
n = min(abs(dx), r.GetWidth());
Refresh(dx < 0 ? r.left : r.right - n, r.top, n, r.GetHeight());
}
else {
int n = r.GetHeight() - abs(dy);
for(int y = 0; y < n; y++)
memmove(framebuffer[dy < 0 ? r.top + y : r.bottom - 1 - y] + r.left,
framebuffer[dy < 0 ? r.top + y - dy : r.bottom - 1 - y - dy] + r.left,
r.GetWidth() * sizeof(RGBA));
n = min(abs(dy), r.GetHeight());
Refresh(r.left, dy < 0 ? r.bottom - n : r.top, r.GetWidth(), n);
}
}
Vector<Rect> ur;
for(int i = 0; i < invalid.GetCount(); i++)
if(invalid[i].Intersects(sr))
ur.Add(invalid[i]);
for(int i = 0; i < ur.GetCount(); i++)
AddInvalid(ur[i].Offseted(dx, dy));
}
void Ctrl::PopUp(Ctrl *owner, bool savebits, bool activate, bool dropshadow, bool topmost)
{
ASSERT(!IsChild() && !IsOpen() && FindTopCtrl() < 0);
NewTop();
if(owner) {
Ctrl *owner_window = owner->GetTopWindow();
if(!owner_window)
owner_window = owner->GetTopCtrl();
ASSERT(owner_window->IsOpen());
if(owner_window != desktop) {
owner_window->SetForeground();
top->owner_window = owner_window;
}
}
topctrl.Add(this);
popup = isopen = true;
RefreshLayoutDeep();
if(activate) SetFocusWnd();
AddInvalid(GetRect());
}
Rect Ctrl::GetDefaultWindowRect() {
GuiLock __;
static int ii = 0;
Size sz = framebuffer.GetSize();
Rect rect = framebuffer.GetSize();
rect.Deflate(sz / 10);
rect.Offset(Size(GetStdFontCy(), 2 * GetStdFontCy()) * (++ii % 8));
return rect;
}
Vector<WString> SplitCmdLine__(const char *cmd)
{
Vector<WString> out;
while(*cmd)
if((byte)*cmd <= ' ')
cmd++;
else if(*cmd == '\"') {
WString quoted;
while(*++cmd && (*cmd != '\"' || *++cmd == '\"'))
quoted.Cat(FromSystemCharset(String(cmd, 1)).ToWString());
out.Add(quoted);
}
else {
const char *begin = cmd;
while((byte)*cmd > ' ')
cmd++;
out.Add(String(begin, cmd).ToWString());
}
return out;
}
void Ctrl::InstallPanicBox()
{
}
void Ctrl::SysEndLoop()
{
}
END_UPP_NAMESPACE
#endif

5
rainbow/Framebuffer/init Normal file
View file

@ -0,0 +1,5 @@
#ifndef _Framebuffer_icpp_init_stub
#define _Framebuffer_icpp_init_stub
#include "Painter/init"
#include "CtrlLib/init"
#endif

62
rainbow/Gtk/GdkImage.cpp Normal file
View file

@ -0,0 +1,62 @@
#include <CtrlCore/CtrlCore.h>
#ifdef GUI_GTK
NAMESPACE_UPP
void ImageGdk::Free()
{
if(pixbuf) {
g_object_unref(pixbuf);
pixbuf = NULL;
}
}
bool ImageGdk::Set(const Image& m)
{
Free();
if(m.GetSerialId() != img.GetSerialId()) {
img = Unmultiply(m);
if(!IsNull(img)) {
Size sz = img.GetSize();
pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, sz.cx, sz.cy);
byte *l = (byte *)gdk_pixbuf_get_pixels(pixbuf);
int stride = gdk_pixbuf_get_rowstride(pixbuf);
for(int y = 0; y < sz.cy; y++) {
const RGBA *s = img[y];
const RGBA *e = s + sz.cx;
byte *t = l;
while(s < e) {
*t++ = s->r;
*t++ = s->g;
*t++ = s->b;
*t++ = s->a;
s++;
}
l += stride;
}
}
return true;
}
return false;
}
ImageGdk::ImageGdk(const Image& m)
{
pixbuf = NULL;
Set(m);
}
ImageGdk::ImageGdk()
{
pixbuf = NULL;
}
ImageGdk::~ImageGdk()
{
Free();
}
END_UPP_NAMESPACE
#endif

174
rainbow/Gtk/Gtk.h Normal file
View file

@ -0,0 +1,174 @@
#define GUI_GTK
#define PLATFORM_X11 // To keep legacy code happy
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
NAMESPACE_UPP
class SystemDraw : public Draw {
virtual dword GetInfo() const;
virtual void BeginOp();
virtual void EndOp();
virtual void OffsetOp(Point p);
virtual bool ClipOp(const Rect& r);
virtual bool ClipoffOp(const Rect& r);
virtual bool ExcludeClipOp(const Rect& r);
virtual bool IntersectClipOp(const Rect& r);
virtual bool IsPaintingOp(const Rect& r) const;
virtual Rect GetPaintRect() const;
virtual void DrawRectOp(int x, int y, int cx, int cy, Color color);
virtual void SysDrawImageOp(int x, int y, const Image& img, Color color);
virtual void DrawLineOp(int x1, int y1, int x2, int y2, int width, Color color);
virtual void DrawPolyPolylineOp(const Point *vertices, int vertex_count,
const int *counts, int count_count,
int width, Color color, Color doxor);
virtual void DrawPolyPolyPolygonOp(const Point *vertices, int vertex_count,
const int *subpolygon_counts, int scc,
const int *disjunct_polygon_counts, int dpcc,
Color color, int width, Color outline,
uint64 pattern, Color doxor);
virtual void DrawArcOp(const Rect& rc, Point start, Point end, int width, Color color);
virtual void DrawEllipseOp(const Rect& r, Color color, int pen, Color pencolor);
virtual void DrawTextOp(int x, int y, int angle, const wchar *text, Font font,
Color ink, int n, const int *dx);
private:
void RectPath(const Rect& r);
void Push();
void Pop();
Vector<Point> offset;
cairo_t *cr;
SystemDraw() {}
friend class ImageDraw;
friend class BackDraw;
friend class ViewDraw;
public:
void SetColor(Color c);
operator cairo_t*() { return cr; }
Point GetOffset() const;
bool CanSetSurface() { return false; } // TODO?
static void Flush() {} // TODO?
SystemDraw(cairo_t *cr) : cr(cr) {}
};
class ImageDraw : public SystemDraw {
cairo_surface_t *surface;
Size isz;
SystemDraw alpha;
cairo_surface_t *alpha_surface;
bool del;
void Init(Size sz);
void FetchStraight(ImageBuffer& b) const;
public:
Draw& Alpha();
operator Image() const;
Image GetStraight() const;
ImageDraw(Size sz);
ImageDraw(int cx, int cy);
~ImageDraw();
ImageDraw(cairo_t *cr, Size sz); // Special variant for chameleon skinning
};
class BackDraw : public SystemDraw {
Size size;
Draw *painting;
Point painting_offset;
public:
virtual bool IsPaintingOp(const Rect& r) const;
public:
void Put(SystemDraw& w, int x, int y);
void Put(SystemDraw& w, Point p) { Put(w, p.x, p.y); }
void Create(SystemDraw& w, int cx, int cy);
void Create(SystemDraw& w, Size sz) { Create(w, sz.cx, sz.cy); }
void Destroy();
void SetPaintingDraw(Draw& w, Point off) { painting = &w; painting_offset = off; }
BackDraw();
~BackDraw();
};
struct GdkRect : GdkRectangle {
operator GdkRectangle *() { return this; }
GdkRect(const Rect& r);
};
class ImageGdk {
GdkPixbuf *pixbuf;
Image img;
void Free();
public:
operator GdkPixbuf *() { return pixbuf; }
bool Set(const Image& m);
ImageGdk();
ImageGdk(const Image& m);
~ImageGdk();
};
Image ImageFromPixbufUnref(GdkPixbuf *pixbuf);
GdkAtom GAtom(const String& id);
struct DrawDragRectInfo {
Rect rect1, rect2, clip;
int n;
Color color;
int type;
int animation;
};
#ifndef PLATFORM_WIN32
#include <CtrlCore/stdids.h>
#endif
#define GUIPLATFORM_KEYCODES_INCLUDE <Gtk/GtkKeys.h>
//$ struct Ctrl::Top {
#define GUIPLATFORM_CTRL_TOP_DECLS \
GtkWidget *window; \
GtkIMContext *im_context; \
int64 cursor_id; \
One<DrawDragRectInfo> dr; \
int id; \
//$ }
#define GUIPLATFORM_CTRL_DECLS_INCLUDE <Gtk/GtkCtrl.h>
#define GUIPLATFORM_PASTECLIP_DECLS \
int type; \
#define GUIPLATFORM_TOPWINDOW_DECLS_INCLUDE <Gtk/GtkTop.h>
#define GUIPLATFORM_NOSCROLL
int rmsecs();
END_UPP_NAMESPACE
#define GUIPLATFORM_INCLUDE_AFTER <Gtk/GtkAfter.h>

23
rainbow/Gtk/Gtk.upp Normal file
View file

@ -0,0 +1,23 @@
description "Gtk backend\377";
file
Gtk.h,
GtkAfter.h,
GtkKeys.h,
GtkDrawOp.cpp,
GtkDrawText.cpp,
GtkDrawImage.cpp,
GtkUtil.cpp,
GdkImage.cpp,
GtkCtrl.h,
GtkCtrl.cpp,
GtkWnd.cpp,
GtkCreate.cpp,
GtkCapture.cpp,
GtkEvent.cpp,
GtkApp.cpp,
GtkTop.h,
GtkTop.cpp,
GtkClip.cpp,
GtkDnD.cpp;

25
rainbow/Gtk/GtkAfter.h Normal file
View file

@ -0,0 +1,25 @@
class ViewDraw : public SystemDraw {
public:
ViewDraw(Ctrl *ctrl);
~ViewDraw();
};
void DrawDragRect(Ctrl& q, const DrawDragRectInfo& f);
class DHCtrl : Ctrl {};
void InitGtkApp(int argc, char **argv, const char **envptr);
#define GUI_APP_MAIN \
void GuiMainFn_(); \
\
int main(int argc, char **argv, const char **envptr) { \
UPP::AppInit__(argc, (const char **)argv, envptr); \
UPP::InitGtkApp(argc, argv, envptr); \
GuiMainFn_(); \
UPP::Ctrl::CloseTopCtrls(); \
UPP::AppExit__(); \
return UPP::GetExitCode(); \
} \
\
void GuiMainFn_()

43
rainbow/Gtk/GtkApp.cpp Normal file
View file

@ -0,0 +1,43 @@
#include <CtrlCore/CtrlCore.h>
#ifdef GUI_GTK
NAMESPACE_UPP
#define LLOG(x) // DLOG(x)
void _DBG_Ungrab(void)
{
gdk_pointer_ungrab(GDK_CURRENT_TIME);
}
void Ctrl::PanicMsgBox(const char *title, const char *text)
{
LLOG("PanicMsgBox " << title << ": " << text);
_DBG_Ungrab();
GtkWidget *dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE, "%s: %s", title, text);
gtk_dialog_run(GTK_DIALOG (dialog));
gtk_widget_destroy(dialog);
__BREAK__;
}
void InitGtkApp(int argc, char **argv, const char **envptr)
{
gtk_init(&argc, &argv); // TODO?
Ctrl::GlobalBackBuffer();
Ctrl::ReSkin();
g_timeout_add(20, (GSourceFunc) Ctrl::TimeHandler, NULL);
InstallPanicMessageBox(Ctrl::PanicMsgBox);
}
/*
void ChSysInit()
{
CtrlImg::Reset();
CtrlsImg::Reset();
ChReset();
}
*/
END_UPP_NAMESPACE
#endif

View file

@ -0,0 +1,77 @@
#include <CtrlCore/CtrlCore.h>
#ifdef GUI_GTK
NAMESPACE_UPP
#define LLOG(x) // DLOG(x)
Ptr<Ctrl> Ctrl::grabwindow;
Ptr<Ctrl> Ctrl::grabpopup;
void Ctrl::StopGrabPopup()
{
if(grabpopup && gdk_pointer_is_grabbed()) {
gdk_pointer_ungrab(CurrentTime);
grabpopup = NULL;
}
}
void Ctrl::StartGrabPopup()
{
if(activePopup.GetCount() && !grabpopup) {
Ctrl *w = activePopup[0];
if(w) {
ReleaseWndCapture0();
if(gdk_pointer_grab(w->gdk(), FALSE,
GdkEventMask(GDK_BUTTON_RELEASE_MASK|GDK_BUTTON_PRESS_MASK|GDK_POINTER_MOTION_MASK),
NULL, NULL, CurrentTime) == GDK_GRAB_SUCCESS)
grabpopup = w;
}
}
}
bool Ctrl::SetWndCapture()
{
GuiLock __;
ASSERT(IsMainThread());
LLOG("SetWndCapture " << Name());
StopGrabPopup();
ReleaseWndCapture();
if(gdk_pointer_grab(gdk(), FALSE,
GdkEventMask(GDK_BUTTON_RELEASE_MASK|GDK_BUTTON_PRESS_MASK|GDK_POINTER_MOTION_MASK),
NULL, NULL, CurrentTime) == GDK_GRAB_SUCCESS) {
grabwindow = this;
return true;
}
return false;
}
bool Ctrl::ReleaseWndCapture0()
{
GuiLock __;
ASSERT(IsMainThread());
LLOG("ReleaseWndCapture");
if(grabwindow) {
gdk_pointer_ungrab(CurrentTime);
grabwindow = NULL;
StartGrabPopup();
return true;
}
return false;
}
bool Ctrl::ReleaseWndCapture()
{
return ReleaseWndCapture0();
}
bool Ctrl::HasWndCapture() const
{
GuiLock __;
return this == grabwindow && gdk_pointer_is_grabbed();
}
END_UPP_NAMESPACE
#endif

376
rainbow/Gtk/GtkClip.cpp Normal file
View file

@ -0,0 +1,376 @@
#include <CtrlCore/CtrlCore.h>
#include <plugin/bmp/bmp.h>
#ifdef GUI_GTK
NAMESPACE_UPP
#define LLOG(x) // DLOG(x)
void Ctrl::GtkSelectionDataSet(GtkSelectionData *selection_data, const String& fmt, const String& data)
{
if(fmt == "text") {
String s = data;
gtk_selection_data_set_text(selection_data, (const gchar*)~s, s.GetCount());
}
else
if(fmt == "image") {
Image img;
if(IsString(data))
LoadFromString(img, data);
if(!IsNull(img)) {
ImageGdk m(img);
gtk_selection_data_set_pixbuf(selection_data, m);
}
}
else {
String s = data;
gtk_selection_data_set(selection_data, GAtom(fmt), 8, (const guchar*)~s, s.GetCount());
}
}
void Ctrl::GtkGetClipData(GtkClipboard *clipboard, GtkSelectionData *selection_data,
guint info, gpointer user_data)
{
ArrayMap<String, ClipData>& target = *(ArrayMap<String, ClipData> *)user_data;
LLOG("GtkGetClipData for " << target.GetKey(info));
GtkSelectionDataSet(selection_data, target.GetKey(info), target[info].Render());
}
void ClearClipData(GtkClipboard *clipboard, gpointer) {}
Ctrl::Gclipboard::Gclipboard(GdkAtom type)
{
clipboard = gtk_clipboard_get(type);
}
void Ctrl::AddFmt(GtkTargetList *list, const String& fmt, int info)
{
if(fmt == "text")
gtk_target_list_add_text_targets(list, info);
else
if(fmt == "image")
gtk_target_list_add_image_targets(list, info, TRUE);
else
gtk_target_list_add(list, GAtom(fmt), 0, info);
}
GtkTargetList *Ctrl::CreateTargetList(const VectorMap<String, ClipData>& target)
{
GtkTargetList *list = gtk_target_list_new(NULL, 0);
for(int i = 0; i < target.GetCount(); i++)
AddFmt(list, target.GetKey(i), i);
return list;
}
void Ctrl::Gclipboard::Put(const String& fmt, const ClipData& data)
{
GuiLock __;
LLOG("Gclipboard::Put " << fmt);
target.GetAdd(fmt) = data;
GtkTargetList *list = CreateTargetList(target);
gint n;
GtkTargetEntry *targets = gtk_target_table_new_from_list(list, &n);
gtk_clipboard_set_with_data(clipboard, targets, n, GtkGetClipData, ClearClipData, &target);
gtk_clipboard_set_can_store(clipboard, NULL, 0);
gtk_target_table_free(targets, n);
gtk_target_list_unref(list);
}
String Ctrl::GtkDataGet(GtkSelectionData *s)
{
if(!s)
return Null;
const guchar *b = gtk_selection_data_get_data(s);
int n = gtk_selection_data_get_length(s);
return n >= 0 && b ? String(b, n) : String();
}
String Ctrl::Gclipboard::Get(const String& fmt)
{
if(fmt == "text") {
gchar *s = gtk_clipboard_wait_for_text(clipboard);
if(s) {
String h = s;
g_free(s);
return h;
}
return Null;
}
else
if(fmt == "image") {
Image img = ImageFromPixbufUnref(gtk_clipboard_wait_for_image(clipboard));
return StoreAsString(img); // Not very optimal...
}
else
return GtkDataGet(gtk_clipboard_wait_for_contents(clipboard, GAtom(fmt)));
}
bool Ctrl::Gclipboard::IsAvailable(const String& fmt)
{
if(fmt == "text")
return gtk_clipboard_wait_is_text_available(clipboard);
if(fmt == "image")
return gtk_clipboard_wait_is_image_available(clipboard);
return gtk_clipboard_wait_is_target_available(clipboard, GAtom(fmt));
}
bool PasteClip::IsAvailable(const char *fmt) const
{
LLOG("PasteClip::IsAvailable " << fmt << ", type: " << type);
if(type == 1)
return Ctrl::IsDragAvailable(fmt);
return (type == 0 ? Ctrl::gclipboard() : Ctrl::gselection()).IsAvailable(fmt);
}
String PasteClip::Get(const char *fmt) const
{
LLOG("PasteClip::Get " << fmt << ", type: " << type);
if(type == 1)
return Ctrl::DragGet(fmt);
return (type == 0 ? Ctrl::gclipboard() : Ctrl::gselection()).Get(fmt);
}
void PasteClip::GuiPlatformConstruct()
{
type = 0;
}
void Ctrl::Gclipboard::Clear()
{
gtk_clipboard_clear(clipboard);
target.Clear();
}
void ClearClipboard()
{
Ctrl::gclipboard().Clear();
}
Ctrl::Gclipboard& Ctrl::gclipboard()
{
GuiLock __;
static Gclipboard c(GDK_SELECTION_CLIPBOARD);
return c;
}
Ctrl::Gclipboard& Ctrl::gselection()
{
GuiLock __;
static Gclipboard c(GDK_SELECTION_PRIMARY);
return c;
}
void AppendClipboard(const char *format, const Value& data, String (*render)(const Value& data))
{
GuiLock __;
LLOG("AppendClipboard " << format);
Vector<String> s = Split(format, ';');
for(int i = 0; i < s.GetCount(); i++)
Ctrl::gclipboard().Put(s[i], ClipData(data, render));
}
void AppendClipboard(const char *format, const byte *data, int length)
{
GuiLock __;
AppendClipboard(format, String(data, length));
}
void AppendClipboard(const char *format, const String& data)
{
GuiLock __;
LLOG("AppendClipboard " << format);
Vector<String> s = Split(format, ';');
for(int i = 0; i < s.GetCount(); i++)
Ctrl::gclipboard().Put(s[i], ClipData(data));
}
String ReadClipboard(const char *format)
{
GuiLock __;
return Null;
}
const char *ClipFmtsText()
{
GuiLock __;
return "text";
}
void AppendClipboardUnicodeText(const WString& s)
{
AppendClipboard(ClipFmtsText(), Value(ToUtf8(s)), NULL);
}
void AppendClipboardText(const String& s)
{
AppendClipboard(ClipFmtsText(), Value(ToCharset(CHARSET_UTF8, s)), NULL);
}
String GetString(PasteClip& clip)
{
GuiLock __;
if(clip.IsAvailable("text"))
return ToCharset(CHARSET_DEFAULT, clip.Get("text"), CHARSET_UTF8);
return Null;
}
WString GetWString(PasteClip& clip)
{
GuiLock __;
if(clip.IsAvailable("text"))
return FromUtf8(clip.Get("text"));
return Null;
}
bool AcceptText(PasteClip& clip)
{
return clip.Accept(ClipFmtsText());
}
static String sText(const Value& data)
{
return data;
}
void Append(VectorMap<String, ClipData>& data, const String& text)
{
data.GetAdd("text", ClipData(ToCharset(CHARSET_UTF8, text), sText));
}
void Append(VectorMap<String, ClipData>& data, const WString& text)
{
data.GetAdd("text", ClipData(ToUtf8(text), sText));
}
String GetTextClip(const WString& text, const String& fmt)
{
if(fmt == "text")
return ToUtf8(text);
return Null;
}
String GetTextClip(const String& text, const String& fmt)
{
if(fmt == "text")
return ToCharset(CHARSET_UTF8, text);
return Null;
}
String ReadClipboardText()
{
return ToCharset(CHARSET_DEFAULT, Ctrl::gclipboard().Get("text"), CHARSET_UTF8);
}
WString ReadClipboardUnicodeText()
{
return FromUtf8(Ctrl::gclipboard().Get("text"));
}
bool IsClipboardAvailable(const char *id)
{
return Ctrl::gclipboard().IsAvailable(id);
}
bool IsClipboardAvailableText()
{
return Ctrl::gclipboard().IsAvailable("text");
}
const char *ClipFmtsImage()
{
return "image";
}
bool AcceptImage(PasteClip& clip)
{
GuiLock __;
return clip.Accept("image");
}
Image GetImage(PasteClip& clip)
{
GuiLock __;
Image m;
LoadFromString(m, clip.Get("image"));
return m;
}
Image ReadClipboardImage()
{
GuiLock __;
Image m;
LoadFromString(m, Ctrl::gclipboard().Get("image"));
return m;
}
String GetImageClip(const Image& m, const String& fmt)
{
Image h = m;
if(fmt == "image")
return StoreAsString(h);
return Null;
}
void AppendClipboardImage(const Image& img)
{
GuiLock __;
if(img.IsEmpty()) return;
Image h = img;
AppendClipboard("image", StoreAsString(h));
}
bool AcceptFiles(PasteClip& clip)
{
if(clip.Accept("files")) {
clip.SetAction(DND_COPY);
return true;
}
return false;
}
bool IsAvailableFiles(PasteClip& clip)
{
return clip.IsAvailable("files");
}
// TODO:
Vector<String> GetFiles(PasteClip& clip)
{
GuiLock __;
Vector<String> f;
return f;
}
Ptr<Ctrl> Ctrl::sel_ctrl;
void Ctrl::GuiPlatformSelection(PasteClip& d)
{
d.fmt.Clear();
d.type = 2;
}
String Ctrl::RenderPrimarySelection(const Value& fmt)
{
return sel_ctrl->GetSelectionData(fmt);
}
void Ctrl::SetSelectionSource(const char *fmts)
{
GuiLock __;
LLOG("SetSelectionSource " << UPP::Name(this) << ": " << fmts);
Vector<String> s = Split(fmts, ';');
sel_ctrl = this;
for(int i = 0; i < s.GetCount(); i++)
gselection().Put(s[i], ClipData(s[i], RenderPrimarySelection));
}
END_UPP_NAMESPACE
#endif

119
rainbow/Gtk/GtkCreate.cpp Normal file
View file

@ -0,0 +1,119 @@
#include <CtrlCore/CtrlCore.h>
#ifdef GUI_GTK
NAMESPACE_UPP
#define LLOG(x) // DLOG(x)
void Ctrl::Create(Ctrl *owner, bool popup)
{
GuiLock __;
ASSERT(IsMainThread());
LLOG("Create " << Name() << " " << GetRect());
ASSERT(!IsChild() && !IsOpen());
LLOG("Ungrab1");
top = new Top;
top->window = gtk_window_new(popup ? GTK_WINDOW_POPUP : GTK_WINDOW_TOPLEVEL);
top->owner = owner;
static int id;
top->id = ++id;
Win& w = wins.Add();
w.id = top->id;
w.ctrl = this;
w.gtk = top->window;
w.gdk = top->window->window;
TopWindow *tw = dynamic_cast<TopWindow *>(this);
gtk_window_set_type_hint(gtk(), popup ? GDK_WINDOW_TYPE_HINT_COMBO
: tw && tw->tool ? GDK_WINDOW_TYPE_HINT_UTILITY
: owner ? GDK_WINDOW_TYPE_HINT_DIALOG
: GDK_WINDOW_TYPE_HINT_NORMAL);
top->cursor_id = -1;
gtk_widget_set_events(top->window, 0xffffffff);
g_signal_connect(top->window, "event", G_CALLBACK(GtkEvent), (gpointer)(uintptr_t)top->id);
gtk_widget_realize(top->window);
Rect r = GetRect();
gtk_window_move(gtk(), r.left, r.top);
gtk_window_resize(gtk(), r.GetWidth(), r.GetHeight());
if(owner && owner->top)
gtk_window_set_transient_for(gtk(), owner->gtk());
gtk_widget_set_app_paintable(top->window, TRUE);
gtk_widget_set_can_focus(top->window, TRUE);
isopen = true;
top->im_context = gtk_im_multicontext_new();
gtk_im_context_set_client_window(top->im_context, gdk());
gtk_im_context_set_use_preedit(top->im_context, false);
g_signal_connect(top->im_context, "commit", G_CALLBACK(IMCommit), (gpointer)(uintptr_t)top->id);
WndShow(IsShown());
FocusSync();
if(!popup)
SetWndFocus();
DndInit();
StateH(OPEN);
}
void Ctrl::WndDestroy0()
{
GuiLock __;
LLOG("WndDestroy " << Name());
DndExit();
gtk_widget_destroy(top->window);
g_object_unref(top->im_context);
isopen = false;
popup = false;
delete top;
top = NULL;
int q = FindCtrl(this);
if(q >= 0)
wins.Remove(q);
}
Vector< Ptr<Ctrl> > Ctrl::activePopup;
void Ctrl::GuiPlatformRemove()
{
for(int i = 0; i < activePopup.GetCount();)
if(activePopup[i] == this) {
if(this == grabpopup && gdk_pointer_is_grabbed())
StopGrabPopup();
activePopup.Remove(i);
StartGrabPopup();
}
else
i++;
}
void Ctrl::PopUp(Ctrl *owner, bool savebits, bool activate, bool dropshadow, bool topmost)
{
GuiLock __;
LLOG("POPUP " << Name() << ", " << GetRect() << ", activate " << activate);
Create(owner, true);
popup = true;
if(activate) {
Ptr<Ctrl> _this = this;
SetFocus();
if(_this) {
activePopup.Add(this);
StartGrabPopup();
CheckMouseCtrl();
}
}
}
END_UPP_NAMESPACE
#endif

81
rainbow/Gtk/GtkCtrl.cpp Normal file
View file

@ -0,0 +1,81 @@
#include <CtrlCore/CtrlCore.h>
#ifdef GUI_GTK
#define LLOG(x) // DLOG(x)
NAMESPACE_UPP
void Ctrl::GuiPlatformConstruct()
{
}
void Ctrl::GuiPlatformDestruct()
{
}
void Ctrl::GuiPlatformGetTopRect(Rect& r) const
{
}
bool Ctrl::GuiPlatformRefreshFrameSpecial(const Rect& r)
{
return false;
}
bool Ctrl::GuiPlatformSetFullRefreshSpecial()
{
return false;
}
String GuiPlatformGetKeyDesc(dword key)
{
return Null;
}
void GuiPlatformAdjustDragImage(ImageBuffer&)
{
}
bool GuiPlatformHasSizeGrip()
{
return true;
}
void GuiPlatformGripResize(TopWindow *q)
{
if(q->top) {
Point p = GetMousePos();
gtk_window_begin_resize_drag(q->gtk(), GDK_WINDOW_EDGE_SOUTH_EAST,
1, p.x, p.y, Ctrl::CurrentTime);
}
}
Color GuiPlatformGetScreenPixel(int x, int y)
{
return Black;
}
void GuiPlatformAfterMenuPopUp()
{
}
String Ctrl::Name() const {
GuiLock __;
#ifdef CPU_64
String s = String(typeid(*this).name()) + " : 0x" + FormatIntHex(this);
#else
String s = String(typeid(*this).name()) + " : " + Format("0x%x", (int) this);
#endif
if(IsChild())
s << "(parent " << String(typeid(*parent).name()) << ")";
return s;
}
void Ctrl::InstallPanicBox()
{
}
END_UPP_NAMESPACE
#endif

167
rainbow/Gtk/GtkCtrl.h Normal file
View file

@ -0,0 +1,167 @@
//$ class Ctrl {
void Create(Ctrl *owner, bool popup);
static gboolean GtkProc(GtkWidget *widget, GdkEvent *event, gpointer user_data);
static void IMCommit(GtkIMContext *context, gchar *str, gpointer user_data);
static void DoMouseEvent(int state, Point pos);
static int DoButtonEvent(GdkEvent *event, bool press);
static void AddEvent(gpointer user_data, int type, const Value& value);
static void FetchEvents(bool may_block);
bool DispatchMouseIn(int act, int zd);
void GtkMouseEvent(int action, int act, int zd);
void GtkButtonEvent(int action);
static bool IsWaitingEvent0(bool fetch);
static bool ProcessEvent0(bool *quit, bool fetch);
static bool ProcessEvents0(bool *quit, bool fetch);
void Proc();
bool SweepConfigure(bool wait);
static gboolean GtkEvent(GtkWidget *widget, GdkEvent *key, gpointer user_data);
enum {
EVENT_NONE = -15321,
EVENT_TEXT,
};
struct Event0 {
int time;
int windowid;
int type;
Value value;
Point mousepos;
guint state;
int count;
};
struct Event : Moveable<Event, Event0> {
GdkEvent *event;
void Free();
void Set(const Event& e);
Event(const Event& e);
void operator=(const Event& e);
Event();
~Event();
};
struct Win : Moveable<Win> {
int id;
GtkWidget *gtk;
GdkWindow *gdk;
Ptr<Ctrl> ctrl;
};
static bool EventMouseValid;
static Point EventMousePos;
static guint EventState;
static BiVector<Event> Events;
static Vector< Ptr<Ctrl> > activePopup;
static Vector<Win> wins;
static int WndCaretTime;
static bool WndCaretVisible;
static Ptr<Ctrl> grabwindow;
static Ptr<Ctrl> grabpopup;
static Ptr<Ctrl> sel_ctrl;
static int FindId(int id);
static int FindCtrl(Ctrl *ctrl);
static int FindGtkWindow(GtkWidget *gtk);
static int FindGdkWindow(GdkWindow *gdk);
static Ctrl *GetTopCtrlFromId(int id);
static Ctrl *GetTopCtrlFromId(gpointer user_data) { return GetTopCtrlFromId((uint32)(uintptr_t)user_data); }
static void SyncPopupCapture();
void ReleasePopupCapture();
static void FocusSync();
static void AnimateCaret();
static gboolean TimeHandler(GtkWidget *);
static void InvalidateMousePos();
static void StopGrabPopup();
static void StartGrabPopup();
static bool ReleaseWndCapture0();
static Index<String> dnd_targets;
static String dnd_text_target;
static String dnd_image_target;
static String dnd_data;
static String dnd_data_fmt;
static bool dnd_data_wait;
static GtkWidget *dnd_widget;
static GdkDragContext *dnd_context;
static guint dnd_time;
static Ptr<Ctrl> dnd_source;
static const VectorMap<String, ClipData> *dnd_source_data;
static Vector<String> dnd_fmts;
static int dnd_result;
static Image dnd_icon;
static void GtkSelectionDataSet(GtkSelectionData *selection_data, const String& fmt, const String& data);
static void GtkGetClipData(GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, gpointer user_data);
static void AddFmt(GtkTargetList *list, const String& fmt, int info);
static GtkTargetList *CreateTargetList(const VectorMap<String, ClipData>& target);
static String GtkDataGet(GtkSelectionData *s);
void DndInit();
void DndExit();
static void GtkDragBegin(GtkWidget *widget, GdkDragContext *context, gpointer user_data);
static void GtkDragDelete(GtkWidget *widget, GdkDragContext *context, gpointer user_data);
static void GtkDragGetData(GtkWidget *widget, GdkDragContext *context, GtkSelectionData *data, guint info, guint time, gpointer user_data);
static void GtkDragDataReceived(GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *data, guint info, guint time, gpointer user_data);
static gboolean GtkDragDrop(GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time, gpointer user_data);
static void GtkDragEnd(GtkWidget *widget, GdkDragContext *context, gpointer user_data);
static gboolean GtkDragFailed(GtkWidget *widget, GdkDragContext *context, GtkDragResult result, gpointer user_data);
static void GtkDragLeave(GtkWidget *widget, GdkDragContext *context, guint time, gpointer user_data);
static gboolean GtkDragMotion(GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time, gpointer user_data);
static Ctrl *DragWnd(gpointer user_data);
static void DndTargets(GdkDragContext *context);
static bool IsDragAvailable(const char *fmt);
static String DragGet(const char *fmt);
static PasteClip GtkDnd(GtkWidget *widget, GdkDragContext *context, gint x, gint y,
guint time, gpointer user_data, bool paste);
friend void InitGtkApp(int argc, char **argv, const char **envptr);
friend void DrawDragRect(Ctrl& q, const Rect& rect1, const Rect& rect2, const Rect& clip, int n,
Color color, int type, int animation);
friend void FinishDragRect(Ctrl& q);
friend void GuiPlatformGripResize(TopWindow *q);
public: // really private:
struct Gclipboard {
VectorMap<String, ClipData> target;
GtkClipboard *clipboard;
String Get(const String& fmt);
void Put(const String& fmt, const ClipData& data);
bool IsAvailable(const String& fmt);
void Clear();
Gclipboard(GdkAtom type);
};
static Gclipboard& gclipboard();
static Gclipboard& gselection();
static String RenderPrimarySelection(const Value& fmt);
public:
static void EndSession() {}
static bool IsEndSession() { return false; }
static void PanicMsgBox(const char *title, const char *text);
static Point CurrentMousePos;
static guint CurrentState;
static guint32 CurrentTime;
static Event CurrentEvent;
GdkWindow *gdk() const { return top ? top->window->window : NULL; }
GtkWindow *gtk() const { return top ? (GtkWindow *)top->window : NULL; }
//$ };

329
rainbow/Gtk/GtkDnD.cpp Normal file
View file

@ -0,0 +1,329 @@
#include <CtrlCore/CtrlCore.h>
#ifdef GUI_GTK
NAMESPACE_UPP
#define LLOG(x) // DLOG(x)
// --------------------------------------------------------------------------------------------
Ptr<Ctrl> Ctrl::dnd_source;
const VectorMap<String, ClipData> *Ctrl::dnd_source_data;
Vector<String> Ctrl::dnd_fmts;
int Ctrl::dnd_result;
Image Ctrl::dnd_icon;
Ctrl *Ctrl::GetDragAndDropSource()
{
return dnd_source;
}
void Ctrl::GtkDragBegin(GtkWidget *widget, GdkDragContext *context, gpointer user_data)
{
if(IsNull(dnd_icon))
gtk_drag_set_icon_default(context);
else {
ImageGdk m(dnd_icon);
gtk_drag_set_icon_pixbuf(context, m, 0, 0);
}
LLOG("GtkDragBegin");
}
void Ctrl::GtkDragDelete(GtkWidget *widget, GdkDragContext *context, gpointer user_data)
{
LLOG("GtkDragDelete");
}
void Ctrl::GtkDragGetData(GtkWidget *widget, GdkDragContext *context, GtkSelectionData *data,
guint info, guint time, gpointer user_data)
{
LLOG("GtkDragGetData");
if(info < (guint)dnd_source_data->GetCount())
GtkSelectionDataSet(data, dnd_source_data->GetKey(info), (*dnd_source_data)[info].Render());
else {
info -= dnd_source_data->GetCount();
if(info < (guint)dnd_fmts.GetCount()) {
String fmt = dnd_fmts[info];
GtkSelectionDataSet(data, fmt, dnd_source->GetDropData(fmt));
}
}
}
void Ctrl::GtkDragEnd(GtkWidget *widget, GdkDragContext *context, gpointer user_data)
{
LLOG("GtkDragEnd");
dnd_result = DND_NONE;
GdkDragAction a = gdk_drag_context_get_selected_action(context);
dnd_result = a == GDK_ACTION_MOVE ? DND_MOVE : a == GDK_ACTION_COPY ? DND_COPY : DND_NONE;
dnd_source = NULL;
}
gboolean Ctrl::GtkDragFailed(GtkWidget *widget, GdkDragContext *context, GtkDragResult result,
gpointer user_data)
{
LLOG("GtkDragFailed");
dnd_source = NULL;
return FALSE;
}
Image MakeDragImage(const Image& arrow, Image sample);
Image MakeDragImage(const Image& arrow, const Image& arrow98, Image sample)
{
#ifdef PLATFORM_WIN32
if(IsWin2K())
return MakeDragImage(arrow, sample);
else
#endif
return arrow98;
}
int Ctrl::DoDragAndDrop(const char *fmts, const Image& sample, dword actions,
const VectorMap<String, ClipData>& data)
{
LLOG("DoDragAndDrop");
TopWindow *w = GetTopWindow();
if(!w || !w->top)
return DND_NONE;
int gdk_actions = 0;
if(actions & DND_MOVE)
gdk_actions |= GDK_ACTION_MOVE;
if(actions & DND_COPY)
gdk_actions |= GDK_ACTION_COPY;
GtkTargetList *list = CreateTargetList(data);
Vector<String> f = Split(fmts, ';');
dnd_fmts.Clear();
for(int i = 0; i < f.GetCount(); i++) {
AddFmt(list, f[i], data.GetCount() + i);
dnd_fmts.Add(f[i]);
}
dnd_source_data = &data;
dnd_result = DND_NONE;
dnd_source = this;
if(IsNull(sample))
dnd_icon = Null;
else {
Size sz = sample.GetSize();
if(sz.cx > 128)
sz.cx = 128;
if(sz.cy > 128)
sz.cy = 128;
sz += 2;
ImageDraw iw(sz);
iw.DrawRect(sz, White());
DrawFrame(iw, sz, Black());
iw.DrawImage(1, 1, sz.cx, sz.cy, sample);
ImageBuffer b(128, 128);
dnd_icon = iw;
}
gtk_drag_begin(w->top->window, list, GdkDragAction(gdk_actions),
GetMouseLeft() ? 1 : GetMouseMiddle() ? 2 : 3, CurrentEvent.event);
while(dnd_source && GetTopCtrls().GetCount())
ProcessEvents();
dnd_source_data = NULL;
gtk_target_list_unref (list);
LLOG("--DoDragAndDrop");
return dnd_result;
}
// --------------------------------------------------------------------------------------------
Index<String> Ctrl::dnd_targets;
String Ctrl::dnd_text_target;
String Ctrl::dnd_image_target;
GtkWidget *Ctrl::dnd_widget;
GdkDragContext *Ctrl::dnd_context;
guint Ctrl::dnd_time;
String Ctrl::dnd_data;
String Ctrl::dnd_data_fmt;
bool Ctrl::dnd_data_wait;
Ctrl *Ctrl::DragWnd(gpointer user_data)
{
if(dnd_data_wait) // Do nothing if waiting for data
return NULL;
ProcessEvents0(NULL, false); // process any events that are already fetched
return GetTopCtrlFromId(user_data);
}
void ToIndex(GtkTargetList *target_list, Index<String>& ndx)
{
gint n;
GtkTargetEntry *t = gtk_target_table_new_from_list(target_list, &n);
for(int i = 0; i < n; i++)
ndx.Add(t[i].target);
gtk_target_table_free(t, n);
gtk_target_list_unref(target_list);
}
void Ctrl::DndTargets(GdkDragContext *context)
{
static Index<String> text_targets;
static Index<String> image_targets;
ONCELOCK {
GtkTargetList *target_list = gtk_target_list_new (NULL, 0);
gtk_target_list_add_text_targets (target_list, 0);
ToIndex(target_list, text_targets);
GtkTargetList *target_list2 = gtk_target_list_new (NULL, 0);
gtk_target_list_add_image_targets (target_list2, 0, TRUE);
ToIndex(target_list2, image_targets);
}
dnd_targets.Clear();
dnd_text_target.Clear();
for(GList *list = gdk_drag_context_list_targets(context); list; list = g_list_next (list)) {
String g = gdk_atom_name((GdkAtom)list->data);
if(text_targets.Find(g) >= 0) {
dnd_targets.Add("text");
if(dnd_text_target.IsEmpty())
dnd_text_target = g;
}
else
if(image_targets.Find(g) >= 0) {
dnd_targets.Add("image");
if(dnd_image_target.IsEmpty())
dnd_image_target = g;
}
else
dnd_targets.Add(g);
}
}
void Ctrl::GtkDragDataReceived(GtkWidget *widget, GdkDragContext *context,
gint x, gint y, GtkSelectionData *data,
guint info, guint time, gpointer user_data)
{
LLOG("GtkDragDataReceived");
dnd_data_wait = false;
if(dnd_data_fmt == "text") {
guchar *s = gtk_selection_data_get_text(data);
if(s) {
dnd_data = (const char *)s;
g_free(s);
}
}
else
if(dnd_data_fmt == "image") {
Image img = ImageFromPixbufUnref(gtk_selection_data_get_pixbuf(data));
dnd_data = StoreAsString(img); // Not very optimal...
}
else
dnd_data = GtkDataGet(data);
}
bool Ctrl::IsDragAvailable(const char *fmt)
{
LLOG("IsDragAvailable " << fmt << " " << (Ctrl::dnd_targets.Find(fmt) >= 0));
return dnd_targets.Find(fmt) >= 0;
}
String Ctrl::DragGet(const char *fmt)
{
LLOG("DragGet " << fmt << " " << (Ctrl::dnd_targets.Find(fmt) >= 0));
if(Ctrl::dnd_targets.Find(fmt) < 0)
return Null;
dnd_data.Clear();
dnd_data_wait = true;
dnd_data_fmt = fmt;
int t0 = msecs();
gtk_drag_get_data(dnd_widget, dnd_context,
GAtom(strcmp(fmt, "image") == 0 ? ~dnd_image_target
: strcmp(fmt, "text") == 0 ? ~dnd_text_target
: fmt),
dnd_time);
while(msecs() - t0 < 1000 && dnd_data_wait)
FetchEvents(true);
LLOG("DragGet data length " << dnd_data.GetLength());
return dnd_data;
}
PasteClip Ctrl::GtkDnd(GtkWidget *widget, GdkDragContext *context, gint x, gint y,
guint time, gpointer user_data, bool paste)
{
DndTargets(context);
g_object_ref(context); // make sure these always survive the action...
g_object_ref(widget);
dnd_context = context;
dnd_widget = widget;
dnd_time = time;
PasteClip clip;
clip.type = 1;
clip.paste = paste;
clip.accepted = false;
clip.allowed = DND_MOVE|DND_COPY;
gint dummy;
GdkModifierType mod;
gdk_window_get_pointer(gdk_get_default_root_window(), &dummy, &dummy, &mod);
clip.action = mod & GDK_CONTROL_MASK ? DND_COPY : DND_MOVE;
Ctrl *w = DragWnd(user_data);
if(w) {
gint mx, my;
GdkModifierType mod;
gdk_window_get_pointer(gdk_get_default_root_window(), &mx, &my, &mod);
CurrentState = mod;
CurrentMousePos = Point(x, y) + w->GetScreenRect().TopLeft();
w->DnD(CurrentMousePos, clip);
}
gdk_drag_status(context, clip.IsAccepted() ? clip.GetAction() == DND_MOVE ? GDK_ACTION_MOVE
: GDK_ACTION_COPY
: GdkDragAction(0), time);
return clip;
}
gboolean Ctrl::GtkDragMotion(GtkWidget *widget, GdkDragContext *context, gint x, gint y,
guint time, gpointer user_data)
{
LLOG("GtkDragMotion");
PasteClip clip = GtkDnd(widget, context, x, y, time, user_data, false);
g_object_unref(widget);
g_object_unref(context);
return TRUE;
}
void Ctrl::GtkDragLeave(GtkWidget *widget, GdkDragContext *context, guint time, gpointer user_data)
{
LLOG("GtkDragLeave");
DnDLeave();
}
gboolean Ctrl::GtkDragDrop(GtkWidget *widget, GdkDragContext *context, gint x, gint y,
guint time, gpointer user_data)
{
LLOG("GtkDragDrop");
PasteClip clip = GtkDnd(widget, context, x, y, time, user_data, true);
gtk_drag_finish(context, clip.IsAccepted(), clip.IsAccepted() && clip.GetAction() == DND_MOVE, time);
g_object_unref(widget);
g_object_unref(context);
DnDLeave();
return TRUE;
}
// -----------------------------------------------------------------------------------------
void Ctrl::DndInit()
{
GtkWidget *w = top->window;
gpointer id = (gpointer)(uintptr_t)top->id;
g_signal_connect(w, "drag-begin", G_CALLBACK(GtkDragBegin), id);
g_signal_connect(w, "drag-data-delete", G_CALLBACK(GtkDragDelete), id);
g_signal_connect(w, "drag-data-get", G_CALLBACK(GtkDragGetData), id);
g_signal_connect(w, "drag-data-received", G_CALLBACK(GtkDragDataReceived), id);
g_signal_connect(w, "drag-drop", G_CALLBACK(GtkDragDrop), id);
g_signal_connect(w, "drag-end", G_CALLBACK(GtkDragEnd), id);
g_signal_connect(w, "drag-failed", G_CALLBACK(GtkDragFailed), id);
g_signal_connect(w, "drag-leave", G_CALLBACK(GtkDragLeave), id);
g_signal_connect(w, "drag-motion", G_CALLBACK(GtkDragMotion), id);
gtk_drag_dest_set(w, GtkDestDefaults(0), NULL, 0, GdkDragAction(GDK_ACTION_COPY|GDK_ACTION_MOVE));
}
void Ctrl::DndExit()
{
if(top)
gtk_drag_dest_unset(top->window);
}
END_UPP_NAMESPACE
#endif

View file

@ -0,0 +1,208 @@
#include <CtrlCore/CtrlCore.h>
#ifdef GUI_GTK
//#include <shellapi.h>
NAMESPACE_UPP
#define LTIMING(x) // RTIMING(x)
#define LLOG(x)
void SetSurface(SystemDraw& w, int x, int y, int cx, int cy, const RGBA *pixels);
void SetSurface(SystemDraw& w, const Rect& dest, const RGBA *pixels, Size psz, Point poff);
struct ImageSysData {
Image img;
cairo_surface_t *surface;
void Init(const Image& img);
~ImageSysData();
};
void ImageSysData::Init(const Image& m)
{
img = m;
Size isz = img.GetSize();
surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, isz.cx, isz.cy);
cairo_surface_flush(surface);
byte *a = (byte *)cairo_image_surface_get_data(surface);
int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, isz.cx);
for(int yy = 0; yy < isz.cy; yy++) {
Copy((RGBA *)a, img[yy], isz.cx);
a += stride;
}
cairo_surface_mark_dirty(surface);
SysImageRealized(img);
}
ImageSysData::~ImageSysData()
{
SysImageReleased(img);
cairo_surface_destroy(surface);
}
struct ImageSysDataMaker : LRUCache<ImageSysData, int64>::Maker {
Image img;
virtual int64 Key() const { return img.GetSerialId(); }
virtual int Make(ImageSysData& object) const { object.Init(img); return img.GetLength(); }
};
void SystemDraw::SysDrawImageOp(int x, int y, const Image& img, Color color)
{
GuiLock __;
if(img.GetLength() == 0)
return;
LLOG("SysDrawImageOp " << img.GetSerialId() << ' ' << x << ", " << y << ", "<< img.GetSize());
ImageSysDataMaker m;
static LRUCache<ImageSysData, int64> cache;
LLOG("SysImage cache pixels " << cache.GetSize() << ", count " << cache.GetCount());
m.img = img;
ImageSysData& sd = cache.Get(m);
if(!IsNull(color)) {
SetColor(color);
cairo_mask_surface(cr, sd.surface, x, y);
}
else {
cairo_set_source_surface(cr, sd.surface, x, y);
cairo_paint(cr);
}
cache.Shrink(4 * 1024 * 768, 1000); // Cache must be after Paint because of PaintOnly!
}
Draw& ImageDraw::Alpha()
{
if(!alpha_surface) {
alpha_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, isz.cx, isz.cy);
alpha.cr = cairo_create(alpha_surface);
}
return alpha;
}
void CairoGet(ImageBuffer& b, Size isz, cairo_surface_t *surface, cairo_surface_t *alpha_surface)
{
cairo_surface_flush(surface);
byte *a = (byte *)cairo_image_surface_get_data(surface);
int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, isz.cx);
RGBA *t = b;
byte *aa = NULL;
if(alpha_surface) {
cairo_surface_flush(alpha_surface);
aa = (byte *)cairo_image_surface_get_data(alpha_surface);
}
for(int yy = 0; yy < isz.cy; yy++) {
RGBA *s = (RGBA *)a;
RGBA *e = s + isz.cx;
if(aa) {
RGBA *ss = (RGBA *)aa;
while(s < e) {
*t = *s++;
(t++)->a = (ss++)->r;
}
aa += stride;
}
else
while(s < e) {
*t = *s++;
(t++)->a = 255;
}
a += stride;
}
}
void ImageDraw::FetchStraight(ImageBuffer& b) const
{
CairoGet(b, isz, surface, alpha_surface);
}
ImageDraw::operator Image() const
{
ImageBuffer img(isz);
FetchStraight(img);
Premultiply(img);
return img;
}
Image ImageDraw::GetStraight() const
{
ImageBuffer img(isz);
FetchStraight(img);
return img;
}
void ImageDraw::Init(Size sz)
{
isz = sz;
surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, isz.cx, isz.cy);
cr = cairo_create(surface);
alpha_surface = NULL;
del = true;
}
ImageDraw::ImageDraw(Size sz)
{
Init(sz);
}
ImageDraw::ImageDraw(int cx, int cy)
{
Init(Size(cx, cy));
}
ImageDraw::ImageDraw(cairo_t *cr_, Size sz)
{
isz = sz;
cr = cr_;
surface = cairo_get_target(cr);
alpha_surface = NULL;
del = false;
}
ImageDraw::~ImageDraw()
{
if(del) {
cairo_destroy(cr);
cairo_surface_destroy(surface);
if(alpha_surface) {
cairo_destroy(alpha.cr);
cairo_surface_destroy(alpha_surface);
}
}
}
void BackDraw::Put(SystemDraw& w, int x, int y)
{
}
void BackDraw::Create(SystemDraw& w, int cx, int cy)
{
}
void BackDraw::Destroy()
{
}
#define FCURSOR_(x) { static Image h; ONCELOCK { h = CreateImage(Size(1, 1), Black); h.SetAuxData(x + 1); } return h; }
Image Image::Arrow() FCURSOR_(GDK_LEFT_PTR)
Image Image::Wait() FCURSOR_(GDK_WATCH)
Image Image::IBeam() FCURSOR_(GDK_XTERM)
Image Image::No() FCURSOR_(GDK_CIRCLE)
Image Image::SizeAll() FCURSOR_(GDK_FLEUR)
Image Image::SizeHorz() FCURSOR_(GDK_SB_H_DOUBLE_ARROW)
Image Image::SizeVert() FCURSOR_(GDK_DOUBLE_ARROW)
Image Image::SizeTopLeft() FCURSOR_(GDK_TOP_LEFT_CORNER)
Image Image::SizeTop() FCURSOR_(GDK_TOP_SIDE)
Image Image::SizeTopRight() FCURSOR_(GDK_TOP_RIGHT_CORNER)
Image Image::SizeLeft() FCURSOR_(GDK_LEFT_SIDE)
Image Image::SizeRight() FCURSOR_(GDK_RIGHT_SIDE)
Image Image::SizeBottomLeft() FCURSOR_(GDK_BOTTOM_LEFT_CORNER)
Image Image::SizeBottom() FCURSOR_(GDK_BOTTOM_SIDE)
Image Image::SizeBottomRight() FCURSOR_(GDK_BOTTOM_RIGHT_CORNER)
Image Image::Cross() FCURSOR_(GDK_CROSSHAIR)
Image Image::Hand() FCURSOR_(GDK_HAND1)
END_UPP_NAMESPACE
#endif

148
rainbow/Gtk/GtkDrawOp.cpp Normal file
View file

@ -0,0 +1,148 @@
#include <CtrlCore/CtrlCore.h>
#ifdef GUI_GTK
NAMESPACE_UPP
#define LLOG(x)
void SystemDraw::SetColor(Color c)
{
cairo_set_source_rgb(cr, c.GetR() / 255.0, c.GetG() / 255.0, c.GetB() / 255.0);
}
dword SystemDraw::GetInfo() const
{
return DRAWTEXTLINES;
}
Point SystemDraw::GetOffset() const
{
return offset.GetCount() ? offset.Top() : Point(0, 0);
}
void SystemDraw::Push()
{
cairo_save(cr);
offset.Add(GetOffset());
}
void SystemDraw::Pop()
{
if(offset.GetCount())
offset.Drop();
cairo_restore(cr);
}
void SystemDraw::BeginOp()
{
Push();
}
void SystemDraw::EndOp()
{
Pop();
}
void SystemDraw::OffsetOp(Point p)
{
Push();
offset.Top() += p;
cairo_translate(cr, p.x, p.y);
}
void SystemDraw::RectPath(const Rect& r)
{
cairo_rectangle(cr, r.left, r.top, r.GetWidth(), r.GetHeight());
}
bool SystemDraw::ClipOp(const Rect& r)
{
Push();
RectPath(r);
cairo_clip(cr);
return true;
}
bool SystemDraw::ClipoffOp(const Rect& r)
{
Push();
offset.Top() += r.TopLeft();
RectPath(r);
cairo_clip(cr);
cairo_translate(cr, r.left, r.top);
return true;
}
bool SystemDraw::ExcludeClipOp(const Rect& r)
{
RectPath(Rect(-99999, -99999, 99999, r.top));
RectPath(Rect(-99999, r.top, r.left, 99999));
RectPath(Rect(r.right, r.top, 99999, 99999));
RectPath(Rect(r.left, r.bottom, r.right, 99999));
cairo_clip(cr);
return true;
}
bool SystemDraw::IntersectClipOp(const Rect& r)
{
RectPath(r);
cairo_clip(cr);
return true;
}
bool SystemDraw::IsPaintingOp(const Rect& r) const
{
return true;
}
Rect SystemDraw::GetPaintRect() const
{
return Rect(0, 0, INT_MAX, INT_MAX);
}
void SystemDraw::DrawRectOp(int x, int y, int cx, int cy, Color color)
{
if(IsNull(color))
return;
cairo_rectangle(cr, x, y, cx, cy);
if(color == InvertColor()) {
SetColor(White());
cairo_set_operator(cr, CAIRO_OPERATOR_DIFFERENCE);
cairo_fill(cr);
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
}
else {
SetColor(color);
cairo_fill(cr);
}
}
void SystemDraw::DrawLineOp(int x1, int y1, int x2, int y2, int width, Color color)
{
SetColor(color);
cairo_move_to(cr, x1, y1);
cairo_line_to(cr, x2, y2);
cairo_set_line_width (cr, width);
cairo_stroke(cr);
}
void SystemDraw::DrawPolyPolylineOp(const Point *vertices, int vertex_count, const int *counts, int count_count, int width, Color color, Color doxor)
{
}
void SystemDraw::DrawPolyPolyPolygonOp(const Point *vertices, int vertex_count, const int *subpolygon_counts, int scc, const int *disjunct_polygon_counts, int dpcc, Color color, int width, Color outline, uint64 pattern, Color doxor)
{
}
void SystemDraw::DrawArcOp(const Rect& rc, Point start, Point end, int width, Color color)
{
}
void SystemDraw::DrawEllipseOp(const Rect& r, Color color, int pen, Color pencolor)
{
}
END_UPP_NAMESPACE
#endif

View file

@ -0,0 +1,88 @@
#include <CtrlCore/CtrlCore.h>
#ifdef GUI_GTK
#include <cairo/cairo-ft.h>
NAMESPACE_UPP
#define LLOG(x)
FcPattern *CreateFcPattern(Font font);
FT_Face FTFace(Font fnt, String *rpath = NULL);
struct FontSysData {
cairo_scaled_font_t *scaled_font;
void Init(Font font, int angle);
~FontSysData() { cairo_scaled_font_destroy(scaled_font); }
};
void FontSysData::Init(Font font, int angle)
{
LLOG("FontSysData::Init " << font << ", " << angle);
FcPattern *p = CreateFcPattern(font);
cairo_font_face_t *font_face = cairo_ft_font_face_create_for_pattern(p);
FcPatternDestroy(p);
cairo_matrix_t font_matrix[1], ctm[1];
cairo_matrix_init_identity(ctm);
cairo_matrix_init_scale(font_matrix, font.GetHeight(), font.GetHeight());
if(angle)
cairo_matrix_rotate(font_matrix, -angle * M_2PI / 3600);
cairo_font_options_t *opt = cairo_font_options_create();
scaled_font = cairo_scaled_font_create(font_face, font_matrix, ctm, opt);
cairo_font_options_destroy(opt);
cairo_font_face_destroy(font_face);
}
struct FontDataSysMaker : LRUCache<FontSysData, Tuple2<Font, int> >::Maker {
Font font;
int angle;
virtual Tuple2<Font, int> Key() const { return MakeTuple(font, angle); }
virtual int Make(FontSysData& object) const { object.Init(font, angle); return 1; }
};
int gtk_antialias = -1;
int gtk_hinting = -1;
String gtk_hintstyle;
String gtk_rgba;
void SystemDraw::DrawTextOp(int x, int y, int angle, const wchar *text, Font font, Color ink, int n, const int *dx)
{
GuiLock __;
int ascent = font.GetAscent();
double sina = 0;
double cosa = 1;
if(angle)
Draw::SinCos(angle, sina, cosa);
int xpos = 0;
Buffer<cairo_glyph_t> gs(n);
for(int i = 0; i < n; i++) {
cairo_glyph_t& g = gs[i];
g.index = GetGlyphInfo(font, text[i]).glyphi;
g.x = fround(x + cosa * xpos + sina * ascent);
g.y = fround(y + cosa * ascent - sina * xpos);
xpos += dx ? dx[i] : font[text[i]];
}
static LRUCache<FontSysData, Tuple2<Font, int> > cache;
FontDataSysMaker m;
m.font = font;
m.angle = angle;
FontSysData& sf = cache.Get(m);
cairo_set_scaled_font(cr, sf.scaled_font);
SetColor(ink);
cairo_show_glyphs(cr, gs, n);
cache.Shrink(64);
}
END_UPP_NAMESPACE
#endif

584
rainbow/Gtk/GtkEvent.cpp Normal file
View file

@ -0,0 +1,584 @@
#include <CtrlCore/CtrlCore.h>
#ifdef GUI_GTK
//#include <winnls.h>
//#include "imm.h"
NAMESPACE_UPP
#define LLOG(x) LOG(x)
#define LOG_EVENTS
bool Ctrl::EventMouseValid;
Point Ctrl::EventMousePos;
guint Ctrl::EventState;
BiVector<Ctrl::Event> Ctrl::Events;
Point Ctrl::CurrentMousePos;
guint Ctrl::CurrentState;
guint32 Ctrl::CurrentTime;
Ctrl::Event Ctrl::CurrentEvent;
bool GetShift() { return Ctrl::CurrentState & GDK_SHIFT_MASK; }
bool GetCtrl() { return Ctrl::CurrentState & GDK_CONTROL_MASK ; }
bool GetAlt() { return Ctrl::CurrentState & GDK_MOD1_MASK; }
bool GetCapsLock() { return Ctrl::CurrentState & GDK_LOCK_MASK; }
bool GetMouseLeft() { return Ctrl::CurrentState & GDK_BUTTON1_MASK; }
bool GetMouseRight() { return Ctrl::CurrentState & GDK_BUTTON3_MASK; }
bool GetMouseMiddle() { return Ctrl::CurrentState & GDK_BUTTON2_MASK; }
Point GetMousePos() { return Ctrl::CurrentMousePos; }
#ifdef LOG_EVENTS
Tuple2<int, const char *> xEvent[] = {
{ GDK_NOTHING, "GDK_NOTHING" },
{ GDK_DELETE, "GDK_DELETE" },
{ GDK_DESTROY, "GDK_DESTROY" },
{ GDK_EXPOSE, "GDK_EXPOSE" },
{ GDK_MOTION_NOTIFY, "GDK_MOTION_NOTIFY" },
{ GDK_BUTTON_PRESS, "GDK_BUTTON_PRESS" },
{ GDK_2BUTTON_PRESS, "GDK_2BUTTON_PRESS" },
{ GDK_3BUTTON_PRESS, "GDK_3BUTTON_PRESS" },
{ GDK_BUTTON_RELEASE, "GDK_BUTTON_RELEASE" },
{ GDK_KEY_PRESS, "GDK_KEY_PRESS" },
{ GDK_KEY_RELEASE, "GDK_KEY_RELEASE" },
{ GDK_ENTER_NOTIFY, "GDK_ENTER_NOTIFY" },
{ GDK_LEAVE_NOTIFY, "GDK_LEAVE_NOTIFY" },
{ GDK_FOCUS_CHANGE, "GDK_FOCUS_CHANGE" },
{ GDK_CONFIGURE, "GDK_CONFIGURE" },
{ GDK_MAP, "GDK_MAP" },
{ GDK_UNMAP, "GDK_UNMAP" },
{ GDK_PROPERTY_NOTIFY, "GDK_PROPERTY_NOTIFY" },
{ GDK_SELECTION_CLEAR, "GDK_SELECTION_CLEAR" },
{ GDK_SELECTION_REQUEST, "GDK_SELECTION_REQUEST" },
{ GDK_SELECTION_NOTIFY, "GDK_SELECTION_NOTIFY" },
{ GDK_PROXIMITY_IN, "GDK_PROXIMITY_IN" },
{ GDK_PROXIMITY_OUT, "GDK_PROXIMITY_OUT" },
{ GDK_DRAG_ENTER, "GDK_DRAG_ENTER" },
{ GDK_DRAG_LEAVE, "GDK_DRAG_LEAVE" },
{ GDK_DRAG_MOTION, "GDK_DRAG_MOTION" },
{ GDK_DRAG_STATUS, "GDK_DRAG_STATUS" },
{ GDK_DROP_START, "GDK_DROP_START" },
{ GDK_DROP_FINISHED, "GDK_DROP_FINISHED" },
{ GDK_CLIENT_EVENT, "GDK_CLIENT_EVENT" },
{ GDK_VISIBILITY_NOTIFY, "GDK_VISIBILITY_NOTIFY" },
{ GDK_NO_EXPOSE, "GDK_NO_EXPOSE" },
{ GDK_SCROLL, "GDK_SCROLL" },
{ GDK_WINDOW_STATE, "GDK_WINDOW_STATE" },
{ GDK_SETTING, "GDK_SETTING" },
{ GDK_OWNER_CHANGE, "GDK_OWNER_CHANGE" },
{ GDK_GRAB_BROKEN, "GDK_GRAB_BROKEN" },
{ GDK_DAMAGE, "GDK_DAMAGE" },
{ GDK_EVENT_LAST, "GDK_EVENT_LAST" },
};
#endif
Ctrl *Ctrl::GetTopCtrlFromId(int id)
{
int q = FindId(id);
if(q >= 0) {
Ctrl *p = wins[q].ctrl;
if(p && p->top)
return p;
}
return NULL;
}
gboolean Ctrl::GtkEvent(GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
#ifdef LOG_EVENTS
String ev = "?";
Tuple2<int, const char *> *f = FindTuple(xEvent, __countof(xEvent), event->type);
if(f)
ev = f->b;
LOG(rmsecs() << " FETCH EVENT " << ev);
#endif
GdkEventKey *key;
bool pressed = false;
bool retval = true;
Value value;
Ctrl *p;
switch(event->type) {
case GDK_EXPOSE:
case GDK_DAMAGE:
p = GetTopCtrlFromId(user_data);
if(p) {
#ifdef LOG_EVENTS
TimeStop tm;
#endif
p->fullrefresh = false;
GdkEventExpose *e = (GdkEventExpose *)event;
SystemDraw w(gdk_cairo_create(p->gdk()));
painting = true;
Rect r = RectC(e->area.x, e->area.y, e->area.width, e->area.height);
w.Clip(r);
p->UpdateArea(w, r);
w.End();
cairo_destroy(w);
if(p->top->dr)
DrawDragRect(*p, *p->top->dr);
painting = false;
#ifdef LOG_EVENTS
LOG("* " << ev << " elapsed " << tm);
#endif
}
return true;
case GDK_DELETE:
break;
case GDK_FOCUS_CHANGE:
retval = false;
value = ((GdkEventFocus *)event)->in;
break;
case GDK_LEAVE_NOTIFY:
EventMouseValid = false;
return false;
case GDK_MOTION_NOTIFY: {
GdkEventMotion *e = (GdkEventMotion *)event;
DoMouseEvent(e->state, Point((int)e->x_root, (int)e->y_root));
break;
}
case GDK_BUTTON_PRESS:
value = DoButtonEvent(event, true);
if(IsNull(value))
return false;
break;
case GDK_2BUTTON_PRESS:
value = DoButtonEvent(event, true);
if(IsNull(value))
return false;
break;
case GDK_BUTTON_RELEASE:
value = DoButtonEvent(event, false);
if(IsNull(value))
return false;
break;
case GDK_SCROLL: {
GdkEventScroll *e = (GdkEventScroll *)event;
value = findarg(e->direction, GDK_SCROLL_UP, GDK_SCROLL_LEFT) < 0 ? -120 : 120;
DoMouseEvent(e->state, Point((int)e->x_root, (int)e->y_root));
break;
}
case GDK_KEY_PRESS:
pressed = true;
case GDK_KEY_RELEASE:
key = (GdkEventKey *)event;
EventState = key->state;
value = (int) key->keyval;
if(pressed) {
p = GetTopCtrlFromId(user_data);
if(p && gtk_im_context_filter_keypress(p->top->im_context, key))
return true;
}
break;
case GDK_CONFIGURE: {
retval = false;
GdkEventConfigure *e = (GdkEventConfigure *)event;
value = RectC(e->x, e->y, e->width, e->height);
break;
}
default:
return false;
}
AddEvent(user_data, event->type, value);
return retval;
}
void Ctrl::DoMouseEvent(int state, Point pos)
{
EventMousePos = pos;
EventState = state;
EventMouseValid = true;
}
int Ctrl::DoButtonEvent(GdkEvent *event, bool press)
{
GdkEventButton *e = (GdkEventButton *)event;
static int mask[] = { GDK_BUTTON1_MASK, GDK_BUTTON2_MASK, GDK_BUTTON3_MASK };
if(e->button >= 1 && e->button <= 3) {
int m = mask[e->button - 1];
int state = e->state;
if(press) // gtk seems to provide state "before" the event, so buttons are wrong
state |= m;
else
state &= ~m;
DoMouseEvent(state, Point((int)e->x_root, (int)e->y_root));
return e->button;
}
return Null;
}
Ctrl::Event::Event()
{
event = NULL;
}
void Ctrl::Event::Free()
{
if(event) {
gdk_event_free(event);
event = NULL;
}
}
void Ctrl::Event::Set(const Event& e)
{
*(Event0 *)this = e;
event = gdk_event_copy(e.event);
}
Ctrl::Event::~Event()
{
Free();
}
Ctrl::Event::Event(const Event& e)
{
Set(e);
}
void Ctrl::Event::operator=(const Event& e)
{
if(this == &e)
return;
Free();
Set(e);
}
void Ctrl::AddEvent(gpointer user_data, int type, const Value& value)
{
if(Events.GetCount() > 50000)
return;
Event& e = Events.AddTail();
e.time = gtk_get_current_event_time();
e.windowid = (uint32)(uintptr_t)user_data;
e.type = type;
e.value = value;
if(!EventMouseValid) {
gint x, y;
GdkModifierType mod;
gdk_window_get_pointer(gdk_get_default_root_window(), &x, &y, &mod);
EventState = mod;
EventMousePos = Point(x, y);
EventMouseValid = true;
}
e.mousepos = EventMousePos;
e.state = EventState;
e.count = 1;
e.event = gtk_get_current_event();
}
void Ctrl::IMCommit(GtkIMContext *context, gchar *str, gpointer user_data)
{
AddEvent(user_data, EVENT_TEXT, FromUtf8(str));
}
void Ctrl::FetchEvents(bool may_block)
{
while(g_main_context_iteration(NULL, may_block))
may_block = false;
}
bool Ctrl::IsWaitingEvent0(bool fetch)
{
if(fetch)
FetchEvents(FALSE);
return Events.GetCount();
}
bool Ctrl::IsWaitingEvent()
{
return IsWaitingEvent0(true);
}
struct ProcStop {
TimeStop tm;
String ev;
~ProcStop() { LOG("* " << ev << " elapsed " << tm); }
};
bool Ctrl::DispatchMouseIn(int act, int zd)
{
Point p = GetMousePos();
Rect r = GetScreenRect();
if(r.Contains(p)) {
p -= r.TopLeft();
DispatchMouse(act, p, zd);
return true;
}
return false;
}
void Ctrl::GtkMouseEvent(int action, int act, int zd)
{
if(grabpopup && activePopup.GetCount()) {
for(int i = activePopup.GetCount(); --i >= 0;)
if(activePopup[i] && activePopup[i]->DispatchMouseIn(act, zd))
return;
if(action == DOWN) { // Deactivate active popup(s) if clicked outside of active popups
IgnoreMouseUp();
if(activePopup.Top())
activePopup.Top()->GetTopWindow()->ActivateWnd();
}
else
if(activePopup[0]) { // Redirect other events to TopWindow that spawned first popup
Ptr<TopWindow> w = activePopup[0]->GetTopWindow();
if(w)
w->DispatchMouseIn(act, zd);
}
return;
}
DispatchMouse(act, GetMousePos() - GetScreenRect().TopLeft(), zd);
}
void Ctrl::GtkButtonEvent(int action)
{
int act = action;
int button = CurrentEvent.value;
if(action != MOUSEMOVE)
act |= button == 2 ? MIDDLE : button == 3 ? RIGHT : LEFT;
GtkMouseEvent(action, act, 0);
}
void Ctrl::Proc()
{
#ifdef LOG_EVENTS
String ev = "?";
Tuple2<int, const char *> *f = FindTuple(xEvent, __countof(xEvent), CurrentEvent.type);
if(f)
ev = f->b;
LOG(rmsecs() << "PROCESS EVENT " << Upp::Name(this) << " " << ev);
ProcStop tm;
tm.ev = ev;
#endif
if(!top)
return;
Ptr<Ctrl> _this = this;
bool pressed = false;
int kv;
switch(CurrentEvent.type) {
case GDK_DELETE: {
TopWindow *w = dynamic_cast<TopWindow *>(this);
if(w) {
if(IsEnabled()) {
IgnoreMouseUp();
w->WhenClose();
}
}
}
case GDK_FOCUS_CHANGE:
LLOG("FocusChange in: " << (bool)CurrentEvent.value << ", focusCtrlWnd " << focusCtrlWnd);
if((bool)CurrentEvent.value) {
gtk_im_context_focus_in(top->im_context);
if(this != focusCtrlWnd) {
LLOG("Activate " << Name());
SetFocusWnd();
}
}
else {
gtk_im_context_focus_out(top->im_context);
KillFocusWnd();
}
return;
case GDK_MOTION_NOTIFY: {
GtkMouseEvent(MOUSEMOVE, MOUSEMOVE, 0);
DoCursorShape();
break;
}
case GDK_BUTTON_PRESS:
if(!HasWndFocus() && !popup)
SetWndFocus();
ClickActivateWnd();
GtkButtonEvent(DOWN);
break;
case GDK_2BUTTON_PRESS:
GtkButtonEvent(DOUBLE);
break;
case GDK_BUTTON_RELEASE:
if(ignoreclick)
EndIgnore();
else
GtkButtonEvent(UP);
break;
case GDK_SCROLL: {
GtkMouseEvent(MOUSEWHEEL, MOUSEWHEEL, CurrentEvent.value);
break;
}
case GDK_KEY_PRESS:
pressed = true;
case GDK_KEY_RELEASE:
kv = CurrentEvent.value;
if(kv >= 0 && kv < 65536) {
LOG(FormatIntHex(kv) << ' ' << (char)kv);
if(kv >= 'a' && kv <= 'z')
kv = kv - 'a' + 'A';
static Tuple2<int, int> cv[] = {
{ GDK_KEY_BackSpace, K_BACKSPACE },
{ GDK_KEY_Tab, K_TAB },
{ GDK_KEY_Return, K_ENTER },
{ GDK_KEY_Escape, K_ESCAPE },
};
Tuple2<int, int> *x = FindTuple(cv, __countof(cv), kv);
if(x)
kv = x->b;
else
kv += K_DELTA;
if(GetShift())
kv |= K_SHIFT;
if(GetCtrl())
kv |= K_CTRL;
if(GetAlt())
kv |= K_ALT;
LLOG(GetKeyDesc(kv) << ", pressed: " << pressed << ", count: " << CurrentEvent.count);
DispatchKey(!pressed * K_KEYUP + kv, CurrentEvent.count);
}
break;
case EVENT_TEXT: {
WString h = CurrentEvent.value;
for(int i = 0; i < h.GetCount(); i++) // TODO: Add compression
DispatchKey(h[i], 1);
break;
}
case GDK_CONFIGURE: {
Rect rect = CurrentEvent.value;
if(GetRect() != rect)
SetWndRect(rect);
}
break;
default:
return;
}
if(_this)
_this->PostInput();
}
bool Ctrl::ProcessEvent0(bool *quit, bool fetch)
{
ASSERT(IsMainThread());
bool r = false;
if(IsWaitingEvent0(fetch)) {
while(Events.GetCount() > 1) { // Event compression (coalesce autorepeat, mouse moves/wheel, configure)
Event& a = Events[0];
Event& b = Events[1];
if(b.type == a.type && a.windowid == b.windowid && a.state == b.state) {
if(a.type == GDK_KEY_PRESS && a.value == b.value)
b.count += a.count;
else
if(a.type == GDK_SCROLL)
b.value = (int)b.value + (int)a.value;
else
if(findarg(a.type, GDK_MOTION_NOTIFY, GDK_CONFIGURE) < 0)
break;
Events.DropHead();
}
else
break;
}
Event& e = Events.Head();
CurrentTime = e.time;
CurrentMousePos = e.mousepos;
CurrentState = e.state;
CurrentEvent = e;
Value val = e.value;
Events.DropHead();
Ctrl *w = GetTopCtrlFromId(e.windowid);
if(w)
w->Proc();
r = true;
}
if(quit)
*quit = IsEndSession();
return r;
}
bool Ctrl::ProcessEvent(bool *quit)
{
return ProcessEvent0(quit, true);
}
gboolean Ctrl::TimeHandler(GtkWidget *)
{
return true;
}
void SweepMkImageCache();
bool Ctrl::ProcessEvents0(bool *quit, bool fetch)
{
bool r = false;
while(IsWaitingEvent0(fetch) && (!LoopCtrl || LoopCtrl->InLoop()))
r = ProcessEvent0(quit, fetch) || r;
TimerProc(GetTickCount());
AnimateCaret();
if(quit)
*quit = IsEndSession();
for(int i = 0; i < wins.GetCount(); i++)
if(wins[i].ctrl)
wins[i].ctrl->SyncScroll();
gdk_window_process_all_updates();
FetchEvents(FALSE); // To perform any pending GDK_EXPOSE
gdk_flush();
return r;
}
bool Ctrl::ProcessEvents(bool *quit)
{
return ProcessEvents0(quit, true);
}
void Ctrl::SysEndLoop()
{
}
void WakeUpGuiThread()
{
g_main_context_wakeup(g_main_context_default());
}
void Ctrl::EventLoop0(Ctrl *ctrl)
{
GuiLock __;
ASSERT(IsMainThread());
ASSERT(LoopLevel == 0 || ctrl);
LoopLevel++;
LLOG("Entering event loop at level " << LoopLevel << LOG_BEGIN);
if(!GetMouseRight() && !GetMouseMiddle() && !GetMouseLeft())
ReleaseCtrlCapture();
Ptr<Ctrl> ploop;
if(ctrl) {
ploop = LoopCtrl;
LoopCtrl = ctrl;
ctrl->inloop = true;
}
while(!IsEndSession() && (ctrl ? ctrl->IsOpen() && ctrl->InLoop() : GetTopCtrls().GetCount()))
{
FetchEvents(TRUE);
ProcessEvents();
}
if(ctrl)
LoopCtrl = ploop;
LoopLevel--;
LLOG(LOG_END << "Leaving event loop ");
}
gboolean sOnce(GtkWidget *)
{
return false;
}
void Ctrl::GuiSleep0(int ms)
{
GuiLock __;
if(ms < 20) // Periodic timer is each 20ms, so that is the longest possible wait
g_timeout_add(ms, (GSourceFunc) sOnce, NULL); // otherwise setup shorter timer
FetchEvents(TRUE);
}
END_UPP_NAMESPACE
#endif

111
rainbow/Gtk/GtkKeys.h Normal file
View file

@ -0,0 +1,111 @@
K_BACK = 8,
K_BACKSPACE = 8,
K_TAB = 9,
K_RETURN = 13,
K_ENTER = 13,
K_ESCAPE = 27,
K_SPACE = 32,
K_DELETE = GDK_KEY_Delete|K_DELTA,
K_SHIFT_KEY = GDK_KEY_Shift_L|K_DELTA,
K_CTRL_KEY = GDK_KEY_Control_L|K_DELTA,
K_ALT_KEY = GDK_KEY_Meta_L|K_DELTA,
K_CAPSLOCK = GDK_KEY_Caps_Lock|K_DELTA,
K_PRIOR = GDK_KEY_Page_Up|K_DELTA,
K_PAGEUP = GDK_KEY_Page_Up|K_DELTA,
K_NEXT = GDK_KEY_Page_Down|K_DELTA,
K_PAGEDOWN = GDK_KEY_Page_Down|K_DELTA,
K_END = GDK_KEY_End|K_DELTA,
K_HOME = GDK_KEY_Home|K_DELTA,
K_LEFT = GDK_KEY_Left|K_DELTA,
K_UP = GDK_KEY_Up|K_DELTA,
K_RIGHT = GDK_KEY_Right|K_DELTA,
K_DOWN = GDK_KEY_Down|K_DELTA,
K_INSERT = GDK_KEY_Insert|K_DELTA,
K_NUMPAD0 = GDK_KEY_KP_0|K_DELTA,
K_NUMPAD1 = GDK_KEY_KP_1|K_DELTA,
K_NUMPAD2 = GDK_KEY_KP_2|K_DELTA,
K_NUMPAD3 = GDK_KEY_KP_3|K_DELTA,
K_NUMPAD4 = GDK_KEY_KP_4|K_DELTA,
K_NUMPAD5 = GDK_KEY_KP_5|K_DELTA,
K_NUMPAD6 = GDK_KEY_KP_6|K_DELTA,
K_NUMPAD7 = GDK_KEY_KP_7|K_DELTA,
K_NUMPAD8 = GDK_KEY_KP_8|K_DELTA,
K_NUMPAD9 = GDK_KEY_KP_9|K_DELTA,
K_MULTIPLY = GDK_KEY_KP_Multiply|K_DELTA,
K_ADD = GDK_KEY_KP_Add|K_DELTA,
K_SEPARATOR = GDK_KEY_KP_Separator|K_DELTA,
K_SUBTRACT = GDK_KEY_KP_Subtract|K_DELTA,
K_DECIMAL = GDK_KEY_KP_Decimal|K_DELTA,
K_DIVIDE = GDK_KEY_KP_Divide|K_DELTA,
K_SCROLL = GDK_KEY_Scroll_Lock|K_DELTA,
K_F1 = GDK_KEY_F1|K_DELTA,
K_F2 = GDK_KEY_F2|K_DELTA,
K_F3 = GDK_KEY_F3|K_DELTA,
K_F4 = GDK_KEY_F4|K_DELTA,
K_F5 = GDK_KEY_F5|K_DELTA,
K_F6 = GDK_KEY_F6|K_DELTA,
K_F7 = GDK_KEY_F7|K_DELTA,
K_F8 = GDK_KEY_F8|K_DELTA,
K_F9 = GDK_KEY_F9|K_DELTA,
K_F10 = GDK_KEY_F10|K_DELTA,
K_F11 = GDK_KEY_F11|K_DELTA,
K_F12 = GDK_KEY_F12|K_DELTA,
K_A = GDK_KEY_A|K_DELTA,
K_B = GDK_KEY_B|K_DELTA,
K_C = GDK_KEY_C|K_DELTA,
K_D = GDK_KEY_D|K_DELTA,
K_E = GDK_KEY_E|K_DELTA,
K_F = GDK_KEY_F|K_DELTA,
K_G = GDK_KEY_G|K_DELTA,
K_H = GDK_KEY_H|K_DELTA,
K_I = GDK_KEY_I|K_DELTA,
K_J = GDK_KEY_J|K_DELTA,
K_K = GDK_KEY_K|K_DELTA,
K_L = GDK_KEY_L|K_DELTA,
K_M = GDK_KEY_M|K_DELTA,
K_N = GDK_KEY_N|K_DELTA,
K_O = GDK_KEY_O|K_DELTA,
K_P = GDK_KEY_P|K_DELTA,
K_Q = GDK_KEY_Q|K_DELTA,
K_R = GDK_KEY_R|K_DELTA,
K_S = GDK_KEY_S|K_DELTA,
K_T = GDK_KEY_T|K_DELTA,
K_U = GDK_KEY_U|K_DELTA,
K_V = GDK_KEY_V|K_DELTA,
K_W = GDK_KEY_W|K_DELTA,
K_X = GDK_KEY_X|K_DELTA,
K_Y = GDK_KEY_Y|K_DELTA,
K_Z = GDK_KEY_Z|K_DELTA,
K_0 = GDK_KEY_0|K_DELTA,
K_1 = GDK_KEY_1|K_DELTA,
K_2 = GDK_KEY_2|K_DELTA,
K_3 = GDK_KEY_3|K_DELTA,
K_4 = GDK_KEY_4|K_DELTA,
K_5 = GDK_KEY_5|K_DELTA,
K_6 = GDK_KEY_6|K_DELTA,
K_7 = GDK_KEY_7|K_DELTA,
K_8 = GDK_KEY_8|K_DELTA,
K_9 = GDK_KEY_9|K_DELTA,
K_CTRL_LBRACKET = K_CTRL|GDK_KEY_bracketleft|K_DELTA,
K_CTRL_RBRACKET = K_CTRL|GDK_KEY_bracketright|K_DELTA,
K_CTRL_MINUS = K_CTRL|GDK_KEY_minus|K_DELTA,
K_CTRL_GRAVE = K_CTRL|GDK_KEY_grave|K_DELTA,
K_CTRL_SLASH = K_CTRL|GDK_KEY_slash|K_DELTA,
K_CTRL_BACKSLASH = K_CTRL|GDK_KEY_backslash|K_DELTA,
K_CTRL_COMMA = K_CTRL|GDK_KEY_comma|K_DELTA,
K_CTRL_PERIOD = K_CTRL|GDK_KEY_period|K_DELTA,
K_CTRL_SEMICOLON = K_CTRL|GDK_KEY_semicolon|K_DELTA,
K_CTRL_EQUAL = K_CTRL|GDK_KEY_equal|K_DELTA,
K_CTRL_APOSTROPHE= K_CTRL|GDK_KEY_apostrophe|K_DELTA,
K_BREAK = GDK_KEY_Break|K_DELTA,

252
rainbow/Gtk/GtkTop.cpp Normal file
View file

@ -0,0 +1,252 @@
#include <CtrlCore/CtrlCore.h>
#ifdef GUI_GTK
NAMESPACE_UPP
#define LLOG(x) // DLOG(x)
void TopWindow::SyncSizeHints()
{
GuiLock __;
if(!top)
return;
GdkGeometry m;
Size sz0 = GetRect().GetSize();
Size sz = sz0;
if(sizeable)
sz = GetMinSize();
m.min_width = sz.cx;
m.min_height = sz.cy;
sz = sz0;
if(sizeable)
sz = GetMaxSize();
m.max_width = sz.cx;
m.max_height = sz.cy;
gtk_window_set_resizable(gtk(), sizeable);
gtk_window_set_geometry_hints(gtk(), top->window, &m, GdkWindowHints(GDK_HINT_MIN_SIZE|GDK_HINT_MAX_SIZE));
}
void TopWindow::SyncTitle0()
{
GuiLock __;
if(top)
gtk_window_set_title(gtk(), FromUnicode(title, CHARSET_UTF8));
}
void TopWindow::SyncCaption0()
{
GuiLock __;
SyncTitle0();
if(top) {
if(gdk_icon.Set(icon))
gtk_window_set_icon(gtk(), gdk_icon);
gtk_window_set_decorated(gtk(), !frameless);
gtk_window_set_urgency_hint(gtk(), urgent);
}
}
void TopWindow::CenterRect(Ctrl *owner)
{
GuiLock __;
SetupRect();
if(owner && center == 1 || center == 2) {
Size sz = GetRect().Size();
Rect r, wr;
wr = Ctrl::GetWorkArea();
// TODO: Add Frame support
if(center == 1)
r = owner->GetRect();
else
r = wr;
Point p = r.CenterPos(sz);
r = RectC(p.x, p.y, sz.cx, sz.cy);
if(r.top < wr.top) {
r.bottom += wr.top - r.top;
r.top = wr.top;
}
if(r.bottom > wr.bottom)
r.bottom = wr.bottom;
minsize.cx = min(minsize.cx, r.GetWidth());
minsize.cy = min(minsize.cy, r.GetHeight());
SetRect(r);
}
}
gboolean TopWindow::StateEvent(GtkWidget *widget, GdkEventWindowState *event, gpointer user_data)
{
TopWindow *w = (TopWindow *)user_data;
dword h = event->new_window_state;
if(h & GDK_WINDOW_STATE_FULLSCREEN)
w->state = FULLSCREEN;
else
if(h & GDK_WINDOW_STATE_ICONIFIED)
w->state = MINIMIZED;
else
if(h & GDK_WINDOW_STATE_MAXIMIZED)
w->state = MAXIMIZED;
else
w->state = OVERLAPPED;
w->topmost = h & GDK_WINDOW_STATE_ABOVE;
return FALSE;
}
void TopWindow::Open(Ctrl *owner)
{
GuiLock __;
LLOG("OPEN " << Name() << " owner: " << UPP::Name(owner));
if(dokeys && (!GUI_AKD_Conservative() || GetAccessKeysDeep() <= 1))
DistributeAccessKeys();
if(fullscreen)
SetRect(GetPrimaryScreenArea());
else
CenterRect(owner);
IgnoreMouseUp();
Create(owner, false);
g_signal_connect(top->window, "window-state-event", G_CALLBACK(StateEvent), this);
SyncSizeHints();
SyncCaption();
PlaceFocus();
int q = state;
state = OVERLAPPED;
SetMode(q);
SyncTopMost();
}
void TopWindow::Open()
{
Open(GetActiveWindow()); //TODO!
}
void TopWindow::OpenMain()
{
Open(NULL);
}
void TopWindow::SyncTopMost()
{
if(top)
gtk_window_set_keep_above(gtk(), topmost);
}
void TopWindow::SetMode(int mode)
{
GtkWindow *w = gtk();
if(w)
switch(state) {
case MINIMIZED:
gtk_window_deiconify(w);
break;
case MAXIMIZED:
gtk_window_unmaximize(w);
break;
case FULLSCREEN:
gtk_window_unfullscreen(w);
break;
}
state = mode;
if(w)
switch(state) {
case MINIMIZED:
gtk_window_iconify(w);
break;
case MAXIMIZED:
gtk_window_maximize(w);
break;
case FULLSCREEN:
gtk_window_fullscreen(w);
break;
}
}
void TopWindow::Minimize(bool effect)
{
SetMode(MINIMIZED);
}
TopWindow& TopWindow::FullScreen(bool b)
{
SetMode(FULLSCREEN);
return *this;
}
void TopWindow::Maximize(bool effect)
{
SetMode(MAXIMIZED);
}
void TopWindow::Overlap(bool effect)
{
SetMode(OVERLAPPED);
}
TopWindow& TopWindow::TopMost(bool b, bool)
{
GuiLock __;
topmost = b;
SyncTopMost();
return *this;
}
bool TopWindow::IsTopMost() const
{
GuiLock __;
return topmost;
}
void TopWindow::GuiPlatformConstruct()
{
}
void TopWindow::GuiPlatformDestruct()
{
}
void TopWindow::SerializePlacement(Stream& s, bool reminimize)
{
GuiLock __;
int version = 0;
s / version;
Rect rect = GetRect();
s % overlapped % rect;
bool mn = state == MINIMIZED;
bool mx = state == MAXIMIZED;
s.Pack(mn, mx);
LLOG("TopWindow::SerializePlacement / " << (s.IsStoring() ? "write" : "read"));
LLOG("minimized = " << mn << ", maximized = " << mx);
LLOG("rect = " << rect << ", overlapped = " << overlapped);
if(s.IsLoading()) {
if(mn) rect = overlapped;
Rect limit = GetWorkArea();
Rect fm = windowFrameMargin;
if((fm.left|fm.right|fm.top|fm.bottom) == 0)
fm = Rect(8, 32, 8, 8);
limit.left += fm.left;
limit.right -= fm.right;
limit.top += fm.top;
limit.bottom -= fm.bottom;
Size sz = min(rect.Size(), limit.Size());
rect = RectC(
minmax(rect.left, limit.left, limit.right - sz.cx),
minmax(rect.top, limit.top, limit.bottom - sz.cy),
sz.cx, sz.cy);
state = OVERLAPPED;
if(mn && reminimize)
state = MINIMIZED;
if(mx)
state = MAXIMIZED;
if(state == OVERLAPPED)
SetRect(rect);
if(IsOpen()) {
if(state == MINIMIZED)
Minimize(false);
if(state == MAXIMIZED)
Maximize(false);
}
}
}
END_UPP_NAMESPACE
#endif

14
rainbow/Gtk/GtkTop.h Normal file
View file

@ -0,0 +1,14 @@
//$ class TopWindow : Ctrl {
ImageGdk gdk_icon;
bool topmost;
enum { FULLSCREEN = 99 };
void CenterRect(Ctrl *owner);
void SetMode(int mode);
void SyncTopMost();
static gboolean StateEvent(GtkWidget *widget, GdkEventWindowState *event, gpointer user_data);
friend class Ctrl;
//$ };

149
rainbow/Gtk/GtkUtil.cpp Normal file
View file

@ -0,0 +1,149 @@
#include <CtrlCore/CtrlCore.h>
#ifdef GUI_GTK
NAMESPACE_UPP
void SetSurface(SystemDraw& w, const Rect& dest, const RGBA *pixels, Size psz, Point poff)
{
}
void DrawDragLine(SystemDraw& w, bool horz, int x, int y, int len, int n, const int *pattern, Color color, int animation)
{
if(len <= 0)
return;
if(horz)
w.Clip(x, y, len, n);
else
w.Clip(x, y, n, len);
(horz ? x : y) -= animation;
len += animation;
bool ch = false;
while(len > 0) {
int segment = pattern[ch];
int d = segment + pattern[2];
if(horz) {
w.DrawRect(x, y, segment, n, color);
x += d;
}
else {
w.DrawRect(x, y, n, segment, color);
y += d;
}
len -= d;
ch = !ch;
}
w.End();
}
void DrawDragFrame(SystemDraw& w, const Rect& r, int n, const int *pattern, Color color, int animation)
{
DrawDragLine(w, true, r.left, r.top, r.GetWidth(), n, pattern, color, animation);
DrawDragLine(w, false, r.left, r.top + n, r.GetHeight() - 2 * n, n, pattern, color, animation);
DrawDragLine(w, false, r.right - n, r.top + n, r.GetHeight() - 2 * n, n, pattern, color, animation);
DrawDragLine(w, true, r.left, r.bottom - n, r.GetWidth(), n, pattern, color, animation);
}
void DrawDragRect(Ctrl& q, const DrawDragRectInfo& f)
{
ViewDraw w(&q);
w.Clip(f.clip);
static int dashes[3][3] = {
{ 32, 32, 0 },
{ 1, 1, 1 },
{ 5, 1, 2 },
};
const int *dash = dashes[minmax(f.type, 0, 2)];
Color color = InvertColor;
DrawDragFrame(w, f.rect1, f.n, dash, color, f.animation);
DrawDragFrame(w, f.rect2, f.n, dash, color, f.animation);
w.End();
}
void DrawDragRect(Ctrl& q, const Rect& rect1, const Rect& rect2, const Rect& clip, int n,
Color color, int type, int animation)
{
Ctrl *top = q.GetTopCtrl();
if(top && top->top) {
Rect sv = q.GetScreenView();
Rect tv = top->GetScreenView();
Point off = sv.TopLeft() - tv.TopLeft();
DrawDragRectInfo& f = top->top->dr.Create();
f.rect1 = rect1 + off;
f.rect2 = rect2 + off;
f.clip = (clip & q.GetSize()) + off;
f.n = n;
f.color = color;
f.type = type;
f.animation = animation;
DrawDragRect(*top, f);
}
}
void FinishDragRect(Ctrl& q)
{
Ctrl *top = q.GetTopCtrl();
if(top && top->top && top->top->dr) {
DrawDragRect(*top, *top->top->dr);
top->top->dr.Clear();
}
}
GdkRect::GdkRect(const Rect& r)
{
x = r.left;
y = r.top;
width = r.GetWidth();
height = r.GetHeight();
}
Image ImageFromPixbufUnref(GdkPixbuf *pixbuf)
{
Image img;
if(pixbuf) {
if(gdk_pixbuf_get_n_channels (pixbuf) == 4 &&
gdk_pixbuf_get_colorspace (pixbuf) == GDK_COLORSPACE_RGB &&
gdk_pixbuf_get_bits_per_sample (pixbuf) == 8 &&
gdk_pixbuf_get_has_alpha (pixbuf)) {
Size sz(gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height(pixbuf));
ImageBuffer m(sz);
int stride = gdk_pixbuf_get_rowstride(pixbuf);
byte *l = (byte *)gdk_pixbuf_get_pixels(pixbuf);
for(int y = 0; y < sz.cy; y++) {
RGBA *s = m[y];
const RGBA *e = s + sz.cx;
const byte *t = l;
while(s < e) {
s->r = *t++;
s->g = *t++;
s->b = *t++;
s->a = *t++;
s++;
}
l += stride;
}
img = m;
}
g_object_unref(pixbuf);
}
return img;
}
GdkAtom GAtom(const String& id)
{
GuiLock __;
static VectorMap<String, GdkAtom> m;
int q = m.Find(id);
return q >= 0 ? m[q] : (m.Add(id) = gdk_atom_intern(~id, FALSE));
}
int rmsecs()
{
static int msecs0 = msecs();
return msecs(msecs0);
}
END_UPP_NAMESPACE
#endif

474
rainbow/Gtk/GtkWnd.cpp Normal file
View file

@ -0,0 +1,474 @@
#include <CtrlCore/CtrlCore.h>
#ifdef GUI_GTK
NAMESPACE_UPP
#define LLOG(x) // DLOG(x)
Vector<Ctrl::Win> Ctrl::wins;
int Ctrl::WndCaretTime;
bool Ctrl::WndCaretVisible;
int Ctrl::FindId(int id)
{
for(int i = 0; i < wins.GetCount(); i++)
if(wins[i].id == id)
return i;
return -1;
}
int Ctrl::FindCtrl(Ctrl *ctrl)
{
for(int i = 0; i < wins.GetCount(); i++)
if(wins[i].ctrl == ctrl)
return i;
return -1;
}
int Ctrl::FindGtkWindow(GtkWidget *gtk)
{
for(int i = 0; i < wins.GetCount(); i++)
if(wins[i].gtk == gtk)
return i;
return -1;
}
int Ctrl::FindGdkWindow(GdkWindow *gdk)
{
for(int i = 0; i < wins.GetCount(); i++)
if(wins[i].gdk == gdk)
return i;
return -1;
}
bool Ctrl::IsAlphaSupported()
{
return false;
}
bool Ctrl::IsCompositedGui()
{
return false;
}
Vector<Ctrl *> Ctrl::GetTopCtrls()
{
GuiLock __;
Vector<Ctrl *> h;
for(int i = 0; i < wins.GetCount(); i++)
h.Add(wins[i].ctrl);
return h;
}
void Ctrl::SetMouseCursor(const Image& image)
{
GuiLock __;
int64 id = image.GetSerialId();
Ctrl *topctrl = NULL;
Top *top = NULL;
if(mouseCtrl)
topctrl = mouseCtrl->GetTopCtrl();
if(topctrl)
top = topctrl->top;
if(top && id != top->cursor_id) {
top->cursor_id = id;
int64 aux = image.GetAuxData();
GdkCursor *c = NULL;
if(aux)
c = gdk_cursor_new((GdkCursorType)(aux - 1));
else
if(IsNull(image))
c = gdk_cursor_new(GDK_BLANK_CURSOR);
else {
Point p = image.GetHotSpot();
ImageGdk m;
m.Set(image);
GdkPixbuf *pb = m;
if(pb)
c = gdk_cursor_new_from_pixbuf(gdk_display_get_default(), pb, p.x, p.y);
}
if(c) {
gdk_window_set_cursor(topctrl->gdk(), c);
gdk_cursor_unref(c);
}
}
}
Ctrl *Ctrl::GetOwner()
{
GuiLock __;
return top ? top->owner : NULL;
}
Ctrl *Ctrl::GetActiveCtrl()
{
GuiLock __;
return focusCtrl ? focusCtrl->GetTopCtrl() : NULL;
}
// Vector<Callback> Ctrl::hotkey;
int Ctrl::RegisterSystemHotKey(dword key, Callback cb)
{
/* ASSERT(key >= K_DELTA);
int q = hotkey.GetCount();
for(int i = 0; i < hotkey.GetCount(); i++)
if(!hotkey[i]) {
q = i;
break;
}
hotkey.At(q) = cb;
dword mod = 0;
if(key & K_ALT)
mod |= MOD_ALT;
if(key & K_SHIFT)
mod |= MOD_SHIFT;
if(key & K_CTRL)
mod |= MOD_CONTROL;
return RegisterHotKey(NULL, q, mod, key & 0xffff) ? q : -1;*/
return -1;
}
void Ctrl::UnregisterSystemHotKey(int id)
{
/* if(id >= 0 && id < hotkey.GetCount()) {
UnregisterHotKey(NULL, id);
hotkey[id].Clear();
}*/
}
void Ctrl::FocusSync()
{
GuiLock __;
if(focusCtrlWnd && gtk_window_is_active(focusCtrlWnd->gtk()))
return;
Ptr<Ctrl> focus = NULL;
static Ctrl *ctrl;
for(int i = 0; i < wins.GetCount(); i++)
if(gtk_window_is_active((GtkWindow *)wins[i].gtk)) {
focus = wins[i].ctrl;
break;
}
if(focus != ctrl) {
if(ctrl)
ctrl->KillFocusWnd();
ctrl = focus;
if(ctrl)
ctrl->SetFocusWnd();
}
}
void Ctrl::AnimateCaret()
{
GuiLock __;
int v = !(((GetTickCount() - WndCaretTime) / 500) & 1);
if(v != WndCaretVisible) {
WndCaretVisible = v;
RefreshCaret();
}
}
void Ctrl::PaintCaret(SystemDraw& w)
{
GuiLock __;
LLOG("PaintCaret " << Name() << ", caretCtrl: " << caretCtrl << ", WndCaretVisible: " << WndCaretVisible);
if(this == caretCtrl && WndCaretVisible)
w.DrawRect(caretx, carety, caretcx, caretcy, InvertColor);
}
void Ctrl::SetCaret(int x, int y, int cx, int cy)
{
GuiLock __;
LLOG("SetCaret " << Name());
if(this == caretCtrl)
RefreshCaret();
caretx = x;
carety = y;
caretcx = cx;
caretcy = cy;
if(this == caretCtrl) {
WndCaretTime = GetTickCount();
RefreshCaret();
AnimateCaret();
}
}
void Ctrl::SyncCaret() {
GuiLock __;
if(focusCtrl != caretCtrl) {
LLOG("SyncCaret DO " << Upp::Name(caretCtrl) << " -> " << Upp::Name(focusCtrl));
RefreshCaret();
caretCtrl = focusCtrl;
RefreshCaret();
}
}
Rect Ctrl::GetWndScreenRect() const
{
GuiLock __;
if(top) {
gint x, y;
gdk_window_get_position(gdk(), &x, &y);
gint width = gdk_window_get_width(gdk());
gint height = gdk_window_get_height(gdk());
return RectC(x, y, width, height);
}
return Null;
}
void Ctrl::WndShow0(bool b)
{
GuiLock __;
LLOG("WndShow " << Name() << ", " << b);
if(top) {
if(b)
gtk_widget_show_now(top->window);
else
gtk_widget_hide(top->window);
StateH(SHOW);
}
}
bool Ctrl::IsWndOpen() const {
GuiLock __;
return top && top->window && top->window->window;
}
void Ctrl::SetAlpha(byte alpha)
{
GuiLock __;
}
Rect Ctrl::GetWorkArea() const
{
GuiLock __;
return GetWorkArea(GetRect().TopLeft());
}
void Ctrl::GetWorkArea(Array<Rect>& rc)
{
GuiLock __;
GdkScreen *s = gdk_screen_get_default();
int n = gdk_screen_get_n_monitors(s);
rc.Clear();
for(int i = 0; i < n; i++) {
GdkRectangle r;
gdk_screen_get_monitor_geometry(s, i, &r); // TODO: Use WorkArea (for GTK 3.4)
rc.Add(RectC(r.x, r.y, r.width, r.height));
}
}
Rect Ctrl::GetWorkArea(Point pt)
{
Array<Rect> rc;
GetWorkArea(rc);
for(int i = 0; i < rc.GetCount(); i++)
if(rc[i].Contains(pt))
return rc[i];
return GetPrimaryWorkArea();
}
Rect Ctrl::GetVirtualWorkArea()
{
Rect out = GetPrimaryWorkArea();
Array<Rect> rc;
GetWorkArea(rc);
for(int i = 0; i < rc.GetCount(); i++)
out |= rc[i];
return out;
}
Rect Ctrl::GetVirtualScreenArea()
{
GuiLock __;
gint x, y, width, height;
gdk_window_get_geometry(gdk_screen_get_root_window(gdk_screen_get_default()),
&x, &y, &width, &height, NULL);
return RectC(x, y, width, height);
}
Rect Ctrl::GetPrimaryWorkArea()
{
Array<Rect> rc;
GetWorkArea(rc);
return rc.GetCount() ? rc[0] : RectC(0, 0, 0, 0);
}
Rect Ctrl::GetPrimaryScreenArea()
{
return GetPrimaryWorkArea();
}
int Ctrl::GetKbdDelay()
{
GuiLock __;
return 500;
}
int Ctrl::GetKbdSpeed()
{
GuiLock __;
return 1000 / 32;
}
void Ctrl::SetWndForeground0()
{
GuiLock __;
if(top)
gtk_window_present(gtk());
}
bool Ctrl::IsWndForeground() const
{
GuiLock __;
LLOG("IsWndForeground");
return top && gtk_window_is_active(gtk());
}
void Ctrl::WndEnable0(bool *b)
{
GuiLock __;
if(top) {
gtk_widget_set_sensitive(top->window, *b);
StateH(ENABLE);
}
}
void Ctrl::SetWndFocus0(bool *b)
{
GuiLock __;
LLOG("SetWndFocus0 " << top);
if(top) {
LLOG("SetWndFocus0 DO " << top->window);
gdk_window_focus(gdk(), CurrentTime);
*b = true;
}
}
bool Ctrl::HasWndFocus() const
{
GuiLock __;
return top && gtk_widget_is_focus(top->window);
}
void Ctrl::WndInvalidateRect(const Rect& r)
{
GuiLock __;
LLOG("WndInvalidateRect " << r);
gdk_window_invalidate_rect(gdk(), GdkRect(r), TRUE);
// gtk_widget_queue_draw_area(top->window, r.left, r.top, r.GetWidth(), r.GetHeight());
}
void Ctrl::WndScrollView0(const Rect& r, int dx, int dy)
{
GuiLock __;
LLOG("ScrollView " << rect);
WndInvalidateRect(r);
}
bool Ctrl::SweepConfigure(bool wait)
{
bool r = false;
FetchEvents(wait);
for(int i = 0; i < Events.GetCount(); i++) {
Event& e = Events[i];
if(e.type == GDK_CONFIGURE && top->id == e.windowid) {
Rect rect = e.value;
LLOG("SweepConfigure " << rect);
if(GetRect() != rect)
SetWndRect(rect);
r = true;
e.type = EVENT_NONE;
}
}
return r;
}
void Ctrl::WndSetPos0(const Rect& rect)
{
GuiLock __;
LLOG("WndSetPos0 " << rect);
if(!top)
return;
SweepConfigure(false); // Remove any previous GDK_CONFIGURE for this window
gtk_window_move(gtk(), rect.left, rect.top);
gtk_window_resize(gtk(), rect.GetWidth(), rect.GetHeight());
int t0 = msecs();
do { // Wait up to 500ms for corresponding GDK_CONFIGURE to arrive
if(SweepConfigure(true))
break;
}
while(msecs() - t0 < 500);
LLOG("-- WndSetPos0 " << rect << " " << msecs() - t0);
}
void Ctrl::WndUpdate0r(const Rect& r)
{
GuiLock __;
LLOG("WndUpdate0r " << r);
WndUpdate0(); // Not found a way how to update only part of window
}
void Ctrl::WndUpdate0()
{
GuiLock __;
LLOG("WndUpdate0");
gdk_window_process_updates(gdk(), TRUE);
FetchEvents(FALSE); // Should pickup GDK_EXPOSE and repaint the window
gdk_flush();
}
Rect Ctrl::GetDefaultWindowRect()
{
GuiLock __;
Size sz = GetPrimaryWorkArea().GetSize();
static int pos = min(sz.cx / 10, 50);
pos += 10;
int cx = sz.cx * 2 / 3;
int cy = sz.cy * 2 / 3;
if(pos + cx + 50 > sz.cx || pos + cy + 50 > sz.cy)
pos = 0;
return RectC(pos + 20, pos + 20, cx, cy);
}
ViewDraw::ViewDraw(Ctrl *ctrl)
{
EnterGuiMutex();
Ctrl *top = ctrl->GetTopCtrl();
cr = gdk_cairo_create(top->gdk());
Clipoff(ctrl->GetScreenView() - top->GetScreenRect().TopLeft());
}
ViewDraw::~ViewDraw()
{
cairo_destroy(cr);
LeaveGuiMutex();
}
Vector<WString> SplitCmdLine__(const char *cmd)
{
Vector<WString> out;
while(*cmd)
if((byte)*cmd <= ' ')
cmd++;
else if(*cmd == '\"') {
WString quoted;
while(*++cmd && (*cmd != '\"' || *++cmd == '\"'))
quoted.Cat(FromSystemCharset(String(cmd, 1)).ToWString());
out.Add(quoted);
}
else {
const char *begin = cmd;
while((byte)*cmd > ' ')
cmd++;
out.Add(String(begin, cmd).ToWString());
}
return out;
}
END_UPP_NAMESPACE
#endif

3
rainbow/Gtk/init Normal file
View file

@ -0,0 +1,3 @@
#ifndef _Gtk_icpp_init_stub
#define _Gtk_icpp_init_stub
#endif

View file

@ -0,0 +1,12 @@
uses
CtrlLib,
Gtk,
RichEdit;
file
main.cpp;
mainconfig
"" = "GUI GTK",
"" = "GUI";

Some files were not shown because too many files have changed in this diff Show more