mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-21 06:45:39 -06:00
Developing new draw
git-svn-id: svn://ultimatepp.org/upp/trunk@1366 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
39bcf6be6e
commit
97446746c8
11 changed files with 2064 additions and 2127 deletions
1828
newdraw/Draw/Draw.h
1828
newdraw/Draw/Draw.h
File diff suppressed because it is too large
Load diff
|
|
@ -33,7 +33,7 @@ file
|
|||
Font.cpp,
|
||||
FontCR.cpp,
|
||||
FontWin32.cpp,
|
||||
FontX11.cpp,
|
||||
FontFc.cpp,
|
||||
Draw.cpp,
|
||||
DrawText.cpp,
|
||||
DrawData.cpp,
|
||||
|
|
|
|||
|
|
@ -1,194 +1,195 @@
|
|||
#include "Draw.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
|
||||
#define LLOG(x) // LOG(x)
|
||||
#define LTIMING(x) // TIMING(x)
|
||||
|
||||
WString TextUnicode(const char *s, int n, byte cs, Font font)
|
||||
{
|
||||
if(n < 0)
|
||||
n = (int)strlen(s);
|
||||
if(font.GetFace() == Font::SYMBOL) {
|
||||
WStringBuffer b(n);
|
||||
wchar *t = b;
|
||||
while(n > 0) {
|
||||
*t++ = *s++;
|
||||
n--;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
else
|
||||
return ToUnicode(s, n, cs);
|
||||
}
|
||||
|
||||
void Draw::DrawText(int x, int y, int angle, const wchar *text, Font font,
|
||||
Color ink, int n, const int *dx)
|
||||
{
|
||||
if(IsNull(ink)) return;
|
||||
if(n < 0)
|
||||
n = wstrlen(text);
|
||||
Std(font);
|
||||
double sina;
|
||||
double cosa;
|
||||
int d = 0;
|
||||
if(angle)
|
||||
Draw::SinCos(angle, sina, cosa); //TODO global sin tables!
|
||||
for(int i = 0; i < n; i++) {
|
||||
wchar chr = text[i];
|
||||
GlyphInfo gi = GetGlyphInfo(font, chr);
|
||||
if(gi.IsNormal())
|
||||
if(angle)
|
||||
DrawTextOp(int(x + cosa * d), int(y - sina * d), angle, &chr, font, ink, 1, NULL);
|
||||
else {
|
||||
int c = 1;
|
||||
int dd = 0;
|
||||
if(!dx)
|
||||
while(c < n) {
|
||||
GlyphInfo gi2 = GetGlyphInfo(font, text[i + c]);
|
||||
if(!gi2.IsNormal())
|
||||
break;
|
||||
c++;
|
||||
dd += gi.width;
|
||||
gi = gi2;
|
||||
}
|
||||
DrawTextOp(x + d, y, 0, text + i, font, ink, c, NULL);
|
||||
i += c - 1;
|
||||
d += dd;
|
||||
}
|
||||
else
|
||||
if(gi.IsReplaced()) {
|
||||
Font fnt = font;
|
||||
fnt.Face(gi.lspc);
|
||||
fnt.Height(gi.rspc);
|
||||
if(angle)
|
||||
DrawTextOp(int(x + cosa * d), int(y - sina * (font.GetAscent() - fnt.GetAscent() + d)),
|
||||
angle, &chr, fnt, ink, 1, NULL);
|
||||
else
|
||||
DrawTextOp(x + d, y + font.GetAscent() - fnt.GetAscent(), 0, &chr, fnt, ink, 1, NULL);
|
||||
GlyphMetrics(gi, font, chr);
|
||||
}
|
||||
else
|
||||
if(gi.IsComposed()) {
|
||||
ComposedGlyph cg;
|
||||
Compose(font, chr, cg);
|
||||
if(angle) {
|
||||
DrawTextOp(int(x + cosa * d), int(y - sina * d), angle, &cg.basic_char, font, ink, 1, NULL);
|
||||
DrawTextOp(int(x + cosa * (d + cg.mark_pos.x)), int(y - sina * (cg.mark_pos.y + d)), angle, &cg.mark_char, cg.mark_font, ink, 1, NULL);
|
||||
}
|
||||
else {
|
||||
DrawTextOp(x + d, y, angle, &cg.basic_char, font, ink, 1, NULL);
|
||||
DrawTextOp(x + cg.mark_pos.x + d, y + cg.mark_pos.y, angle, &cg.mark_char, cg.mark_font, ink, 1, NULL);
|
||||
}
|
||||
GlyphMetrics(gi, font, chr);
|
||||
}
|
||||
if(dx)
|
||||
d += *dx++;
|
||||
else
|
||||
d += gi.width;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------
|
||||
|
||||
void Draw::DrawText(int x, int y, const wchar *text, Font font,
|
||||
Color ink, int n, const int *dx)
|
||||
{
|
||||
DrawText(x, y, 0, text, font, ink, n, dx);
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
|
||||
void Draw::DrawText(int x, int y, int angle, const WString& text, Font font,
|
||||
Color ink, const int *dx)
|
||||
{
|
||||
DrawText(x, y, angle, ~text, font, ink, text.GetLength(), dx);
|
||||
}
|
||||
|
||||
void Draw::DrawText(int x, int y, const WString& text, Font font, Color ink, const int *dx)
|
||||
{
|
||||
DrawText(x, y, 0, text, font, ink, dx);
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
|
||||
void Draw::DrawText(int x, int y, int angle, const char *text, byte charset, Font font,
|
||||
Color ink, int n, const int *dx)
|
||||
{
|
||||
DrawText(x, y, angle, TextUnicode(text, n, charset, font), font, ink, dx);
|
||||
}
|
||||
|
||||
void Draw::DrawText(int x, int y, const char *text, byte charset, Font font,
|
||||
Color ink, int n, const int *dx)
|
||||
{
|
||||
DrawText(x, y, 0, text, charset, font, ink, n, dx);
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
|
||||
void Draw::DrawText(int x, int y, int angle, const char *text,
|
||||
Font font, Color ink, int n, const int *dx)
|
||||
{
|
||||
DrawText(x, y, angle, text, CHARSET_DEFAULT, font, ink, n, dx);
|
||||
}
|
||||
|
||||
void Draw::DrawText(int x, int y, const char *text, Font font,
|
||||
Color ink, int n, const int *dx)
|
||||
{
|
||||
DrawText(x, y, text, CHARSET_DEFAULT, font, ink, n, dx);
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
|
||||
void Draw::DrawText(int x, int y, int angle, const String& text, Font font,
|
||||
Color ink, const int *dx)
|
||||
{
|
||||
DrawText(x, y, angle, text, font, ink, text.GetLength(), dx);
|
||||
}
|
||||
|
||||
void Draw::DrawText(int x, int y, const String& text, Font font, Color ink, const int *dx)
|
||||
{
|
||||
WString h = TextUnicode(text, text.GetLength(), CHARSET_DEFAULT, font);
|
||||
DrawText(x, y, h, font, ink, h.GetLength(), dx);
|
||||
}
|
||||
|
||||
// --------------------------
|
||||
|
||||
Size GetTextSize(const wchar *text, Font font, int n)
|
||||
{
|
||||
FontInfo fi = font.Info();
|
||||
if(n < 0)
|
||||
n = wstrlen(text);
|
||||
Size sz;
|
||||
sz.cx = 0;
|
||||
const wchar *wtext = (const wchar *)text;
|
||||
while(n > 0) {
|
||||
sz.cx += fi[*wtext++];
|
||||
n--;
|
||||
}
|
||||
sz.cy = fi.GetHeight();
|
||||
return sz;
|
||||
}
|
||||
|
||||
Size GetTextSize(const WString& text, Font font)
|
||||
{
|
||||
return GetTextSize(text, font, text.GetLength());
|
||||
}
|
||||
|
||||
Size GetTextSize(const char *text, byte charset, Font font, int n)
|
||||
{
|
||||
return GetTextSize(TextUnicode(text, n, charset, font), font);
|
||||
}
|
||||
|
||||
Size GetTextSize(const char *text, Font font, int n)
|
||||
{
|
||||
return GetTextSize(text, CHARSET_DEFAULT, font, n);
|
||||
}
|
||||
|
||||
Size GetTextSize(const String& text, Font font)
|
||||
{
|
||||
return GetTextSize(text, font, text.GetLength());
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
#include "Draw.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
|
||||
#define LLOG(x) // LOG(x)
|
||||
#define LTIMING(x) // TIMING(x)
|
||||
|
||||
WString TextUnicode(const char *s, int n, byte cs, Font font)
|
||||
{
|
||||
if(n < 0)
|
||||
n = (int)strlen(s);
|
||||
#ifdef PLATFORM_WIN32
|
||||
if(font.GetFace() == Font::SYMBOL) {
|
||||
WStringBuffer b(n);
|
||||
wchar *t = b;
|
||||
while(n > 0) {
|
||||
*t++ = *s++;
|
||||
n--;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
#endif
|
||||
return ToUnicode(s, n, cs);
|
||||
}
|
||||
|
||||
void Draw::DrawText(int x, int y, int angle, const wchar *text, Font font,
|
||||
Color ink, int n, const int *dx)
|
||||
{
|
||||
if(IsNull(ink)) return;
|
||||
if(n < 0)
|
||||
n = wstrlen(text);
|
||||
Std(font);
|
||||
double sina;
|
||||
double cosa;
|
||||
int d = 0;
|
||||
if(angle)
|
||||
Draw::SinCos(angle, sina, cosa); //TODO global sin tables!
|
||||
for(int i = 0; i < n; i++) {
|
||||
wchar chr = text[i];
|
||||
GlyphInfo gi = GetGlyphInfo(font, chr);
|
||||
if(gi.IsNormal())
|
||||
if(angle)
|
||||
DrawTextOp(int(x + cosa * d), int(y - sina * d), angle, &chr, font, ink, 1, NULL);
|
||||
else {
|
||||
int c = 1;
|
||||
int dd = 0;
|
||||
if(!dx)
|
||||
while(c < n) {
|
||||
GlyphInfo gi2 = GetGlyphInfo(font, text[i + c]);
|
||||
if(!gi2.IsNormal())
|
||||
break;
|
||||
c++;
|
||||
dd += gi.width;
|
||||
gi = gi2;
|
||||
}
|
||||
DrawTextOp(x + d, y, 0, text + i, font, ink, c, NULL);
|
||||
i += c - 1;
|
||||
d += dd;
|
||||
}
|
||||
else
|
||||
if(gi.IsReplaced()) {
|
||||
Font fnt = font;
|
||||
fnt.Face(gi.lspc);
|
||||
fnt.Height(gi.rspc);
|
||||
if(angle)
|
||||
DrawTextOp(int(x + cosa * d), int(y - sina * (font.GetAscent() - fnt.GetAscent() + d)),
|
||||
angle, &chr, fnt, ink, 1, NULL);
|
||||
else
|
||||
DrawTextOp(x + d, y + font.GetAscent() - fnt.GetAscent(), 0, &chr, fnt, ink, 1, NULL);
|
||||
GlyphMetrics(gi, font, chr);
|
||||
}
|
||||
else
|
||||
if(gi.IsComposed()) {
|
||||
ComposedGlyph cg;
|
||||
Compose(font, chr, cg);
|
||||
if(angle) {
|
||||
DrawTextOp(int(x + cosa * d), int(y - sina * d), angle, &cg.basic_char, font, ink, 1, NULL);
|
||||
DrawTextOp(int(x + cosa * (d + cg.mark_pos.x)), int(y - sina * (cg.mark_pos.y + d)), angle, &cg.mark_char, cg.mark_font, ink, 1, NULL);
|
||||
}
|
||||
else {
|
||||
DrawTextOp(x + d, y, angle, &cg.basic_char, font, ink, 1, NULL);
|
||||
DrawTextOp(x + cg.mark_pos.x + d, y + cg.mark_pos.y, angle, &cg.mark_char, cg.mark_font, ink, 1, NULL);
|
||||
}
|
||||
GlyphMetrics(gi, font, chr);
|
||||
}
|
||||
if(dx)
|
||||
d += *dx++;
|
||||
else
|
||||
d += gi.width;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------
|
||||
|
||||
void Draw::DrawText(int x, int y, const wchar *text, Font font,
|
||||
Color ink, int n, const int *dx)
|
||||
{
|
||||
DrawText(x, y, 0, text, font, ink, n, dx);
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
|
||||
void Draw::DrawText(int x, int y, int angle, const WString& text, Font font,
|
||||
Color ink, const int *dx)
|
||||
{
|
||||
DrawText(x, y, angle, ~text, font, ink, text.GetLength(), dx);
|
||||
}
|
||||
|
||||
void Draw::DrawText(int x, int y, const WString& text, Font font, Color ink, const int *dx)
|
||||
{
|
||||
DrawText(x, y, 0, text, font, ink, dx);
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
|
||||
void Draw::DrawText(int x, int y, int angle, const char *text, byte charset, Font font,
|
||||
Color ink, int n, const int *dx)
|
||||
{
|
||||
DrawText(x, y, angle, TextUnicode(text, n, charset, font), font, ink, dx);
|
||||
}
|
||||
|
||||
void Draw::DrawText(int x, int y, const char *text, byte charset, Font font,
|
||||
Color ink, int n, const int *dx)
|
||||
{
|
||||
DrawText(x, y, 0, text, charset, font, ink, n, dx);
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
|
||||
void Draw::DrawText(int x, int y, int angle, const char *text,
|
||||
Font font, Color ink, int n, const int *dx)
|
||||
{
|
||||
DrawText(x, y, angle, text, CHARSET_DEFAULT, font, ink, n, dx);
|
||||
}
|
||||
|
||||
void Draw::DrawText(int x, int y, const char *text, Font font,
|
||||
Color ink, int n, const int *dx)
|
||||
{
|
||||
DrawText(x, y, text, CHARSET_DEFAULT, font, ink, n, dx);
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
|
||||
void Draw::DrawText(int x, int y, int angle, const String& text, Font font,
|
||||
Color ink, const int *dx)
|
||||
{
|
||||
DrawText(x, y, angle, text, font, ink, text.GetLength(), dx);
|
||||
}
|
||||
|
||||
void Draw::DrawText(int x, int y, const String& text, Font font, Color ink, const int *dx)
|
||||
{
|
||||
WString h = TextUnicode(text, text.GetLength(), CHARSET_DEFAULT, font);
|
||||
DrawText(x, y, h, font, ink, h.GetLength(), dx);
|
||||
}
|
||||
|
||||
// --------------------------
|
||||
|
||||
Size GetTextSize(const wchar *text, Font font, int n)
|
||||
{
|
||||
FontInfo fi = font.Info();
|
||||
if(n < 0)
|
||||
n = wstrlen(text);
|
||||
Size sz;
|
||||
sz.cx = 0;
|
||||
const wchar *wtext = (const wchar *)text;
|
||||
while(n > 0) {
|
||||
sz.cx += fi[*wtext++];
|
||||
n--;
|
||||
}
|
||||
sz.cy = fi.GetHeight();
|
||||
return sz;
|
||||
}
|
||||
|
||||
Size GetTextSize(const WString& text, Font font)
|
||||
{
|
||||
return GetTextSize(text, font, text.GetLength());
|
||||
}
|
||||
|
||||
Size GetTextSize(const char *text, byte charset, Font font, int n)
|
||||
{
|
||||
return GetTextSize(TextUnicode(text, n, charset, font), font);
|
||||
}
|
||||
|
||||
Size GetTextSize(const char *text, Font font, int n)
|
||||
{
|
||||
return GetTextSize(text, CHARSET_DEFAULT, font, n);
|
||||
}
|
||||
|
||||
Size GetTextSize(const String& text, Font font)
|
||||
{
|
||||
return GetTextSize(text, font, text.GetLength());
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -7,20 +7,10 @@ NAMESPACE_UPP
|
|||
#define LTIMING(x)
|
||||
#define LLOG(x)
|
||||
|
||||
extern int gtk_antialias;
|
||||
extern int gtk_hinting;
|
||||
extern String gtk_hintstyle;
|
||||
extern String gtk_rgba;
|
||||
|
||||
void Std(Font& font)
|
||||
{
|
||||
if(IsNull(font))
|
||||
font = StdFont();
|
||||
if(font.GetFace() == 0)
|
||||
font.Face(GetStdFont().GetFace());
|
||||
if(font.GetHeight() == 0)
|
||||
font.Height(GetStdFont().GetHeight());
|
||||
}
|
||||
int gtk_antialias = -1;
|
||||
int gtk_hinting = -1;
|
||||
String gtk_hintstyle;
|
||||
String gtk_rgba;
|
||||
|
||||
XftFont *CreateXftFont(Font font, int angle)
|
||||
{
|
||||
|
|
@ -124,8 +114,6 @@ void SystemDraw::DrawTextOp(int x, int y, int angle, const wchar *text, Font fon
|
|||
int ox = x + actual_offset.x;
|
||||
int oy = y + actual_offset.y;
|
||||
SetForeground(ink);
|
||||
SetFont(font, angle);
|
||||
const FontInfo::Data *fd = lastFont.ptr;
|
||||
XftColor c;
|
||||
c.color.red = ink.GetR() << 8;
|
||||
c.color.green = ink.GetG() << 8;
|
||||
|
|
@ -207,11 +195,9 @@ void SystemDraw::DrawTextOp(int x, int y, int angle, const wchar *text, Font fon
|
|||
else
|
||||
cx = GetTextSize(text, font, n).cx;
|
||||
if(font.IsUnderline())
|
||||
DrawRect(x, y + lastFont.GetAscent() + lastFont.ptr->underline_position,
|
||||
cx, lastFont.ptr->underline_thickness, ink);
|
||||
DrawRect(x, y + ascent + underline_position, cx, underline_thickness, ink);
|
||||
if(font.IsStrikeout())
|
||||
DrawRect(x, y + 2 * lastFont.GetAscent() / 3,
|
||||
cx, lastFont.ptr->underline_thickness, ink);
|
||||
DrawRect(x, y + 2 * ascent / 3, cx, underline_thickness, ink);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,15 +43,9 @@ bool Xpalette;
|
|||
|
||||
dword (*Xgetpixel)(int r, int g, int b);
|
||||
|
||||
void StaticExitDraw_()
|
||||
{
|
||||
FontInfo::FreeFonts();
|
||||
}
|
||||
|
||||
EXITBLOCK
|
||||
{
|
||||
if(Xdisplay) {
|
||||
StaticExitDraw_();
|
||||
// No CloseDisplay for now...
|
||||
XCloseDisplay(Xdisplay);
|
||||
LLOG("Xdisplay closed");
|
||||
|
|
@ -223,7 +217,7 @@ void InitX11Draw(XDisplay *display)
|
|||
}
|
||||
// XFree(v);
|
||||
|
||||
FontInfo::SetStdFont(ScreenSans(12));
|
||||
Font::SetStdFont(ScreenSans(12));
|
||||
}
|
||||
|
||||
void InitX11Draw(const char *dispname)
|
||||
|
|
@ -299,14 +293,6 @@ void SystemDraw::SetClip() {
|
|||
UPP::SetClip(gc, xftdraw, clip.Top());
|
||||
}
|
||||
|
||||
void SystemDraw::SetFont(Font font, int angle) {
|
||||
DrawLock __;
|
||||
LLOG("Set font: " << font << " face: " << font.GetFaceName());
|
||||
if(lastFont && lastFont.IsEqual(CHARSET_UNICODE, font, angle))
|
||||
return;
|
||||
lastFont = FontInfo::AcquireFontInfo(font, angle);
|
||||
}
|
||||
|
||||
void SystemDraw::SetLineStyle(int width)
|
||||
{
|
||||
DrawLock __;
|
||||
|
|
@ -340,7 +326,6 @@ void SystemDraw::Init()
|
|||
{
|
||||
DrawLock __;
|
||||
pageSize = Size(Xwidth, Xheight);
|
||||
FontInfo::InitFonts();
|
||||
cloff.Clear();
|
||||
clip.Clear();
|
||||
foreground = linewidth = Null;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
#ifdef PLATFORM_X11
|
||||
|
||||
void SetClip(GC gc, XftDraw *xftdraw, const Vector<Rect>& cl);
|
||||
|
||||
class SystemDraw : public Draw {
|
||||
public:
|
||||
virtual dword GetInfo() const;
|
||||
|
|
@ -93,7 +95,6 @@ public:
|
|||
|
||||
void SetForeground(Color color);
|
||||
void SetLineStyle(int width);
|
||||
void SetFont(Font font, int angle);
|
||||
void SetClip();
|
||||
|
||||
Drawable GetDrawable() const { return dw; }
|
||||
|
|
|
|||
|
|
@ -1,326 +1,341 @@
|
|||
#include "Draw.h"
|
||||
|
||||
#define LLOG(x)
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
CommonFontInfo GetFontInfoSys(Font font);
|
||||
GlyphInfo GetGlyphInfoSys(Font font, int chr);
|
||||
void GetStdFontSys(String& name, int& height);
|
||||
Vector<FaceInfo> GetAllFacesSys();
|
||||
|
||||
bool Replace(Font fnt, int chr, Font& rfnt);
|
||||
|
||||
void Std(Font& font)
|
||||
{
|
||||
if(IsNull(font))
|
||||
font = StdFont();
|
||||
if(font.GetFace() == 0)
|
||||
font.Face(GetStdFont().GetFace());
|
||||
if(font.GetHeight() == 0)
|
||||
font.Height(GetStdFont().GetHeight());
|
||||
}
|
||||
|
||||
Size Font::StdFontSize;
|
||||
Font Font::AStdFont;
|
||||
|
||||
INITBLOCK {
|
||||
RichValue<Font>::Register();
|
||||
}
|
||||
|
||||
const Vector<FaceInfo>& Font::List()
|
||||
{
|
||||
static Vector<FaceInfo> *q;
|
||||
ONCELOCK {
|
||||
static Vector<FaceInfo> x;
|
||||
x = GetAllFacesSys();
|
||||
q = &x;
|
||||
}
|
||||
return *q;
|
||||
}
|
||||
|
||||
void sInitFonts()
|
||||
{
|
||||
Font::List();
|
||||
}
|
||||
|
||||
INITBLOCK {
|
||||
sInitFonts();
|
||||
}
|
||||
|
||||
int Font::GetFaceCount()
|
||||
{
|
||||
return List().GetCount();
|
||||
}
|
||||
|
||||
String Font::GetFaceName(int index)
|
||||
{
|
||||
const Vector<FaceInfo>& l = List();
|
||||
if(index >= 0 && index < l.GetCount())
|
||||
return l[index].name;
|
||||
return Null;
|
||||
}
|
||||
|
||||
dword Font::GetFaceInfo(int index)
|
||||
{
|
||||
const Vector<FaceInfo>& l = List();
|
||||
if(index >= 0 && index < l.GetCount())
|
||||
return l[index].info;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FontFilter(int c)
|
||||
{
|
||||
return c >= 'a' && c <= 'z' || c >= '0' && c <= '9' ? c : c >= 'A' && c <= 'Z' ? ToLower(c) : 0;
|
||||
}
|
||||
|
||||
int Font::FindFaceNameIndex(const String& name) {
|
||||
if(name == "STDFONT")
|
||||
return 0;
|
||||
for(int i = 1; i < GetFaceCount(); i++)
|
||||
if(GetFaceName(i) == name)
|
||||
return i;
|
||||
String n = Filter(name, FontFilter);
|
||||
for(int i = 1; i < GetFaceCount(); i++)
|
||||
if(Filter(GetFaceName(i), FontFilter) == n)
|
||||
return i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Font::SyncStdFont()
|
||||
{
|
||||
DrawLock __;
|
||||
StdFontSize = Size(AStdFont.GetAveWidth(), AStdFont().Bold().GetCy());
|
||||
}
|
||||
|
||||
void Font::SetStdFont(Font font)
|
||||
{
|
||||
DrawLock __;
|
||||
AStdFont = font;
|
||||
SyncStdFont();
|
||||
}
|
||||
|
||||
void Font::InitStdFont()
|
||||
{
|
||||
ONCELOCK {
|
||||
DrawLock __;
|
||||
List();
|
||||
AStdFont = Arial(12);
|
||||
String name;
|
||||
int height = 0;
|
||||
GetStdFontSys(name, height);
|
||||
int q = FindFaceNameIndex(name);
|
||||
if(q > 0)
|
||||
SetStdFont(Font(q, max(height, 1)));
|
||||
}
|
||||
}
|
||||
|
||||
Font Font::GetStdFont()
|
||||
{
|
||||
InitStdFont();
|
||||
return AStdFont;
|
||||
}
|
||||
|
||||
Size Font::GetStdFontSize()
|
||||
{
|
||||
InitStdFont();
|
||||
return StdFontSize;
|
||||
}
|
||||
|
||||
Font StdFont()
|
||||
{
|
||||
return Font(0, Font::GetStdFont().GetHeight());
|
||||
}
|
||||
|
||||
String Font::GetFaceName() const {
|
||||
if(IsNull()) return String();
|
||||
if(GetFace() == 0)
|
||||
return "STDFONT";
|
||||
return GetFaceName(GetFace());
|
||||
}
|
||||
|
||||
dword Font::GetFaceInfo() const {
|
||||
if(IsNull()) return 0;
|
||||
return GetFaceInfo(GetFace());
|
||||
}
|
||||
|
||||
Font& Font::FaceName(const String& name) {
|
||||
int n = FindFaceNameIndex(name);
|
||||
Face(n < 0 ? 0xffff : n);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Font::Serialize(Stream& s) {
|
||||
int version = 1;
|
||||
s / version;
|
||||
if(version >= 1) {
|
||||
int f = GetFace();
|
||||
if(f > COURIER)
|
||||
f = -1;
|
||||
s / f;
|
||||
String name;
|
||||
if(f < 0) {
|
||||
name = GetFaceName();
|
||||
s % name;
|
||||
}
|
||||
if(s.IsLoading())
|
||||
if(f >= 0)
|
||||
Face(f);
|
||||
else
|
||||
FaceName(name);
|
||||
}
|
||||
else {
|
||||
String name = GetFaceName();
|
||||
s % name;
|
||||
if(s.IsLoading()) {
|
||||
FaceName(name);
|
||||
if(IsNull())
|
||||
Face(COURIER);
|
||||
}
|
||||
}
|
||||
s % v.flags % v.height % v.width;
|
||||
}
|
||||
|
||||
template<>
|
||||
String AsString(const Font& f) {
|
||||
if(IsNull(f)) return "<null>";
|
||||
String s = "<" + f.GetFaceName() + Format(":%d", f.GetHeight());
|
||||
if(f.IsBold())
|
||||
s += " Bold";
|
||||
if(f.IsItalic())
|
||||
s += " Italic";
|
||||
if(f.IsUnderline())
|
||||
s += " Underline";
|
||||
if(f.IsStrikeout())
|
||||
s += " Strikeout";
|
||||
return s + '>';
|
||||
}
|
||||
|
||||
struct CharEntry {
|
||||
int64 font;
|
||||
GlyphInfo info;
|
||||
word chr;
|
||||
};
|
||||
|
||||
CharEntry fc_cache_global[4093];
|
||||
|
||||
bool IsNormal(Font font, int chr)
|
||||
{
|
||||
DrawLock __;
|
||||
CharEntry& e = fc_cache_global[CombineHash(font.GetHashValue(), chr) % 4093];
|
||||
if(e.font == font.AsInt64() || e.chr == chr)
|
||||
return e.info.IsNormal();
|
||||
return GetGlyphInfoSys(font, chr).IsNormal();
|
||||
}
|
||||
|
||||
CharEntry GetGlyphEntry(Font font, int chr, unsigned hash)
|
||||
{
|
||||
DrawLock __;
|
||||
CharEntry& e = fc_cache_global[hash % 4093];
|
||||
if(e.font != font.AsInt64() || e.chr != chr) {
|
||||
e.font = font.AsInt64();
|
||||
e.chr = chr;
|
||||
e.info = GetGlyphInfoSys(font, chr);
|
||||
if(!e.info.IsNormal()) {
|
||||
ComposedGlyph cg;
|
||||
Font rfnt;
|
||||
if(Compose(font, chr, cg)) {
|
||||
e.info.lspc = -1;
|
||||
e.info.rspc = cg.basic_char;
|
||||
}
|
||||
else
|
||||
if(Replace(font, chr, rfnt)) {
|
||||
e.info.lspc = rfnt.GetFace();
|
||||
e.info.rspc = rfnt.GetHeight();
|
||||
}
|
||||
else
|
||||
e.info.lspc = -2;
|
||||
}
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
thread__ CharEntry fc_cache[512];
|
||||
|
||||
GlyphInfo GetGlyphInfo(Font font, int chr)
|
||||
{
|
||||
Std(font);
|
||||
unsigned hash = CombineHash(font.GetHashValue(), chr);
|
||||
CharEntry& e = fc_cache[hash & 511];
|
||||
if(e.font != font.AsInt64() || e.chr != chr)
|
||||
e = GetGlyphEntry(font, chr, hash);
|
||||
return e.info;
|
||||
}
|
||||
|
||||
void GlyphMetrics(GlyphInfo& f, Font font, int chr)
|
||||
{
|
||||
if(f.IsReplaced())
|
||||
f = GetGlyphInfo(font().Face(f.lspc).Height(f.rspc), chr);
|
||||
if(f.IsComposed()) {
|
||||
f = GetGlyphInfo(font, f.rspc);
|
||||
if(f.IsComposedLM())
|
||||
f.rspc += f.width / 2;
|
||||
}
|
||||
}
|
||||
|
||||
GlyphInfo GetGlyphMetrics(Font font, int chr)
|
||||
{
|
||||
GlyphInfo f = GetGlyphInfo(font, chr);
|
||||
if(f.IsMissing())
|
||||
f = GetGlyphInfo(font, '?');
|
||||
GlyphMetrics(f, font, chr);
|
||||
return f;
|
||||
}
|
||||
|
||||
struct FontEntry {
|
||||
CommonFontInfo info;
|
||||
int64 font;
|
||||
};
|
||||
|
||||
thread__ FontEntry fi_cache[64];
|
||||
|
||||
const CommonFontInfo& GetFontInfo(Font font)
|
||||
{
|
||||
Std(font);
|
||||
unsigned hash = font.GetHashValue() & 63;
|
||||
FontEntry& e = fi_cache[hash];
|
||||
if(e.font != font.AsInt64()) {
|
||||
DrawLock __;
|
||||
e.font = font.AsInt64();
|
||||
e.info = GetFontInfoSys(font);
|
||||
}
|
||||
return e.info;
|
||||
}
|
||||
|
||||
int Font::GetWidth(int c) const {
|
||||
return GetGlyphMetrics(*this, c).width;
|
||||
}
|
||||
|
||||
int Font::GetLeftSpace(int c) const {
|
||||
return GetGlyphMetrics(*this, c).lspc;
|
||||
}
|
||||
|
||||
int Font::GetRightSpace(int c) const {
|
||||
return GetGlyphMetrics(*this, c).rspc;
|
||||
}
|
||||
|
||||
thread__ int64 lastFiFont = INT_MIN;
|
||||
thread__ CommonFontInfo lastFontInfo;
|
||||
|
||||
const CommonFontInfo& Font::Fi() const
|
||||
{
|
||||
if(AsInt64() == lastFiFont)
|
||||
return lastFontInfo;
|
||||
lastFontInfo = GetFontInfo(*this);
|
||||
lastFiFont = AsInt64();
|
||||
return lastFontInfo;
|
||||
}
|
||||
|
||||
FontInfo Font::Info() const
|
||||
{
|
||||
FontInfo h;
|
||||
h.font = *this;
|
||||
return h;
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
#include "Draw.h"
|
||||
|
||||
#define LLOG(x)
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
CommonFontInfo GetFontInfoSys(Font font);
|
||||
GlyphInfo GetGlyphInfoSys(Font font, int chr);
|
||||
void GetStdFontSys(String& name, int& height);
|
||||
Vector<FaceInfo> GetAllFacesSys();
|
||||
|
||||
bool Replace(Font fnt, int chr, Font& rfnt);
|
||||
|
||||
void Std(Font& font)
|
||||
{
|
||||
if(IsNull(font))
|
||||
font = StdFont();
|
||||
if(font.GetFace() == 0)
|
||||
font.Face(GetStdFont().GetFace());
|
||||
if(font.GetHeight() == 0)
|
||||
font.Height(GetStdFont().GetHeight());
|
||||
}
|
||||
|
||||
Size Font::StdFontSize;
|
||||
Font Font::AStdFont;
|
||||
|
||||
INITBLOCK {
|
||||
RichValue<Font>::Register();
|
||||
}
|
||||
|
||||
const Vector<FaceInfo>& Font::List()
|
||||
{
|
||||
static Vector<FaceInfo> *q;
|
||||
ONCELOCK {
|
||||
static Vector<FaceInfo> x;
|
||||
x = GetAllFacesSys();
|
||||
q = &x;
|
||||
}
|
||||
return *q;
|
||||
}
|
||||
|
||||
void sInitFonts()
|
||||
{
|
||||
Font::List();
|
||||
GetStdFont();
|
||||
}
|
||||
|
||||
INITBLOCK {
|
||||
sInitFonts();
|
||||
}
|
||||
|
||||
int Font::GetFaceCount()
|
||||
{
|
||||
return List().GetCount();
|
||||
}
|
||||
|
||||
String Font::GetFaceName(int index)
|
||||
{
|
||||
if(index == 0)
|
||||
return "STDFONT";
|
||||
const Vector<FaceInfo>& l = List();
|
||||
if(index >= 0 && index < l.GetCount())
|
||||
return l[index].name;
|
||||
return Null;
|
||||
}
|
||||
|
||||
dword Font::GetFaceInfo(int index)
|
||||
{
|
||||
const Vector<FaceInfo>& l = List();
|
||||
if(index >= 0 && index < l.GetCount())
|
||||
return l[index].info;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FontFilter(int c)
|
||||
{
|
||||
return c >= 'a' && c <= 'z' || c >= '0' && c <= '9' ? c : c >= 'A' && c <= 'Z' ? ToLower(c) : 0;
|
||||
}
|
||||
|
||||
int Font::FindFaceNameIndex(const String& name) {
|
||||
if(name == "STDFONT")
|
||||
return 0;
|
||||
for(int i = 1; i < GetFaceCount(); i++)
|
||||
if(GetFaceName(i) == name)
|
||||
return i;
|
||||
String n = Filter(name, FontFilter);
|
||||
for(int i = 1; i < GetFaceCount(); i++)
|
||||
if(Filter(GetFaceName(i), FontFilter) == n)
|
||||
return i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Font::SyncStdFont()
|
||||
{
|
||||
DrawLock __;
|
||||
StdFontSize = Size(AStdFont.GetAveWidth(), AStdFont().Bold().GetCy());
|
||||
}
|
||||
|
||||
void Font::SetStdFont(Font font)
|
||||
{
|
||||
DrawLock __;
|
||||
InitStdFont();
|
||||
AStdFont = font;
|
||||
SyncStdFont();
|
||||
DLOG("SetStdFont " << font);
|
||||
}
|
||||
|
||||
void Font::InitStdFont()
|
||||
{
|
||||
ONCELOCK {
|
||||
DrawLock __;
|
||||
List();
|
||||
AStdFont = Arial(12);
|
||||
String name;
|
||||
int height = 0;
|
||||
GetStdFontSys(name, height);
|
||||
int q = FindFaceNameIndex(name);
|
||||
if(q > 0)
|
||||
SetStdFont(Font(q, max(height, 1)));
|
||||
}
|
||||
}
|
||||
|
||||
Font Font::GetStdFont()
|
||||
{
|
||||
InitStdFont();
|
||||
return AStdFont;
|
||||
}
|
||||
|
||||
Size Font::GetStdFontSize()
|
||||
{
|
||||
InitStdFont();
|
||||
return StdFontSize;
|
||||
}
|
||||
|
||||
Font StdFont()
|
||||
{
|
||||
return Font(0, 0);
|
||||
}
|
||||
|
||||
int Font::GetHeight() const
|
||||
{
|
||||
return v.height ? v.height : GetStdFont().GetHeight();
|
||||
}
|
||||
|
||||
String Font::GetFaceName() const {
|
||||
if(IsNull()) return String();
|
||||
if(GetFace() == 0)
|
||||
return "STDFONT";
|
||||
return GetFaceName(GetFace());
|
||||
}
|
||||
|
||||
dword Font::GetFaceInfo() const {
|
||||
if(IsNull()) return 0;
|
||||
return GetFaceInfo(GetFace());
|
||||
}
|
||||
|
||||
Font& Font::FaceName(const String& name) {
|
||||
int n = FindFaceNameIndex(name);
|
||||
Face(n < 0 ? 0xffff : n);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Font::Serialize(Stream& s) {
|
||||
int version = 1;
|
||||
s / version;
|
||||
if(version >= 1) {
|
||||
int f = GetFace();
|
||||
if(f > COURIER)
|
||||
f = -1;
|
||||
s / f;
|
||||
String name;
|
||||
if(f < 0) {
|
||||
name = GetFaceName();
|
||||
s % name;
|
||||
}
|
||||
if(s.IsLoading())
|
||||
if(f >= 0)
|
||||
Face(f);
|
||||
else
|
||||
FaceName(name);
|
||||
}
|
||||
else {
|
||||
String name = GetFaceName();
|
||||
s % name;
|
||||
if(s.IsLoading()) {
|
||||
FaceName(name);
|
||||
if(IsNull())
|
||||
Face(COURIER);
|
||||
}
|
||||
}
|
||||
s % v.flags % v.height % v.width;
|
||||
}
|
||||
|
||||
template<>
|
||||
String AsString(const Font& f) {
|
||||
if(IsNull(f)) return "<null>";
|
||||
String s = "<" + f.GetFaceName() + Format(":%d", f.GetHeight());
|
||||
if(f.IsBold())
|
||||
s += " Bold";
|
||||
if(f.IsItalic())
|
||||
s += " Italic";
|
||||
if(f.IsUnderline())
|
||||
s += " Underline";
|
||||
if(f.IsStrikeout())
|
||||
s += " Strikeout";
|
||||
return s + '>';
|
||||
}
|
||||
|
||||
struct CharEntry {
|
||||
int64 font;
|
||||
GlyphInfo info;
|
||||
word chr;
|
||||
};
|
||||
|
||||
CharEntry fc_cache_global[4093];
|
||||
|
||||
bool IsNormal(Font font, int chr)
|
||||
{
|
||||
DrawLock __;
|
||||
CharEntry& e = fc_cache_global[CombineHash(font.GetHashValue(), chr) % 4093];
|
||||
if(e.font == font.AsInt64() || e.chr == chr)
|
||||
return e.info.IsNormal();
|
||||
return GetGlyphInfoSys(font, chr).IsNormal();
|
||||
}
|
||||
|
||||
CharEntry GetGlyphEntry(Font font, int chr, unsigned hash)
|
||||
{
|
||||
DrawLock __;
|
||||
CharEntry& e = fc_cache_global[hash % 4093];
|
||||
if(e.font != font.AsInt64() || e.chr != chr) {
|
||||
e.font = font.AsInt64();
|
||||
e.chr = chr;
|
||||
e.info = GetGlyphInfoSys(font, chr);
|
||||
if(!e.info.IsNormal()) {
|
||||
ComposedGlyph cg;
|
||||
Font rfnt;
|
||||
if(Compose(font, chr, cg)) {
|
||||
e.info.lspc = -1;
|
||||
e.info.rspc = cg.basic_char;
|
||||
}
|
||||
else
|
||||
if(Replace(font, chr, rfnt)) {
|
||||
e.info.lspc = rfnt.GetFace();
|
||||
e.info.rspc = rfnt.GetHeight();
|
||||
}
|
||||
else
|
||||
e.info.lspc = -2;
|
||||
}
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
thread__ CharEntry fc_cache[512];
|
||||
|
||||
GlyphInfo GetGlyphInfo(Font font, int chr)
|
||||
{
|
||||
Std(font);
|
||||
unsigned hash = CombineHash(font.GetHashValue(), chr);
|
||||
CharEntry& e = fc_cache[hash & 511];
|
||||
if(e.font != font.AsInt64() || e.chr != chr)
|
||||
e = GetGlyphEntry(font, chr, hash);
|
||||
return e.info;
|
||||
}
|
||||
|
||||
void GlyphMetrics(GlyphInfo& f, Font font, int chr)
|
||||
{
|
||||
if(f.IsReplaced())
|
||||
f = GetGlyphInfo(font().Face(f.lspc).Height(f.rspc), chr);
|
||||
if(f.IsComposed()) {
|
||||
f = GetGlyphInfo(font, f.rspc);
|
||||
if(f.IsComposedLM())
|
||||
f.rspc += f.width / 2;
|
||||
}
|
||||
}
|
||||
|
||||
GlyphInfo GetGlyphMetrics(Font font, int chr)
|
||||
{
|
||||
GlyphInfo f = GetGlyphInfo(font, chr);
|
||||
if(f.IsMissing())
|
||||
f = GetGlyphInfo(font, '?');
|
||||
GlyphMetrics(f, font, chr);
|
||||
return f;
|
||||
}
|
||||
|
||||
struct FontEntry {
|
||||
CommonFontInfo info;
|
||||
int64 font;
|
||||
};
|
||||
|
||||
thread__ FontEntry fi_cache[64];
|
||||
|
||||
const CommonFontInfo& GetFontInfo(Font font)
|
||||
{
|
||||
Std(font);
|
||||
unsigned hash = font.GetHashValue() & 63;
|
||||
FontEntry& e = fi_cache[hash];
|
||||
if(e.font != font.AsInt64()) {
|
||||
DrawLock __;
|
||||
e.font = font.AsInt64();
|
||||
e.info = GetFontInfoSys(font);
|
||||
}
|
||||
return e.info;
|
||||
}
|
||||
|
||||
int Font::GetWidth(int c) const {
|
||||
return GetGlyphMetrics(*this, c).width;
|
||||
}
|
||||
|
||||
int Font::GetLeftSpace(int c) const {
|
||||
return GetGlyphMetrics(*this, c).lspc;
|
||||
}
|
||||
|
||||
int Font::GetRightSpace(int c) const {
|
||||
return GetGlyphMetrics(*this, c).rspc;
|
||||
}
|
||||
|
||||
thread__ int64 lastFiFont = INT_MIN;
|
||||
thread__ CommonFontInfo lastFontInfo;
|
||||
thread__ int64 lastStdFont = INT_MIN;
|
||||
|
||||
const CommonFontInfo& Font::Fi() const
|
||||
{
|
||||
if(lastStdFont != AStdFont.AsInt64()) {
|
||||
lastFiFont = INT_MIN;
|
||||
lastStdFont = AStdFont.AsInt64();
|
||||
}
|
||||
if(AsInt64() == lastFiFont)
|
||||
return lastFontInfo;
|
||||
lastFontInfo = GetFontInfo(*this);
|
||||
lastFiFont = AsInt64();
|
||||
return lastFontInfo;
|
||||
}
|
||||
|
||||
FontInfo Font::Info() const
|
||||
{
|
||||
FontInfo h;
|
||||
h.font = *this;
|
||||
return h;
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
|
|
|||
225
newdraw/Draw/FontFc.cpp
Normal file
225
newdraw/Draw/FontFc.cpp
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
#include "Draw.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
#ifdef PLATFORM_POSIX
|
||||
|
||||
#define LLOG(x) // LOG(x)
|
||||
#define LTIMING(x) // TIMING(x)
|
||||
|
||||
void GetStdFontSys(String& name, int& height)
|
||||
{
|
||||
name = "xxxx";
|
||||
}
|
||||
|
||||
static FT_Library sFTlib;
|
||||
|
||||
bool sInitFt(void)
|
||||
{
|
||||
if(sFTlib)
|
||||
return true;
|
||||
return FT_Init_FreeType(&sFTlib) == 0;
|
||||
}
|
||||
|
||||
FcPattern *CreateFcPattern(Font font, int angle)
|
||||
{
|
||||
LTIMING("CreateXftFont");
|
||||
double sina, cosa;
|
||||
int hg = abs(font.GetHeight());
|
||||
if(hg == 0) hg = 10;
|
||||
String n = font.GetFaceName();
|
||||
const char *face = n;
|
||||
FcPattern *p = FcPatternCreate();
|
||||
FcPatternAddString(p, FC_FAMILY, (FcChar8*)face);
|
||||
FcPatternAddInteger(p, FC_SLANT, font.IsItalic() ? 110 : 0);
|
||||
FcPatternAddInteger(p, FC_PIXEL_SIZE, hg);
|
||||
FcPatternAddInteger(p, FC_WEIGHT, font.IsBold() ? 200 : 100);
|
||||
FcPatternAddBool(p, FC_MINSPACE, 1);
|
||||
if(angle) {
|
||||
FcMatrix mx;
|
||||
Draw::SinCos(angle, sina, cosa);
|
||||
mx.xx = cosa;
|
||||
mx.xy = -sina;
|
||||
mx.yx = sina;
|
||||
mx.yy = cosa;
|
||||
FcPatternAddMatrix(p, FC_MATRIX, &mx);
|
||||
}
|
||||
FcResult result;
|
||||
FcPattern *m = XftFontMatch(Xdisplay, Xscreenno, p, &result);
|
||||
FcPatternDestroy(p);
|
||||
return m;
|
||||
}
|
||||
|
||||
FT_Face CreateFTFace(const FcPattern *pattern, String *rpath) {
|
||||
FT_Face face = NULL;
|
||||
|
||||
int id;
|
||||
double dsize;
|
||||
double aspect;
|
||||
FcChar8 *filename;
|
||||
|
||||
if(!sInitFt())
|
||||
return NULL;
|
||||
|
||||
if(FcPatternGetString(pattern, FC_FILE, 0, &filename) != FcResultMatch)
|
||||
return NULL;
|
||||
|
||||
if(rpath)
|
||||
*rpath = (const char *)filename;
|
||||
|
||||
if(FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &dsize) != FcResultMatch)
|
||||
dsize = 16;
|
||||
|
||||
if (FcPatternGetDouble(pattern, FC_ASPECT, 0, &aspect) != FcResultMatch)
|
||||
aspect = 1.0;
|
||||
|
||||
FT_F26Dot6 ysize = (FT_F26Dot6) (dsize * 64.0);
|
||||
FT_F26Dot6 xsize = (FT_F26Dot6) (dsize * aspect * 64.0);
|
||||
|
||||
if(FT_New_Face (sFTlib, (const char *)filename, 0, &face))
|
||||
return NULL;
|
||||
|
||||
FT_Set_Char_Size(face, xsize, ysize, 0, 0);
|
||||
return face;
|
||||
}
|
||||
|
||||
#define FONTCACHE 37
|
||||
|
||||
struct FtFaceEntry {
|
||||
Font font;
|
||||
FT_Face face;
|
||||
String path;
|
||||
};
|
||||
|
||||
FT_Face FTFace(Font fnt, String *rpath = NULL)
|
||||
{
|
||||
RTIMING("FTFace");
|
||||
static FtFaceEntry cache[FONTCACHE];
|
||||
ONCELOCK {
|
||||
for(int i = 0; i < FONTCACHE; i++)
|
||||
cache[i].font.Height(-30000);
|
||||
}
|
||||
FtFaceEntry be;
|
||||
be = cache[0];
|
||||
for(int i = 0; i < FONTCACHE; i++) {
|
||||
FtFaceEntry e = cache[i];
|
||||
if(i)
|
||||
cache[i] = be;
|
||||
if(e.font == fnt) {
|
||||
if(rpath)
|
||||
*rpath = e.path;
|
||||
if(i)
|
||||
cache[0] = e;
|
||||
return e.face;
|
||||
}
|
||||
be = e;
|
||||
}
|
||||
RTIMING("FTFace2");
|
||||
if(be.face) {
|
||||
LOG("Removing " << be.font << " - " << (void *)be.face);
|
||||
FT_Done_Face(be.face);
|
||||
}
|
||||
be.font = fnt;
|
||||
FcPattern *p = CreateFcPattern(fnt, 0);
|
||||
be.face = CreateFTFace(p, &be.path);
|
||||
FcPatternDestroy(p);
|
||||
cache[0] = be;
|
||||
if(rpath)
|
||||
*rpath = be.path;
|
||||
return be.face;
|
||||
}
|
||||
|
||||
CommonFontInfo GetFontInfoSys(Font font)
|
||||
{
|
||||
CommonFontInfo fi;
|
||||
|
||||
FT_Face face = FTFace(font, &fi.path);
|
||||
if(face) {
|
||||
fi.ascent = face->size->metrics.ascender >> 6;
|
||||
fi.descent = -(face->size->metrics.descender >> 6);
|
||||
fi.height = fi.ascent + fi.descent;
|
||||
fi.lineheight = face->size->metrics.height >> 6;
|
||||
fi.external = 0;
|
||||
fi.internal = 0;
|
||||
fi.overhang = 0;
|
||||
fi.maxwidth = face->size->metrics.max_advance >> 6;
|
||||
fi.avewidth = fi.maxwidth;
|
||||
fi.default_char = '?';
|
||||
fi.fixedpitch = font.GetFaceInfo() & Font::FIXEDPITCH;
|
||||
}
|
||||
return fi;
|
||||
}
|
||||
|
||||
#define FLOOR(x) ((x) & -64)
|
||||
#define CEIL(x) (((x)+63) & -64)
|
||||
#define TRUNC(x) ((x) >> 6)
|
||||
#define ROUND(x) (((x)+32) & -64)
|
||||
|
||||
GlyphInfo GetGlyphInfoSys(Font font, int chr)
|
||||
{
|
||||
RTIMING("GetGlyphInfoSys");
|
||||
GlyphInfo gi;
|
||||
FT_Face face = FTFace(font, NULL);
|
||||
gi.lspc = gi.rspc = 0;
|
||||
gi.width = 0x8000;
|
||||
if(face) {
|
||||
RTIMING("GetGlyphInfoSys 2");
|
||||
int glyph_index = FT_Get_Char_Index(face, chr);
|
||||
if(glyph_index &&
|
||||
(FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT|FT_LOAD_NO_BITMAP) == 0 ||
|
||||
FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT) == 0)) {
|
||||
FT_Glyph_Metrics& m = face->glyph->metrics;
|
||||
int left = FLOOR(m.horiBearingX);
|
||||
int width = TRUNC(CEIL(m.horiBearingX + m.width) - left);
|
||||
gi.width = TRUNC(ROUND(face->glyph->advance.x));
|
||||
gi.lspc = TRUNC(left);
|
||||
gi.rspc = gi.width - width - gi.lspc;
|
||||
}
|
||||
}
|
||||
return gi;
|
||||
}
|
||||
|
||||
Vector<FaceInfo> GetAllFacesSys()
|
||||
{
|
||||
static const char *basic_fonts[] = {
|
||||
"sans-serif",
|
||||
"serif",
|
||||
"sans-serif",
|
||||
"monospace",
|
||||
"serif",
|
||||
"sans-serif",
|
||||
"monospace",
|
||||
};
|
||||
|
||||
Vector<FaceInfo> list;
|
||||
for(int i = 0; i < __countof(basic_fonts); i++) {
|
||||
FaceInfo& fi = list.Add();
|
||||
fi.name = basic_fonts[i];
|
||||
fi.info = (i == 3 || i == 6) ? Font::SCALEABLE|Font::FIXEDPITCH : Font::SCALEABLE;
|
||||
}
|
||||
FcPattern *p = FcPatternCreate();
|
||||
FcObjectSet *os = FcObjectSetBuild(XFT_FAMILY, XFT_SPACING, XFT_SCALABLE, (void *)0);
|
||||
FcFontSet *fs = FcFontList(NULL, p, os);
|
||||
FcPatternDestroy(p);
|
||||
FcObjectSetDestroy(os);
|
||||
for(int i = 0; i < fs->nfont; i++) {
|
||||
FcChar8 *family = NULL;
|
||||
if(FcPatternGetString(fs->fonts[i], FC_FAMILY, 0, &family) == 0 && family) {
|
||||
FaceInfo& fi = list.Add();
|
||||
fi.name = (const char *)family;
|
||||
fi.info = 0;
|
||||
int iv;
|
||||
if(FcPatternGetInteger(fs->fonts[i], FC_SPACING, 0, &iv) == 0 && iv == FC_MONO)
|
||||
fi.info |= Font::FIXEDPITCH;
|
||||
FcBool bv;
|
||||
if(FcPatternGetBool(fs->fonts[i], FC_SCALABLE, 0, &bv) == 0 && bv)
|
||||
fi.info |= Font::SCALEABLE;
|
||||
}
|
||||
}
|
||||
FcFontSetDestroy(fs);
|
||||
return list;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
|
@ -1,294 +0,0 @@
|
|||
#include "Draw.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
#ifdef PLATFORM_X11
|
||||
|
||||
#define LLOG(x) // LOG(x)
|
||||
#define LTIMING(x) // TIMING(x)
|
||||
|
||||
struct XFTFontFaceInfo {
|
||||
String name;
|
||||
bool fixed:1;
|
||||
bool scaleable:1;
|
||||
bool compose:1;
|
||||
|
||||
XFTFontFaceInfo()
|
||||
{
|
||||
fixed = scaleable = false;
|
||||
}
|
||||
};
|
||||
|
||||
ArrayMap<String, XFTFontFaceInfo>& XFTFontFace()
|
||||
{
|
||||
static ArrayMap<String, XFTFontFaceInfo> x;
|
||||
return x;
|
||||
}
|
||||
|
||||
FontInfo::Data::Data()
|
||||
{
|
||||
refcount = 1;
|
||||
for(int i = 0; i < 64; i++)
|
||||
base[i] = NULL;
|
||||
xftfont = NULL;
|
||||
}
|
||||
|
||||
FontInfo::Data::~Data()
|
||||
{
|
||||
DrawLock __;
|
||||
if(xftfont0 && xftfont0 != xftfont)
|
||||
XftFontClose(Xdisplay, xftfont0);
|
||||
if(xftfont)
|
||||
XftFontClose(Xdisplay, xftfont);
|
||||
for(int i = 0; i < 64; i++)
|
||||
if(base[i]) delete[] base[i];
|
||||
}
|
||||
|
||||
void FontInfo::Data::GetMetrics(CharMetrics *t, int from, int count)
|
||||
{
|
||||
DrawLock __;
|
||||
LTIMING("GetMetrics");
|
||||
LLOG("GetMetrics " << font << " " << from << ", " << count);
|
||||
if(xftfont) {
|
||||
for(int i = 0; i < count; i++) {
|
||||
LTIMING("XftTextExtents16");
|
||||
wchar h = from + i;
|
||||
XGlyphInfo info;
|
||||
XftTextExtents16(Xdisplay, xftfont0, &h, 1, &info);
|
||||
t[i].width = info.xOff;
|
||||
t[i].lspc = -info.x;
|
||||
t[i].rspc = info.xOff - info.width + info.x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char *basic_fonts[] = {
|
||||
"sans-serif",
|
||||
"serif",
|
||||
"sans-serif",
|
||||
"monospace",
|
||||
"serif",
|
||||
"sans-serif",
|
||||
"monospace",
|
||||
};
|
||||
|
||||
static int sCheckComposed(const char *face)
|
||||
{
|
||||
XftFont *xftfont = XftFontOpen(Xdisplay, Xscreenno,
|
||||
XFT_FAMILY, XftTypeString, (char *)face,
|
||||
XFT_PIXEL_SIZE, XftTypeInteger, 20,
|
||||
(void *)0);
|
||||
if(xftfont == NULL )
|
||||
return -1;
|
||||
int n = 0;
|
||||
for(int c = 0; c < 128; c++)
|
||||
if(!XftCharExists(Xdisplay, xftfont, c + 256))
|
||||
n++;
|
||||
XftFontClose(Xdisplay, xftfont);
|
||||
return n > 10;
|
||||
}
|
||||
|
||||
bool FontInfo::Data::HasChar(int ch) const
|
||||
{
|
||||
return XftCharExists(Xdisplay, xftfont, ch);
|
||||
}
|
||||
|
||||
void FontInfo::InitPlatformFonts()
|
||||
{
|
||||
for(int i = 0; i < __countof(basic_fonts); i++) {
|
||||
XFTFontFaceInfo& f = XFTFontFace().Add(basic_fonts[i]);
|
||||
f.name = basic_fonts[i];
|
||||
f.scaleable = true;
|
||||
f.fixed = i == 3 || i == 6;
|
||||
f.compose = sCheckComposed(basic_fonts[i]);
|
||||
}
|
||||
FcFontSet *fs = XftListFonts(Xdisplay, Xscreenno, (void *)0, XFT_FAMILY, XFT_SPACING,
|
||||
XFT_SCALABLE, (void *)0);
|
||||
for(int i = 0; i < fs->nfont; i++) {
|
||||
FcChar8 *family = NULL;
|
||||
if(FcPatternGetString(fs->fonts[i], FC_FAMILY, 0, &family) == 0 && family) {
|
||||
int comp = sCheckComposed((char *)family);
|
||||
if(comp >= 0) {
|
||||
XFTFontFaceInfo& f = XFTFontFace().GetAdd((char *)family);
|
||||
int spacing;
|
||||
if(FcPatternGetInteger(fs->fonts[i], FC_SPACING, 0, &spacing) == 0 && spacing == XFT_MONO)
|
||||
f.fixed = true;
|
||||
FcBool scaleable;
|
||||
if(FcPatternGetBool(fs->fonts[i], FC_SCALABLE, 0, &scaleable) == 0 && scaleable)
|
||||
f.scaleable = true;
|
||||
f.compose = comp;
|
||||
}
|
||||
}
|
||||
}
|
||||
FcFontSetDestroy(fs);
|
||||
}
|
||||
|
||||
int Font::GetFaceCount()
|
||||
{
|
||||
ONCELOCK {
|
||||
FontInfo::InitFonts();
|
||||
}
|
||||
return XFTFontFace().GetCount();
|
||||
}
|
||||
|
||||
String Font::GetFaceName(int index)
|
||||
{
|
||||
ONCELOCK {
|
||||
FontInfo::InitFonts();
|
||||
}
|
||||
return index >= 0 && index < XFTFontFace().GetCount() ? XFTFontFace().GetKey(index)
|
||||
: Null;
|
||||
}
|
||||
|
||||
dword Font::GetFaceInfo(int index) {
|
||||
ONCELOCK {
|
||||
FontInfo::InitFonts();
|
||||
}
|
||||
dword w = 0;
|
||||
if(index >= 0 && index < XFTFontFace().GetCount()) {
|
||||
XFTFontFaceInfo& fi = XFTFontFace()[index];
|
||||
if(fi.fixed)
|
||||
w |= FIXEDPITCH;
|
||||
if(fi.scaleable)
|
||||
w |= SCALEABLE;
|
||||
if(fi.compose)
|
||||
w |= COMPOSED;
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
int gtk_antialias = -1;
|
||||
int gtk_hinting = -1;
|
||||
String gtk_hintstyle;
|
||||
String gtk_rgba;
|
||||
|
||||
XftFont *FontInfo::CreateXftFont(Font font, int angle)
|
||||
{
|
||||
LTIMING("CreateXftFont");
|
||||
XftFont *xftfont;
|
||||
double sina, cosa;
|
||||
int hg = abs(font.GetHeight());
|
||||
if(hg == 0) hg = 10;
|
||||
int i = font.GetFace();
|
||||
if(i < 0 || i >= XFTFontFace().GetCount())
|
||||
i = 0;
|
||||
const char *face = i < 7 ? basic_fonts[i] : ~XFTFontFace().GetKey(i);
|
||||
FcPattern *p = FcPatternCreate();
|
||||
FcPatternAddString(p, FC_FAMILY, (FcChar8*)face);
|
||||
FcPatternAddInteger(p, FC_SLANT, font.IsItalic() ? 110 : 0);
|
||||
FcPatternAddInteger(p, FC_PIXEL_SIZE, hg);
|
||||
FcPatternAddInteger(p, FC_WEIGHT, font.IsBold() ? 200 : 100);
|
||||
FcPatternAddBool(p, FC_MINSPACE, 1);
|
||||
if(angle) {
|
||||
FcMatrix mx;
|
||||
Draw::SinCos(angle, sina, cosa);
|
||||
mx.xx = cosa;
|
||||
mx.xy = -sina;
|
||||
mx.yx = sina;
|
||||
mx.yy = cosa;
|
||||
FcPatternAddMatrix(p, FC_MATRIX, &mx);
|
||||
}
|
||||
FcResult result;
|
||||
FcPattern *m = XftFontMatch(Xdisplay, Xscreenno, p, &result);
|
||||
if(font.IsNonAntiAliased() || gtk_antialias >= 0) {
|
||||
FcPatternDel(m, FC_ANTIALIAS);
|
||||
FcPatternAddBool(m, FC_ANTIALIAS,
|
||||
font.IsNonAntiAliased() ? FcFalse : gtk_antialias ? FcTrue : FcFalse);
|
||||
}
|
||||
if(gtk_hinting >= 0) {
|
||||
FcPatternDel(m, FC_HINTING);
|
||||
FcPatternAddBool(m, FC_HINTING, gtk_hinting);
|
||||
}
|
||||
const char *hs[] = { "hintnone", "hintslight", "hintmedium", "hintfull" };
|
||||
for(int i = 0; i < 4; i++)
|
||||
if(gtk_hintstyle == hs[i]) {
|
||||
FcPatternDel(m, FC_HINT_STYLE);
|
||||
FcPatternAddInteger(m, FC_HINT_STYLE, i);
|
||||
}
|
||||
const char *rgba[] = { "_", "rgb", "bgr", "vrgb", "vbgr" };
|
||||
for(int i = 0; i < __countof(rgba); i++)
|
||||
if(gtk_rgba == rgba[i]) {
|
||||
FcPatternDel(m, FC_RGBA);
|
||||
FcPatternAddInteger(m, FC_RGBA, i);
|
||||
}
|
||||
xftfont = XftFontOpenPattern(Xdisplay, m);
|
||||
FcPatternDestroy(p);
|
||||
return xftfont;
|
||||
}
|
||||
|
||||
FontInfo FontInfo::AcquireFontInfo(Font font, int angle)
|
||||
{
|
||||
DrawLock __;
|
||||
LTIMING("Acquire");
|
||||
if(IsNull(font))
|
||||
font = StdFont();
|
||||
if(font.GetFace() == 0)
|
||||
font.Face(AStdFont.GetFace());
|
||||
if(font.GetHeight() == 0)
|
||||
font.Height(AStdFont.GetHeight());
|
||||
FontInfo::Data *f, *fh;
|
||||
f = fh = GetFontHash((font.GetHashValue() ^ angle) % (int)FONTHASH);
|
||||
LLOG("Acquire " << font << " device: " << device);
|
||||
for(;;) {
|
||||
f = f->GetNext(HASH);
|
||||
if(f == fh) break;
|
||||
if(f->font == font && f->angle == angle)
|
||||
{
|
||||
LLOG("Reusing " << f->font);
|
||||
if(f->InList(LRU)) {
|
||||
f->Unlink(LRU);
|
||||
FontCached--;
|
||||
LLOG("Removing from cache " << f->font << " cached:" << FontCached);
|
||||
}
|
||||
f->refcount++;
|
||||
return f;
|
||||
}
|
||||
}
|
||||
LLOG("New " << font);
|
||||
LTIMING("Acquire New");
|
||||
f = fh->InsertNext(HASH);
|
||||
f->font = font;
|
||||
f->angle = angle;
|
||||
int hg = abs(font.GetHeight());
|
||||
if(hg == 0) hg = 10;
|
||||
f->xftfont0 = f->xftfont = CreateXftFont(font, angle);
|
||||
if(angle)
|
||||
f->xftfont0 = CreateXftFont(font, 0);
|
||||
f->filename = NULL;
|
||||
f->ascent = (int16)f->xftfont0->ascent;
|
||||
f->descent = (int16)f->xftfont0->descent;
|
||||
f->height = f->ascent + f->descent;
|
||||
f->lineheight = (int16)f->xftfont0->height;
|
||||
f->external = 0;
|
||||
f->internal = 0;
|
||||
f->overhang = 0;
|
||||
f->maxwidth = (int16)f->xftfont0->max_advance_width;
|
||||
f->avewidth = f->maxwidth;
|
||||
f->default_char = '?';
|
||||
f->fixedpitch = font.GetFaceInfo() & Font::FIXEDPITCH;
|
||||
f->underline_thickness = max(hg / 20, 1);
|
||||
f->underline_position = max(hg / 15, int(f->descent > 0));
|
||||
if(angle) {
|
||||
Draw::SinCos(angle, f->sina, f->cosa);
|
||||
f->offset.cx = fround(f->ascent * f->sina);
|
||||
f->offset.cy = fround(f->ascent * f->cosa);
|
||||
}
|
||||
FontInfo fi = FontInfo(f);
|
||||
fi.GetPage(0);
|
||||
return fi;
|
||||
}
|
||||
|
||||
String FontInfo::GetFileName() const
|
||||
{
|
||||
if(IsNull(ptr->filename)) {
|
||||
char *fn = NULL;
|
||||
XftPatternGetString(ptr->xftfont->pattern, XFT_FILE, 0, &fn);
|
||||
if(fn)
|
||||
ptr->filename = fn;
|
||||
}
|
||||
return ptr->filename;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
|
@ -1,342 +1,334 @@
|
|||
#define NEWIMAGE
|
||||
|
||||
enum ImageKind {
|
||||
IMAGE_UNKNOWN,
|
||||
IMAGE_EMPTY,
|
||||
IMAGE_ALPHA,
|
||||
IMAGE_MASK,
|
||||
IMAGE_OPAQUE,
|
||||
};
|
||||
|
||||
inline bool operator==(const RGBA& a, const RGBA& b)
|
||||
{
|
||||
return a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a;
|
||||
}
|
||||
|
||||
inline bool operator!=(const RGBA& a, const RGBA& b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
inline RGBA RGBAZero() { RGBA c; c.r = c.g = c.b = c.a = 0; return c; }
|
||||
|
||||
void Fill(RGBA *t, const RGBA& src, int n);
|
||||
void FillColor(RGBA *t, const RGBA& src, int n);
|
||||
|
||||
void Copy(RGBA *t, const RGBA *s, int n);
|
||||
|
||||
int Premultiply(RGBA *t, const RGBA *s, int len);
|
||||
int Unmultiply(RGBA *t, const RGBA *s, int len);
|
||||
|
||||
void AlphaBlend(RGBA *t, const RGBA *s, int len);
|
||||
void AlphaBlend(RGBA *t, const RGBA *s, int len, Color color);
|
||||
|
||||
void AlphaBlendOpaque(RGBA *t, const RGBA *s, int len, Color color);
|
||||
void AlphaBlendOpaque(RGBA *t, const RGBA *s, int len);
|
||||
|
||||
void AlphaBlendStraight(RGBA *b, const RGBA *f, int len);
|
||||
void AlphaBlendStraight(RGBA *b, const RGBA *f, int len, Color color);
|
||||
void AlphaBlendStraightOpaque(RGBA *t, const RGBA *s, int len);
|
||||
void AlphaBlendStraightOpaque(RGBA *t, const RGBA *s, int len, int alpha);
|
||||
|
||||
int GetChMaskPos32(dword mask);
|
||||
void AlphaBlendOverBgST(RGBA *b, RGBA bg, int len);
|
||||
|
||||
const byte *UnpackRLE(RGBA *t, const byte *src, int len);
|
||||
String PackRLE(const RGBA *s, int len);
|
||||
|
||||
inline int Grayscale(int r, int g, int b) { return (77 * r + 151 * g + 28 * b) >> 8; }
|
||||
inline int Grayscale(const RGBA& c) { return Grayscale(c.r, c.g, c.b); }
|
||||
inline byte Saturate255(int x) { return byte(~(x >> 24) & (x | (-(x >> 8) >> 24)) & 0xff); }
|
||||
|
||||
class Image;
|
||||
class ImageDraw;
|
||||
|
||||
class ImageBuffer : NoCopy {
|
||||
mutable int kind;
|
||||
Size size;
|
||||
Buffer<RGBA> pixels;
|
||||
Point hotspot;
|
||||
Point spot2;
|
||||
Size dots;
|
||||
|
||||
void Set(Image& img);
|
||||
void DeepCopy(const ImageBuffer& img);
|
||||
|
||||
RGBA* Line(int i) const { ASSERT(i >= 0 && i < size.cy); return (RGBA *)~pixels + i * size.cx; }
|
||||
friend void DropPixels___(ImageBuffer& b) { b.pixels.Clear(); }
|
||||
|
||||
friend class Image;
|
||||
|
||||
public:
|
||||
void SetKind(int k) { kind = k; }
|
||||
int GetKind() const { return kind; }
|
||||
int ScanKind() const;
|
||||
int GetScanKind() const { return kind == IMAGE_UNKNOWN ? ScanKind() : kind; }
|
||||
|
||||
void SetHotSpot(Point p) { hotspot = p; }
|
||||
Point GetHotSpot() const { return hotspot; }
|
||||
|
||||
void Set2ndSpot(Point p) { spot2 = p; }
|
||||
Point Get2ndSpot() const { return spot2; }
|
||||
|
||||
void SetDots(Size sz) { dots = sz; }
|
||||
Size GetDots() const { return dots; }
|
||||
|
||||
Size GetSize() const { return size; }
|
||||
int GetWidth() const { return size.cx; }
|
||||
int GetHeight() const { return size.cy; }
|
||||
int GetLength() const { return size.cx * size.cy; }
|
||||
|
||||
RGBA *operator[](int i) { return Line(i); }
|
||||
const RGBA *operator[](int i) const { return Line(i); }
|
||||
RGBA *operator~() { return pixels; }
|
||||
operator RGBA*() { return pixels; }
|
||||
const RGBA *operator~() const { return pixels; }
|
||||
operator const RGBA*() const { return pixels; }
|
||||
|
||||
void Create(int cx, int cy);
|
||||
void Create(Size sz) { Create(sz.cx, sz.cy); }
|
||||
bool IsEmpty() const { return (size.cx | size.cy) == 0; }
|
||||
void Clear() { Create(0, 0); }
|
||||
|
||||
void operator=(Image& img);
|
||||
void operator=(ImageBuffer& img);
|
||||
|
||||
ImageBuffer() { Create(0, 0); }
|
||||
ImageBuffer(int cx, int cy) { Create(cx, cy); }
|
||||
ImageBuffer(Size sz) { Create(sz.cx, sz.cy); }
|
||||
ImageBuffer(Image& img);
|
||||
ImageBuffer(ImageDraw& w);
|
||||
ImageBuffer(ImageBuffer& b);
|
||||
};
|
||||
|
||||
void Premultiply(ImageBuffer& b);
|
||||
void Unmultiply(ImageBuffer& b);
|
||||
|
||||
void SetSurface(Draw& w, int x, int y, int cx, int cy, const RGBA *pixels);
|
||||
|
||||
class Image : public AssignValueTypeNo< Image, 150, Moveable<Image> > {
|
||||
private:
|
||||
struct Data : Link<Data> {
|
||||
Atomic refcount;
|
||||
int64 serial;
|
||||
int paintcount;
|
||||
|
||||
static Link<Data> ResData[1];
|
||||
static int ResCount;
|
||||
|
||||
void Retain() { AtomicInc(refcount); }
|
||||
void Release() { if(AtomicDec(refcount) == 0) delete this; }
|
||||
|
||||
struct SystemData;
|
||||
|
||||
void *system_buffer[6];
|
||||
SystemData& Sys() const;
|
||||
|
||||
#ifdef PLATFORM_WIN32
|
||||
void CreateHBMP(HDC dc, const RGBA *data);
|
||||
int GetResCount() const;
|
||||
#endif
|
||||
|
||||
#ifdef PLATFORM_X11
|
||||
int cursor_cheat;
|
||||
XPicture picture;
|
||||
XPicture picture8;
|
||||
int GetResCount() const { return !!picture; }
|
||||
#endif
|
||||
|
||||
|
||||
ImageBuffer buffer;
|
||||
bool paintonly;
|
||||
|
||||
void SysInit();
|
||||
void SysRelease();
|
||||
int GetKind();
|
||||
void Paint(SystemDraw& w, int x, int y, const Rect& src, Color c);
|
||||
void PaintOnlyShrink();
|
||||
|
||||
Data(ImageBuffer& b);
|
||||
~Data();
|
||||
};
|
||||
|
||||
Data *data;
|
||||
|
||||
static Link<Image::Data> ResData[1];
|
||||
static int ResCount;
|
||||
|
||||
void Set(ImageBuffer& b);
|
||||
|
||||
friend class ImageBuffer;
|
||||
friend struct Data;
|
||||
|
||||
friend class SystemDraw;
|
||||
|
||||
void PaintImage(SystemDraw& w, int x, int y, const Rect& src, Color c) const;
|
||||
|
||||
friend void SetPaintOnly___(Image& m);
|
||||
friend void DrawImageBandRLE(Draw& w, int x, int y, const Image& m, int minp);
|
||||
|
||||
#ifdef PLATFORM_WIN32
|
||||
#ifndef PLATFORM_WINCE
|
||||
void SetCursorCheat(LPCSTR id);
|
||||
LPCSTR GetCursorCheat() const;
|
||||
friend Image Win32IconCursor(LPCSTR id, int iconsize, bool cursor);
|
||||
friend HICON IconWin32(const Image& img, bool cursor);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef PLATFORM_X11
|
||||
void SetCursorCheat(int id) { data->cursor_cheat = id; }
|
||||
int GetCursorCheat() const { return data ? data->cursor_cheat : -1; }
|
||||
friend Cursor X11Cursor(const Image&);
|
||||
friend Image sX11Cursor__(int c);
|
||||
#endif
|
||||
|
||||
public:
|
||||
const RGBA* operator~() const;
|
||||
operator const RGBA*() const;
|
||||
const RGBA* operator[](int i) const;
|
||||
|
||||
Size GetSize() const;
|
||||
int GetWidth() const { return GetSize().cx; }
|
||||
int GetHeight() const { return GetSize().cy; }
|
||||
int GetLength() const;
|
||||
Point GetHotSpot() const;
|
||||
Point Get2ndSpot() const;
|
||||
Size GetDots() const;
|
||||
int GetKindNoScan() const;
|
||||
int GetKind() const;
|
||||
|
||||
int64 GetSerialId() const { return data ? data->serial : 0; }
|
||||
bool IsSame(const Image& img) const { return GetSerialId() == img.GetSerialId(); }
|
||||
|
||||
bool operator==(const Image& img) const;
|
||||
bool operator!=(const Image& img) const;
|
||||
dword GetHashValue() const;
|
||||
String ToString() const;
|
||||
|
||||
void Serialize(Stream& s);
|
||||
void Clear();
|
||||
|
||||
Image& operator=(const Image& img);
|
||||
Image& operator=(ImageBuffer& img);
|
||||
|
||||
bool IsNullInstance() const { Size sz = GetSize(); return (sz.cx|sz.cy) == 0; }
|
||||
|
||||
bool IsEmpty() const { return IsNullInstance(); }
|
||||
operator Value() const { return RichValue<Image>(*this); }
|
||||
|
||||
Image() { data = NULL; }
|
||||
Image(const Nuller&) { data = NULL; }
|
||||
Image(const Value& src);
|
||||
Image(const Image& img);
|
||||
Image(Image (*fn)());
|
||||
Image(ImageBuffer& b);
|
||||
~Image();
|
||||
|
||||
|
||||
static Image Arrow();
|
||||
static Image Wait();
|
||||
static Image IBeam();
|
||||
static Image No();
|
||||
static Image SizeAll();
|
||||
static Image SizeHorz();
|
||||
static Image SizeVert();
|
||||
static Image SizeTopLeft();
|
||||
static Image SizeTop();
|
||||
static Image SizeTopRight();
|
||||
static Image SizeLeft();
|
||||
static Image SizeRight();
|
||||
static Image SizeBottomLeft();
|
||||
static Image SizeBottom();
|
||||
static Image SizeBottomRight();
|
||||
static Image Cross();
|
||||
static Image Hand();
|
||||
|
||||
// IML support ("private"), deprecated - legacy .iml
|
||||
struct Init {
|
||||
const char *const *scans;
|
||||
int16 scan_count;
|
||||
char info[24];
|
||||
};
|
||||
explicit Image(const Init& init);
|
||||
};
|
||||
|
||||
Image Premultiply(const Image& img);
|
||||
Image Unmultiply(const Image& img);
|
||||
|
||||
Vector<Image> UnpackImlData(const void *ptr, int len);
|
||||
Vector<Image> UnpackImlData(const String& d);
|
||||
|
||||
class Iml {
|
||||
struct IImage : Moveable<IImage> {
|
||||
bool loaded;
|
||||
Image image;
|
||||
|
||||
IImage() { loaded = false; }
|
||||
};
|
||||
struct Data : Moveable<Data> {
|
||||
const char *data;
|
||||
int len, count;
|
||||
};
|
||||
Vector<Data> data;
|
||||
VectorMap<String, IImage> map;
|
||||
const Image::Init *img_init;
|
||||
const char **name;
|
||||
bool premultiply;
|
||||
|
||||
void Init(int n);
|
||||
|
||||
public:
|
||||
void Enter();
|
||||
void Leave();
|
||||
void Reset();
|
||||
int GetCount() const { return map.GetCount(); }
|
||||
String GetId(int i) { return map.GetKey(i); }
|
||||
Image Get(int i);
|
||||
int Find(const String& s) const { return map.Find(s); }
|
||||
void Set(int i, const Image& img);
|
||||
void Premultiplied() { premultiply = false; }
|
||||
|
||||
#ifdef _DEBUG
|
||||
int GetBinSize() const;
|
||||
#endif
|
||||
|
||||
Iml(const Image::Init *img_init, const char **name, int n);//Deprecated - legacy .iml
|
||||
void AddData(const byte *data, int len, int count);
|
||||
};
|
||||
|
||||
void Register(const char *imageclass, Iml& iml);
|
||||
|
||||
int GetImlCount();
|
||||
String GetImlName(int i);
|
||||
Iml& GetIml(int i);
|
||||
int FindIml(const char *name);
|
||||
Image GetImlImage(const char *name);
|
||||
void SetImlImage(const char *name, const Image& m);
|
||||
|
||||
String StoreImageAsString(const Image& img);
|
||||
Image LoadImageFromString(const String& s);
|
||||
Size GetImageStringSize(const String& src);
|
||||
Size GetImageStringDots(const String& src);
|
||||
|
||||
#include "Raster.h"
|
||||
#include "ImageOp.h"
|
||||
|
||||
#ifdef PLATFORM_WIN32
|
||||
#ifndef PLATFORM_WINCE
|
||||
|
||||
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);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef PLATFORM_X11
|
||||
Cursor X11Cursor(const Image& img);
|
||||
#endif
|
||||
#define NEWIMAGE
|
||||
|
||||
enum ImageKind {
|
||||
IMAGE_UNKNOWN,
|
||||
IMAGE_EMPTY,
|
||||
IMAGE_ALPHA,
|
||||
IMAGE_MASK,
|
||||
IMAGE_OPAQUE,
|
||||
};
|
||||
|
||||
inline bool operator==(const RGBA& a, const RGBA& b)
|
||||
{
|
||||
return a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a;
|
||||
}
|
||||
|
||||
inline bool operator!=(const RGBA& a, const RGBA& b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
inline RGBA RGBAZero() { RGBA c; c.r = c.g = c.b = c.a = 0; return c; }
|
||||
|
||||
void Fill(RGBA *t, const RGBA& src, int n);
|
||||
void FillColor(RGBA *t, const RGBA& src, int n);
|
||||
|
||||
void Copy(RGBA *t, const RGBA *s, int n);
|
||||
|
||||
int Premultiply(RGBA *t, const RGBA *s, int len);
|
||||
int Unmultiply(RGBA *t, const RGBA *s, int len);
|
||||
|
||||
void AlphaBlend(RGBA *t, const RGBA *s, int len);
|
||||
void AlphaBlend(RGBA *t, const RGBA *s, int len, Color color);
|
||||
|
||||
void AlphaBlendOpaque(RGBA *t, const RGBA *s, int len, Color color);
|
||||
void AlphaBlendOpaque(RGBA *t, const RGBA *s, int len);
|
||||
|
||||
void AlphaBlendStraight(RGBA *b, const RGBA *f, int len);
|
||||
void AlphaBlendStraight(RGBA *b, const RGBA *f, int len, Color color);
|
||||
void AlphaBlendStraightOpaque(RGBA *t, const RGBA *s, int len);
|
||||
void AlphaBlendStraightOpaque(RGBA *t, const RGBA *s, int len, int alpha);
|
||||
|
||||
int GetChMaskPos32(dword mask);
|
||||
void AlphaBlendOverBgST(RGBA *b, RGBA bg, int len);
|
||||
|
||||
const byte *UnpackRLE(RGBA *t, const byte *src, int len);
|
||||
String PackRLE(const RGBA *s, int len);
|
||||
|
||||
inline int Grayscale(int r, int g, int b) { return (77 * r + 151 * g + 28 * b) >> 8; }
|
||||
inline int Grayscale(const RGBA& c) { return Grayscale(c.r, c.g, c.b); }
|
||||
inline byte Saturate255(int x) { return byte(~(x >> 24) & (x | (-(x >> 8) >> 24)) & 0xff); }
|
||||
|
||||
class Image;
|
||||
class ImageDraw;
|
||||
|
||||
class ImageBuffer : NoCopy {
|
||||
mutable int kind;
|
||||
Size size;
|
||||
Buffer<RGBA> pixels;
|
||||
Point hotspot;
|
||||
Point spot2;
|
||||
Size dots;
|
||||
|
||||
void Set(Image& img);
|
||||
void DeepCopy(const ImageBuffer& img);
|
||||
|
||||
RGBA* Line(int i) const { ASSERT(i >= 0 && i < size.cy); return (RGBA *)~pixels + i * size.cx; }
|
||||
friend void DropPixels___(ImageBuffer& b) { b.pixels.Clear(); }
|
||||
|
||||
friend class Image;
|
||||
|
||||
public:
|
||||
void SetKind(int k) { kind = k; }
|
||||
int GetKind() const { return kind; }
|
||||
int ScanKind() const;
|
||||
int GetScanKind() const { return kind == IMAGE_UNKNOWN ? ScanKind() : kind; }
|
||||
|
||||
void SetHotSpot(Point p) { hotspot = p; }
|
||||
Point GetHotSpot() const { return hotspot; }
|
||||
|
||||
void Set2ndSpot(Point p) { spot2 = p; }
|
||||
Point Get2ndSpot() const { return spot2; }
|
||||
|
||||
void SetDots(Size sz) { dots = sz; }
|
||||
Size GetDots() const { return dots; }
|
||||
|
||||
Size GetSize() const { return size; }
|
||||
int GetWidth() const { return size.cx; }
|
||||
int GetHeight() const { return size.cy; }
|
||||
int GetLength() const { return size.cx * size.cy; }
|
||||
|
||||
RGBA *operator[](int i) { return Line(i); }
|
||||
const RGBA *operator[](int i) const { return Line(i); }
|
||||
RGBA *operator~() { return pixels; }
|
||||
operator RGBA*() { return pixels; }
|
||||
const RGBA *operator~() const { return pixels; }
|
||||
operator const RGBA*() const { return pixels; }
|
||||
|
||||
void Create(int cx, int cy);
|
||||
void Create(Size sz) { Create(sz.cx, sz.cy); }
|
||||
bool IsEmpty() const { return (size.cx | size.cy) == 0; }
|
||||
void Clear() { Create(0, 0); }
|
||||
|
||||
void operator=(Image& img);
|
||||
void operator=(ImageBuffer& img);
|
||||
|
||||
ImageBuffer() { Create(0, 0); }
|
||||
ImageBuffer(int cx, int cy) { Create(cx, cy); }
|
||||
ImageBuffer(Size sz) { Create(sz.cx, sz.cy); }
|
||||
ImageBuffer(Image& img);
|
||||
ImageBuffer(ImageDraw& w);
|
||||
ImageBuffer(ImageBuffer& b);
|
||||
};
|
||||
|
||||
void Premultiply(ImageBuffer& b);
|
||||
void Unmultiply(ImageBuffer& b);
|
||||
|
||||
void SetSurface(Draw& w, int x, int y, int cx, int cy, const RGBA *pixels);
|
||||
|
||||
class Image : public AssignValueTypeNo< Image, 150, Moveable<Image> > {
|
||||
private:
|
||||
struct Data : Link<Data> {
|
||||
Atomic refcount;
|
||||
int64 serial;
|
||||
int paintcount;
|
||||
|
||||
static Link<Data> ResData[1];
|
||||
static int ResCount;
|
||||
|
||||
void Retain() { AtomicInc(refcount); }
|
||||
void Release() { if(AtomicDec(refcount) == 0) delete this; }
|
||||
|
||||
struct SystemData;
|
||||
|
||||
void *system_buffer[6];
|
||||
SystemData& Sys() const;
|
||||
int GetResCount() const;
|
||||
|
||||
#ifdef PLATFORM_WIN32
|
||||
void CreateHBMP(HDC dc, const RGBA *data);
|
||||
#endif
|
||||
|
||||
ImageBuffer buffer;
|
||||
bool paintonly;
|
||||
|
||||
void SysInit();
|
||||
void SysRelease();
|
||||
int GetKind();
|
||||
void Paint(SystemDraw& w, int x, int y, const Rect& src, Color c);
|
||||
void PaintOnlyShrink();
|
||||
|
||||
Data(ImageBuffer& b);
|
||||
~Data();
|
||||
};
|
||||
|
||||
Data *data;
|
||||
|
||||
static Link<Image::Data> ResData[1];
|
||||
static int ResCount;
|
||||
|
||||
void Set(ImageBuffer& b);
|
||||
|
||||
friend class ImageBuffer;
|
||||
friend struct Data;
|
||||
|
||||
friend class SystemDraw;
|
||||
|
||||
void PaintImage(SystemDraw& w, int x, int y, const Rect& src, Color c) const;
|
||||
|
||||
friend void SetPaintOnly___(Image& m);
|
||||
friend void DrawImageBandRLE(Draw& w, int x, int y, const Image& m, int minp);
|
||||
|
||||
#ifdef PLATFORM_WIN32
|
||||
#ifndef PLATFORM_WINCE
|
||||
void SetCursorCheat(LPCSTR id);
|
||||
LPCSTR GetCursorCheat() const;
|
||||
friend Image Win32IconCursor(LPCSTR id, int iconsize, bool cursor);
|
||||
friend HICON IconWin32(const Image& img, bool cursor);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef PLATFORM_X11
|
||||
void SetCursorCheat(int id);
|
||||
int GetCursorCheat() const;
|
||||
friend Cursor X11Cursor(const Image&);
|
||||
friend Image sX11Cursor__(int c);
|
||||
#endif
|
||||
|
||||
public:
|
||||
const RGBA* operator~() const;
|
||||
operator const RGBA*() const;
|
||||
const RGBA* operator[](int i) const;
|
||||
|
||||
Size GetSize() const;
|
||||
int GetWidth() const { return GetSize().cx; }
|
||||
int GetHeight() const { return GetSize().cy; }
|
||||
int GetLength() const;
|
||||
Point GetHotSpot() const;
|
||||
Point Get2ndSpot() const;
|
||||
Size GetDots() const;
|
||||
int GetKindNoScan() const;
|
||||
int GetKind() const;
|
||||
|
||||
int64 GetSerialId() const { return data ? data->serial : 0; }
|
||||
bool IsSame(const Image& img) const { return GetSerialId() == img.GetSerialId(); }
|
||||
|
||||
bool operator==(const Image& img) const;
|
||||
bool operator!=(const Image& img) const;
|
||||
dword GetHashValue() const;
|
||||
String ToString() const;
|
||||
|
||||
void Serialize(Stream& s);
|
||||
void Clear();
|
||||
|
||||
Image& operator=(const Image& img);
|
||||
Image& operator=(ImageBuffer& img);
|
||||
|
||||
bool IsNullInstance() const { Size sz = GetSize(); return (sz.cx|sz.cy) == 0; }
|
||||
|
||||
bool IsEmpty() const { return IsNullInstance(); }
|
||||
operator Value() const { return RichValue<Image>(*this); }
|
||||
|
||||
Image() { data = NULL; }
|
||||
Image(const Nuller&) { data = NULL; }
|
||||
Image(const Value& src);
|
||||
Image(const Image& img);
|
||||
Image(Image (*fn)());
|
||||
Image(ImageBuffer& b);
|
||||
~Image();
|
||||
|
||||
|
||||
static Image Arrow();
|
||||
static Image Wait();
|
||||
static Image IBeam();
|
||||
static Image No();
|
||||
static Image SizeAll();
|
||||
static Image SizeHorz();
|
||||
static Image SizeVert();
|
||||
static Image SizeTopLeft();
|
||||
static Image SizeTop();
|
||||
static Image SizeTopRight();
|
||||
static Image SizeLeft();
|
||||
static Image SizeRight();
|
||||
static Image SizeBottomLeft();
|
||||
static Image SizeBottom();
|
||||
static Image SizeBottomRight();
|
||||
static Image Cross();
|
||||
static Image Hand();
|
||||
|
||||
// IML support ("private"), deprecated - legacy .iml
|
||||
struct Init {
|
||||
const char *const *scans;
|
||||
int16 scan_count;
|
||||
char info[24];
|
||||
};
|
||||
explicit Image(const Init& init);
|
||||
};
|
||||
|
||||
Image Premultiply(const Image& img);
|
||||
Image Unmultiply(const Image& img);
|
||||
|
||||
Vector<Image> UnpackImlData(const void *ptr, int len);
|
||||
Vector<Image> UnpackImlData(const String& d);
|
||||
|
||||
class Iml {
|
||||
struct IImage : Moveable<IImage> {
|
||||
bool loaded;
|
||||
Image image;
|
||||
|
||||
IImage() { loaded = false; }
|
||||
};
|
||||
struct Data : Moveable<Data> {
|
||||
const char *data;
|
||||
int len, count;
|
||||
};
|
||||
Vector<Data> data;
|
||||
VectorMap<String, IImage> map;
|
||||
const Image::Init *img_init;
|
||||
const char **name;
|
||||
bool premultiply;
|
||||
|
||||
void Init(int n);
|
||||
|
||||
public:
|
||||
void Enter();
|
||||
void Leave();
|
||||
void Reset();
|
||||
int GetCount() const { return map.GetCount(); }
|
||||
String GetId(int i) { return map.GetKey(i); }
|
||||
Image Get(int i);
|
||||
int Find(const String& s) const { return map.Find(s); }
|
||||
void Set(int i, const Image& img);
|
||||
void Premultiplied() { premultiply = false; }
|
||||
|
||||
#ifdef _DEBUG
|
||||
int GetBinSize() const;
|
||||
#endif
|
||||
|
||||
Iml(const Image::Init *img_init, const char **name, int n);//Deprecated - legacy .iml
|
||||
void AddData(const byte *data, int len, int count);
|
||||
};
|
||||
|
||||
void Register(const char *imageclass, Iml& iml);
|
||||
|
||||
int GetImlCount();
|
||||
String GetImlName(int i);
|
||||
Iml& GetIml(int i);
|
||||
int FindIml(const char *name);
|
||||
Image GetImlImage(const char *name);
|
||||
void SetImlImage(const char *name, const Image& m);
|
||||
|
||||
String StoreImageAsString(const Image& img);
|
||||
Image LoadImageFromString(const String& s);
|
||||
Size GetImageStringSize(const String& src);
|
||||
Size GetImageStringDots(const String& src);
|
||||
|
||||
#include "Raster.h"
|
||||
#include "ImageOp.h"
|
||||
|
||||
#ifdef PLATFORM_WIN32
|
||||
#ifndef PLATFORM_WINCE
|
||||
|
||||
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);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef PLATFORM_X11
|
||||
Cursor X11Cursor(const Image& img);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -4,6 +4,28 @@ NAMESPACE_UPP
|
|||
|
||||
#ifdef PLATFORM_X11
|
||||
|
||||
struct Image::Data::SystemData {
|
||||
int cursor_cheat;
|
||||
XPicture picture;
|
||||
XPicture picture8;
|
||||
};
|
||||
|
||||
Image::Data::SystemData& Image::Data::Sys() const
|
||||
{
|
||||
ASSERT(sizeof(system_buffer) >= sizeof(SystemData));
|
||||
return *(SystemData *)system_buffer;
|
||||
}
|
||||
|
||||
void Image::SetCursorCheat(int id)
|
||||
{
|
||||
data->Sys().cursor_cheat = id;
|
||||
}
|
||||
|
||||
int Image::GetCursorCheat() const
|
||||
{
|
||||
return data ? data->Sys().cursor_cheat : -1;
|
||||
}
|
||||
|
||||
static void sInitXImage(XImage& ximg, Size sz)
|
||||
{
|
||||
Zero(ximg);
|
||||
|
|
@ -51,26 +73,33 @@ void SetSurface(SystemDraw& w, int x, int y, int cx, int cy, const RGBA *pixels)
|
|||
XRenderFreePicture(Xdisplay, picture);
|
||||
}
|
||||
|
||||
int Image::Data::GetResCount() const
|
||||
{
|
||||
return !!Sys().picture + !!Sys().picture8;
|
||||
}
|
||||
|
||||
void Image::Data::SysInit()
|
||||
{
|
||||
picture = 0;
|
||||
picture8 = 0;
|
||||
cursor_cheat = -1;
|
||||
SystemData& sd = Sys();
|
||||
sd.picture = 0;
|
||||
sd.picture8 = 0;
|
||||
sd.cursor_cheat = -1;
|
||||
}
|
||||
|
||||
void Image::Data::SysRelease()
|
||||
{
|
||||
if(picture) {
|
||||
SystemData& sd = Sys();
|
||||
if(sd.picture) {
|
||||
DrawLock __;
|
||||
if(Xdisplay) XRenderFreePicture(Xdisplay, picture);
|
||||
if(Xdisplay) XRenderFreePicture(Xdisplay, sd.picture);
|
||||
ResCount -= !paintonly;
|
||||
picture = 0;
|
||||
sd.picture = 0;
|
||||
}
|
||||
if(picture8) {
|
||||
if(sd.picture8) {
|
||||
DrawLock __;
|
||||
if(Xdisplay) XRenderFreePicture(Xdisplay, picture8);
|
||||
if(Xdisplay) XRenderFreePicture(Xdisplay, sd.picture8);
|
||||
ResCount -= !paintonly;
|
||||
picture8 = 0;
|
||||
sd.picture8 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -119,6 +148,7 @@ static XPicture sGetSolidFill(Color c)
|
|||
void Image::Data::Paint(SystemDraw& w, int x, int y, const Rect& src, Color c)
|
||||
{
|
||||
DrawLock __;
|
||||
SystemData& sd = Sys();
|
||||
while(ResCount > 512) {
|
||||
Image::Data *l = ResData->GetPrev();
|
||||
l->SysRelease();
|
||||
|
|
@ -146,10 +176,10 @@ void Image::Data::Paint(SystemDraw& w, int x, int y, const Rect& src, Color c)
|
|||
Unlink();
|
||||
LinkAfter(ResData);
|
||||
if(IsNull(c)) {
|
||||
if(!picture) {
|
||||
if(!sd.picture) {
|
||||
bool opaque = GetKind() == IMAGE_OPAQUE;
|
||||
Pixmap pixmap = XCreatePixmap(Xdisplay, Xroot, sz.cx, sz.cy, opaque ? 24 : 32);
|
||||
picture = XRenderCreatePicture(
|
||||
sd.picture = XRenderCreatePicture(
|
||||
Xdisplay, pixmap,
|
||||
XRenderFindStandardFormat(Xdisplay, opaque ? PictStandardRGB24
|
||||
: PictStandardARGB32),
|
||||
|
|
@ -175,16 +205,16 @@ void Image::Data::Paint(SystemDraw& w, int x, int y, const Rect& src, Color c)
|
|||
PaintOnlyShrink();
|
||||
}
|
||||
XRenderComposite(Xdisplay, PictOpOver,
|
||||
picture, 0, XftDrawPicture(w.GetXftDraw()),
|
||||
sd.picture, 0, XftDrawPicture(w.GetXftDraw()),
|
||||
sr.left, sr.top, 0, 0, x, y, ssz.cx, ssz.cy);
|
||||
}
|
||||
else {
|
||||
ASSERT(!paintonly);
|
||||
if(!picture8) {
|
||||
if(!sd.picture8) {
|
||||
Pixmap pixmap = XCreatePixmap(Xdisplay, Xroot, sz.cx, sz.cy, 8);
|
||||
picture8 = XRenderCreatePicture(Xdisplay, pixmap,
|
||||
XRenderFindStandardFormat(Xdisplay, PictStandardA8),
|
||||
0, 0);
|
||||
sd.picture8 = XRenderCreatePicture(Xdisplay, pixmap,
|
||||
XRenderFindStandardFormat(Xdisplay, PictStandardA8),
|
||||
0, 0);
|
||||
ResCount++;
|
||||
Buffer<byte> ab(len);
|
||||
byte *t = ab;
|
||||
|
|
@ -207,7 +237,7 @@ void Image::Data::Paint(SystemDraw& w, int x, int y, const Rect& src, Color c)
|
|||
XFreePixmap(Xdisplay, pixmap);
|
||||
}
|
||||
XRenderComposite(Xdisplay, PictOpOver,
|
||||
sGetSolidFill(c), picture8, XftDrawPicture(w.GetXftDraw()),
|
||||
sGetSolidFill(c), sd.picture8, XftDrawPicture(w.GetXftDraw()),
|
||||
sr.left, sr.top, 0, 0, x, y, ssz.cx, ssz.cy);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue