From 379bc287f1dbf4d290b2116867df835cbf2bf290 Mon Sep 17 00:00:00 2001 From: cxl Date: Sun, 5 Jul 2009 14:48:03 +0000 Subject: [PATCH] Developing newdraw git-svn-id: svn://ultimatepp.org/upp/trunk@1359 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- newdraw/Draw/Draw.h | 2029 +++++++++++++++++----------------- newdraw/Draw/Draw.upp | 1 + newdraw/Draw/DrawOpX11.cpp | 87 -- newdraw/Draw/DrawTextX11.cpp | 221 ++++ newdraw/Draw/Font.cpp | 612 +++++----- 5 files changed, 1545 insertions(+), 1405 deletions(-) create mode 100644 newdraw/Draw/DrawTextX11.cpp diff --git a/newdraw/Draw/Draw.h b/newdraw/Draw/Draw.h index 9f155aac6..81d6d3725 100644 --- a/newdraw/Draw/Draw.h +++ b/newdraw/Draw/Draw.h @@ -1,1012 +1,1017 @@ -#ifndef DRAW_H -#define DRAW_H - -#define SYSTEMDRAW 1 - -#include - -#ifdef PLATFORM_X11 - -#define Time XTime -#define Font XFont -#define Display XDisplay -#define Picture XPicture - -#include -#include -#include - -#include -#include - -#undef Picture -#undef Time -#undef Font -#undef Display - -#undef True -#undef False - -#define XFalse 0 -#define XTrue 1 -#endif - - -NAMESPACE_UPP - -#ifdef PLATFORM_X11 - -extern XDisplay *Xdisplay; -extern Visual *Xvisual; -extern int Xscreenno; -extern Window Xroot; -extern Screen *Xscreen; -extern Colormap Xcolormap; -extern int Xheight; -extern int Xwidth; -extern int XheightMM; -extern int XwidthMM; -extern int Xdepth; -extern dword Xblack; -extern dword Xwhite; -extern int Xconnection; - -extern dword (*Xgetpixel)(int r, int g, int b); - -void InitX11Draw(const char *dispname = NULL); -void InitX11Draw(XDisplay *display); - -void XError(); -void XError(const char *s); - -inline dword GetXPixel(int r, int g, int b) { return (*Xgetpixel)(r, g, b); } -inline dword GetXPixel(Color color) { return (*Xgetpixel)(color.GetR(), color.GetG(), color.GetB()); } - -enum { - X11_ROP2_ZERO, - X11_ROP2_AND, - X11_ROP2_AND_NOT, - X11_ROP2_COPY, - X11_ROP2_NOT_AND, - X11_ROP2_NOP, - X11_ROP2_XOR, - X11_ROP2_OR, - X11_ROP2_NOT_AND_NOT, - X11_ROP2_NOT_XOR, - X11_ROP2_INVERT, - X11_ROP2_OR_NOT, - X11_ROP2_NOT_COPY, - X11_ROP2_NOT_OR, - X11_ROP2_NOT_OR_NOT, - X11_ROP2_ONE, -}; - -#endif - -class Drawing; -class Draw; -class Painting; -class SystemDraw; - -#ifdef PLATFORM_WIN32 -HDC ScreenHDC(); -#endif - -bool ScreenInPaletteMode(); -Size GetScreenSize(); - -#include "Image.h" - -#ifdef _MULTITHREADED -void EnterGuiMutex(); -void EnterGuiMutex(int n); -void LeaveGuiMutex(); -int LeaveGuiMutexAll(); - -struct GuiLock { - GuiLock() { EnterGuiMutex(); } - ~GuiLock() { LeaveGuiMutex(); } -}; -#else -inline void EnterGuiMutex() {} -inline void EnterGuiMutex(int n) {} -inline void LeaveGuiMutex() {} -inline int LeaveGuiMutexAll() { return 0; } - -struct GuiLock { - GuiLock() {} - ~GuiLock() {} -}; -#endif - -typedef GuiLock DrawLock; - -const int FONT_V = 40; - -class FontInfo; - -class Font : AssignValueTypeNo >{ - word face; - word flags; - int16 height; - int16 width; - -public: - enum { - FIXEDPITCH = 0x0001, - SCALEABLE = 0x0002, - SYMBOLTYPE = 0x0004, - COMPOSED = 0x0008, - LOCAL = 0x0010, - }; - - static int GetFaceCount(); - static String GetFaceName(int index); - static int FindFaceNameIndex(const char *name); - static dword GetFaceInfo(int index); - - enum { - STDFONT, - SCREEN_SERIF, - SCREEN_SANS, - SCREEN_FIXED, - ROMAN, - ARIAL, - COURIER, - SYMBOL, - #ifdef PLATFORM_WIN32 - WINGDINGS, - TAHOMA, - #endif - OTHER, - }; - - int GetFace() const { return face; } - int GetHeight() const { return height; } - int GetWidth() const { return width; } - bool IsBold() const { return flags & 0x8000; } - bool IsItalic() const { return flags & 0x4000; } - bool IsUnderline() const { return flags & 0x2000; } - bool IsStrikeout() const { return flags & 0x1000; } - bool IsNonAntiAliased() const { return flags & 0x800; } - bool IsTrueTypeOnly() const { return flags & 0x400; } - String GetFaceName() const; - dword GetFaceInfo() const; - - FontInfo Info() const; - - Font& Face(int n) { face = n; return *this; } - Font& Height(int n) { height = n; return *this; } - Font& Width(int n) { width = n; return *this; } - Font& Bold() { flags |= 0x8000; return *this; } - Font& NoBold() { flags &= ~0x8000; return *this; } - Font& Bold(bool b) { return b ? Bold() : NoBold(); } - Font& Italic() { flags |= 0x4000; return *this; } - Font& NoItalic() { flags &= ~0x4000; return *this; } - Font& Italic(bool b) { return b ? Italic() : NoItalic(); } - Font& Underline() { flags |= 0x2000; return *this; } - Font& NoUnderline() { flags &= ~0x2000; return *this; } - Font& Underline(bool b) { return b ? Underline() : NoUnderline(); } - Font& Strikeout() { flags |= 0x1000; return *this; } - Font& NoStrikeout() { flags &= ~0x1000; return *this; } - Font& Strikeout(bool b) { return b ? Strikeout() : NoStrikeout(); } - Font& NonAntiAliased() { flags |= 0x800; return *this; } - Font& NoNonAntiAliased() { flags &= ~0x800; return *this; } - Font& NonAntiAliased(bool b) { return b ? NonAntiAliased() : NoNonAntiAliased(); } - Font& TrueTypeOnly() { flags |= 0x400; return *this; } - Font& NoTrueTypeOnly() { flags &= ~0x400; return *this; } - Font& TrueTypeOnly(bool b) { return b ? TrueTypeOnly() : NoTrueTypeOnly(); } - Font& FaceName(const String& name); - - Font operator()() const { return *this; } - Font operator()(int n) const { return Font(*this).Height(n); } - - void Serialize(Stream& s); - - bool operator==(Font f) const { return face == f.face && flags == f.flags && - width == f.width && height == f.height; } - bool operator!=(Font f) const { return !operator==(f); } - - dword GetHashValue() const { return CombineHash(width, flags, height, face); } - bool IsNull() const { return face == 0xffff; } - - Font() { height = width = 0; face = flags = 0; } - Font(int _face, int _height) { face = _face; height = _height; flags = 0; width = 0; } - Font(const Nuller&) { face = 0xffff; height = width = 0; flags = 0; } - - operator Value() const { return RichValue(*this); } - Font(const Value& q) { *this = RichValue::Extract(q); } -}; - -template<> -inline bool IsNull(const Font& f) { return f.IsNull(); } - -template<> -inline unsigned GetHashValue(const Font& f) { return f.GetHashValue(); } - -template<> -String AsString(const Font& f); - -class FontInfo : Moveable { - struct CharMetrics : Moveable { - int width; - int lspc; - int rspc; - - bool operator==(const CharMetrics& b) const - { return width == b.width && lspc == b.lspc && rspc == b.rspc; } - }; - - struct Kinfo : Moveable { - CharMetrics std; - byte *flags; - - Kinfo() { - flags = NULL; - } - ~Kinfo() { - if(flags) - delete[] flags; - } - }; - - struct Data : public Link { - bool HasChar(int ch) const; - void GetMetrics(CharMetrics *t, int from, int count); - #ifdef PLATFORM_X11 - void CreateFont(int i, int cs); - #endif - - int refcount; - Font font; - int angle; - #ifdef PLATFORM_WIN32 - HFONT hfont; - #endif - #ifdef PLATFORM_X11 - XftFont *xftfont; - XftFont *xftfont0; - #endif - int ascent; - int descent; - int external; - int internal; - int height; - int lineheight; - int overhang; - Size offset; - int avewidth; - int maxwidth; - int firstchar; - int charcount; - int default_char; - - CharMetrics *base[64]; - - Mutex xmutex; - Vector kinfo; - VectorMap xx; - - bool fixedpitch; - bool scaleable; - int spacebefore; - int spaceafter; - #ifdef PLATFORM_X11 - int underline_position; - int underline_thickness; - double sina; - double cosa; - bool twobyte; - String filename; - #endif - - VectorMap kerning; - - Data(); - ~Data(); - }; - - Data *ptr; - int charset; - - CharMetrics *CreateMetricsPage(int page) const; - CharMetrics *GetPage(int page) const; - void ComposeMetrics(Font fnt, CharMetrics *m, int from) const; - CharMetrics GetCM(int c) const; - - void Release(); - void Retain(const FontInfo& f); - FontInfo(Data *ptr) : ptr(ptr) { charset = CHARSET_UNICODE; } - - bool IsEqual(byte charset, Font f, int angle) const; - CharMetrics GetComposedMetrics(int c); - - static void InitPlatformFonts(); - static Size StdFontSize; - static Font AStdFont; - static int FontCacheMax; - static int FontCached; - - enum { LRU, HASH, FONTHASH = 97 }; - - - static Data *GetFontHash(int i); - static Data *GetFontLru(); - static void InitFonts(); - static void SyncStdFont(); - static void FreeFonts(); - static FontInfo AcquireFontInfo(Font font, int angle); - - typedef Link FontLink; - -#ifdef PLATFORM_WIN32 - static int CALLBACK AddFace(const LOGFONT *logfont, const TEXTMETRIC *, dword type, LPARAM param); - static int EnumFace(HDC hdc, const char *face); - static void ForceFace(HDC hdc, const char *face, const char *aface); - static FontInfo AcquireFontInfo0(Font font, HDC hdc, int angle); -#endif - -#ifdef PLATFORM_X11 - static XftFont *CreateXftFont(Font font, int angle); -#endif - - friend class Font; - friend class Draw; - friend class SystemDraw; - friend void StaticExitDraw_(); - -public: - int GetAscent() const { return ptr->ascent; } - int GetDescent() const { return ptr->descent; } - int GetExternal() const { return ptr->external; } - int GetInternal() const { return ptr->internal; } - int GetHeight() const { return ptr->height; } - int GetLineHeight() const { return ptr->lineheight; } - int GetOverhang() const { return ptr->overhang; } - int GetAveWidth() const { return ptr->avewidth; } - int GetMaxWidth() const { return ptr->maxwidth; } - int HasChar(int ch) const { return ptr->HasChar(ch); } - int GetWidth(int c) const; - int operator[](int c) const { return GetWidth(c); } - int GetLeftSpace(int c) const; - int GetRightSpace(int c) const; - int GetKerning(int c1, int c2) const { return ptr->kerning.Get(MAKELONG(c1, c2), 0); } - bool IsFixedPitch() const { return ptr->fixedpitch; } - bool IsScaleable() const { return ptr->scaleable; } - - Font GetFont() const { return ptr->font; } - int GetFontHeight() const { return ptr->font.GetHeight(); } - -#ifdef PLATFORM_X11 - String GetFileName() const; - XftFont *GetXftFont() const { return ptr->xftfont0; } -#endif -#ifdef PLATFORM_WIN32 - HFONT GetHFONT() const { return ptr->hfont; } -#endif - - void Clear() { Release(); ptr = NULL; } - bool IsEmpty() const { return !ptr; } - operator bool() const { return ptr; } - - FontInfo(const FontInfo& f); - FontInfo& operator=(const FontInfo& f); - - FontInfo(); - ~FontInfo() { Release(); } - - static void SetStdFont(Font font); - static Font GetStdFont() { return AStdFont; } - static Size GetStdFontSize(); -}; - -inline void SetStdFont(Font font) { FontInfo::SetStdFont(font); } -inline Font GetStdFont() { return FontInfo::GetStdFont(); } -inline Size GetStdFontSize() { return FontInfo::GetStdFontSize(); } -inline int GetStdFontCy() { return GetStdFontSize().cy; } - -Font StdFont(); - -inline Font StdFont(int h) { return StdFont().Height(h); } - -struct ScreenSans : public Font { ScreenSans(int n = 0) : Font(SCREEN_SANS, n) {} }; -struct ScreenSerif : public Font { ScreenSerif(int n = 0) : Font(SCREEN_SERIF, n) {} }; -struct ScreenFixed : public Font { ScreenFixed(int n = 0) : Font(SCREEN_FIXED, n) {} }; - -struct Roman : public Font { Roman(int n) : Font(ROMAN, n) {} }; -struct Arial : public Font { Arial(int n) : Font(ARIAL, n) {} }; -struct Courier : public Font { Courier(int n) : Font(COURIER, n) {} }; -struct Symbol : public Font { Symbol(int n) : Font(SYMBOL, n) {} }; - -#ifdef PLATFORM_WIN32 -struct WingDings : public Font { WingDings(int n) : Font(WINGDINGS, n) {} }; -struct Tahoma : public Font { Tahoma(int n) : Font(TAHOMA, n) {} }; -#endif - -#ifdef PLATFORM_WIN32 -#ifndef PLATFORM_WINCE -HPALETTE GetQlibPalette(); -#endif -#endif - -Size GetTextSize(const wchar *text, Font font, int n = -1); -Size GetTextSize(const WString& text, Font font); -Size GetTextSize(const char *text, byte charset, Font font, int n = -1); -Size GetTextSize(const char *text, Font font, int n = -1); -Size GetTextSize(const String& text, Font font); - -enum { - PEN_NULL = -1, - PEN_SOLID = -2, - PEN_DASH = -3, -#ifndef PLATFORM_WINCE - PEN_DOT = -4, - PEN_DASHDOT = -5, - PEN_DASHDOTDOT = -6, -#endif -}; - -class Image; - -//DEPRECATED: TODO -Color SBlack(); -Color SGray(); -Color SLtGray(); -Color SWhiteGray(); -Color SWhite(); -Color SRed(); -Color SGreen(); -Color SBrown(); -Color SBlue(); -Color SMagenta(); -Color SCyan(); -Color SYellow(); -Color SLtRed(); -Color SLtGreen(); -Color SLtYellow(); -Color SLtBlue(); -Color SLtMagenta(); -Color SLtCyan(); -//END OF DEPRECATED - -Color SColorPaper(); -Color SColorText(); -Color SColorHighlight(); -Color SColorHighlightText();// -Color SColorMenu(); -Color SColorMenuText(); -Color SColorInfo(); -Color SColorInfoText();// -Color SColorMark(); -Color SColorDisabled(); -Color SColorLight(); -Color SColorFace(); -Color SColorLabel(); -Color SColorShadow(); - -Color SColorLtFace(); -Color SColorDkShadow(); - - -void SBlack_Write(Color c); -void SGray_Write(Color c); -void SLtGray_Write(Color c); -void SWhiteGray_Write(Color c); -void SWhite_Write(Color c); -void SRed_Write(Color c); -void SGreen_Write(Color c); -void SBrown_Write(Color c); -void SBlue_Write(Color c); -void SMagenta_Write(Color c); -void SCyan_Write(Color c); -void SYellow_Write(Color c); -void SLtRed_Write(Color c); -void SLtGreen_Write(Color c); -void SLtYellow_Write(Color c); -void SLtBlue_Write(Color c); -void SLtMagenta_Write(Color c); -void SLtCyan_Write(Color c); - -void SColorPaper_Write(Color c); -void SColorText_Write(Color c); -void SColorHighlight_Write(Color c); -void SColorHighlightText_Write(Color c);// -void SColorMenu_Write(Color c); -void SColorMenuText_Write(Color c); -void SColorInfo_Write(Color c); -void SColorInfoText_Write(Color c);// -void SColorMark_Write(Color c); -void SColorDisabled_Write(Color c); -void SColorLight_Write(Color c); -void SColorFace_Write(Color c); -void SColorLabel_Write(Color c); -void SColorShadow_Write(Color c); - -void SColorLtFace_Write(Color c); -void SColorDkShadow_Write(Color c); - - -inline Color InvertColor() { return Color(255, 0); } -inline Color DefaultInk() { return Black(); } //TODO! - -class Painting : AssignValueTypeNo > { - String cmd; - ValueArray data; - Sizef size; - - friend class PaintingPainter; - friend class Painter; - -public: - Sizef GetSize() const { return size; } - - void Clear() { size = Null; data.Clear(); cmd.Clear(); } - void Serialize(Stream& s) { s % cmd % data % size; } - bool IsNullInstance() const { return cmd.IsEmpty(); } - bool operator==(const Painting& b) const { return cmd == b.cmd && data == b.data && size == b.size; } - unsigned GetHashValue() const { return CombineHash(cmd, data); } - String ToString() const { return "painting " + AsString(size); } - - operator Value() const { return RichValue(*this); } - Painting(const Value& q) { *this = RichValue::Extract(q); } - - Painting() { size = Null; } - Painting(const Nuller&) { size = Null; } -}; - -enum { - MODE_ANTIALIASED = 0, - MODE_NOAA = 1, - MODE_SUBPIXEL = 2, -}; - -bool HasPainter(); -void PaintImageBuffer(ImageBuffer& ib, const Painting& p, Size sz, Point pos, int mode = MODE_ANTIALIASED); -void PaintImageBuffer(ImageBuffer& ib, const Painting& p, int mode = MODE_ANTIALIASED); -void PaintImageBuffer(ImageBuffer& ib, const Drawing& p, int mode = MODE_ANTIALIASED); - -class Draw : NoCopy { -private: - struct DrawingPos; - - void ComposeText(int x, int y, int angle, const wchar *text, Font font, Color ink, int n, const int *dx); - -public: - enum { - DOTS = 0x001, - GUI = 0x002, - PRINTER = 0x004, - NATIVE = 0x008, - }; - - virtual dword GetInfo() const = 0; - - virtual Size GetPageSize() const; - virtual void StartPage(); - virtual void EndPage(); - - virtual void BeginOp() = 0; - virtual void EndOp() = 0; - virtual void OffsetOp(Point p) = 0; - virtual bool ClipOp(const Rect& r) = 0; - virtual bool ClipoffOp(const Rect& r) = 0; - virtual bool ExcludeClipOp(const Rect& r) = 0; - virtual bool IntersectClipOp(const Rect& r) = 0; - virtual bool IsPaintingOp(const Rect& r) const = 0; - - virtual void DrawRectOp(int x, int y, int cx, int cy, Color color) = 0; - virtual void DrawImageOp(int x, int y, int cx, int cy, const Image& img, const Rect& src, Color color) = 0; - virtual void DrawDataOp(int x, int y, int cx, int cy, const String& data, const char *id); - virtual void DrawLineOp(int x1, int y1, int x2, int y2, int width, Color color) = 0; - - virtual void DrawPolyPolylineOp(const Point *vertices, int vertex_count, - const int *counts, int count_count, - int width, Color color, Color doxor) = 0; - 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) = 0; - virtual void DrawArcOp(const Rect& rc, Point start, Point end, int width, Color color) = 0; - - virtual void DrawEllipseOp(const Rect& r, Color color, int pen, Color pencolor) = 0; - virtual void DrawTextOp(int x, int y, int angle, const wchar *text, Font font, - Color ink, int n, const int *dx) = 0; - virtual void DrawDrawingOp(const Rect& target, const Drawing& w); - virtual void DrawPaintingOp(const Rect& target, const Painting& w); - - virtual Size GetNativeDpi() const; - virtual void BeginNative(); - virtual void EndNative(); - - virtual int GetCloffLevel() const; - - virtual ~Draw(); - -// -------------- - Size GetPixelsPerInch() const; - Size GetPageMMs() const; - - bool Dots() const { return GetInfo() & DOTS; } - bool Pixels() const { return !Dots(); } - bool IsGui() const { return GetInfo() & GUI; } - bool IsPrinter() const { return GetInfo() & PRINTER; } - bool IsNative() const { return GetInfo() & NATIVE; } - - int GetNativeX(int x) const; - int GetNativeY(int x) const; - void Native(int& x, int& y) const; - void Native(Point& p) const; - void Native(Size& sz) const; - void Native(Rect& r) const; - - void Begin() { BeginOp(); } - void End() { EndOp(); } - void Offset(Point p) { OffsetOp(p); } - void Offset(int x, int y); - bool Clip(const Rect& r) { return ClipOp(r); } - bool Clip(int x, int y, int cx, int cy); - bool Clipoff(const Rect& r) { return ClipoffOp(r); } - bool Clipoff(int x, int y, int cx, int cy); - bool ExcludeClip(const Rect& r) { return ExcludeClipOp(r); } - bool ExcludeClip(int x, int y, int cx, int cy); - bool IntersectClip(const Rect& r) { return IntersectClipOp(r); } - bool IntersectClip(int x, int y, int cx, int cy); - bool IsPainting(const Rect& r) const { return IsPaintingOp(r); } - bool IsPainting(int x, int y, int cx, int cy) const; - - void DrawRect(int x, int y, int cx, int cy, Color color); - void DrawRect(const Rect& rect, Color color); - - void DrawImage(int x, int y, int cx, int cy, const Image& img, const Rect& src); - void DrawImage(int x, int y, int cx, int cy, const Image& img); - void DrawImage(int x, int y, int cx, int cy, const Image& img, const Rect& src, Color color); - void DrawImage(int x, int y, int cx, int cy, const Image& img, Color color); - - void DrawImage(const Rect& r, const Image& img, const Rect& src); - void DrawImage(const Rect& r, const Image& img); - void DrawImage(const Rect& r, const Image& img, const Rect& src, Color color); - void DrawImage(const Rect& r, const Image& img, Color color); - - void DrawImage(int x, int y, const Image& img, const Rect& src); - void DrawImage(int x, int y, const Image& img); - void DrawImage(int x, int y, const Image& img, const Rect& src, Color color); - void DrawImage(int x, int y, const Image& img, Color color); - - void DrawData(int x, int y, int cx, int cy, const String& data, const char *type); - void DrawData(const Rect& r, const String& data, const char *type); - - void DrawLine(int x1, int y1, int x2, int y2, int width = 0, Color color = DefaultInk); - void DrawLine(Point p1, Point p2, int width = 0, Color color = DefaultInk); - - void DrawEllipse(const Rect& r, Color color = DefaultInk, - int pen = Null, Color pencolor = DefaultInk); - void DrawEllipse(int x, int y, int cx, int cy, Color color = DefaultInk, - int pen = Null, Color pencolor = DefaultInk); - - void DrawArc(const Rect& rc, Point start, Point end, int width = 0, Color color = DefaultInk); - - void DrawPolyPolyline(const Point *vertices, int vertex_count, - const int *counts, int count_count, - int width = 0, Color color = DefaultInk, Color doxor = Null); - void DrawPolyPolyline(const Vector& vertices, const Vector& counts, - int width = 0, Color color = DefaultInk, Color doxor = Null); - void DrawPolyline(const Point *vertices, int count, - int width = 0, Color color = DefaultInk, Color doxor = Null); - void DrawPolyline(const Vector& vertices, - int width = 0, Color color = DefaultInk, Color doxor = Null); - - void DrawPolyPolyPolygon(const Point *vertices, int vertex_count, - const int *subpolygon_counts, int subpolygon_count_count, - const int *disjunct_polygon_counts, int disjunct_polygon_count_count, - Color color = DefaultInk, int width = 0, Color outline = Null, - uint64 pattern = 0, Color doxor = Null); - void DrawPolyPolyPolygon(const Vector& vertices, - const Vector& subpolygon_counts, - const Vector& disjunct_polygon_counts, - Color color = DefaultInk, int width = 0, Color outline = Null, uint64 pattern = 0, Color doxor = Null); - void DrawPolyPolygon(const Point *vertices, int vertex_count, - const int *subpolygon_counts, int subpolygon_count_count, - Color color = DefaultInk, int width = 0, Color outline = Null, uint64 pattern = 0, Color doxor = Null); - void DrawPolyPolygon(const Vector& vertices, const Vector& subpolygon_counts, - Color color = DefaultInk, int width = 0, Color outline = Null, uint64 pattern = 0, Color doxor = Null); - void DrawPolygons(const Point *vertices, int vertex_count, - const int *polygon_counts, int polygon_count_count, - Color color = DefaultInk, int width = 0, Color outline = Null, uint64 pattern = 0, Color doxor = Null); - void DrawPolygons(const Vector& vertices, const Vector& polygon_counts, - Color color = DefaultInk, int width = 0, Color outline = Null, uint64 pattern = 0, Color doxor = Null); - void DrawPolygon(const Point *vertices, int vertex_count, - Color color = DefaultInk, int width = 0, Color outline = Null, uint64 pattern = 0, Color doxor = Null); - void DrawPolygon(const Vector& vertices, - Color color = DefaultInk, int width = 0, Color outline = Null, uint64 pattern = 0, Color doxor = Null); - - void DrawDrawing(const Rect& r, const Drawing& iw) { DrawDrawingOp(r, iw); } - void DrawDrawing(int x, int y, int cx, int cy, const Drawing& iw); - - void DrawPainting(const Rect& r, const Painting& iw) { DrawPaintingOp(r, iw); } - void DrawPainting(int x, int y, int cx, int cy, const Painting& iw); - - void DrawText(int x, int y, int angle, const wchar *text, Font font = StdFont(), - Color ink = DefaultInk, int n = -1, const int *dx = NULL); - void DrawText(int x, int y, const wchar *text, Font font = StdFont(), - Color ink = DefaultInk, int n = -1, const int *dx = NULL); - - void DrawText(int x, int y, const WString& text, Font font = StdFont(), - Color ink = DefaultInk, const int *dx = NULL); - void DrawText(int x, int y, int angle, const WString& text, Font font = StdFont(), - Color ink = DefaultInk, const int *dx = NULL); - - void DrawText(int x, int y, int angle, const char *text, byte charset, - Font font = StdFont(), Color ink = DefaultInk, int n = -1, const int *dx = NULL); - void DrawText(int x, int y, const char *text, byte charset, Font font = StdFont(), - Color ink = DefaultInk, int n = -1, const int *dx = NULL); - - void DrawText(int x, int y, int angle, const char *text, - Font font = StdFont(), Color ink = DefaultInk, int n = -1, const int *dx = NULL); - void DrawText(int x, int y, const char *text, Font font = StdFont(), - Color ink = DefaultInk, int n = -1, const int *dx = NULL); - - void DrawText(int x, int y, const String& text, Font font = StdFont(), - Color ink = DefaultInk, const int *dx = NULL); - void DrawText(int x, int y, int angle, const String& text, Font font = StdFont(), - Color ink = DefaultInk, const int *dx = NULL); - - static void SinCos(int angle, double& sina, double& cosa); - - // deprecated: - static void SetStdFont(Font font) { UPP::SetStdFont(font); } - static Font GetStdFont() { return UPP::GetStdFont(); } - static Size GetStdFontSize() { return UPP::GetStdFontSize(); } - static int GetStdFontCy() { return GetStdFontSize().cy; } - - -#ifdef PLATFORM_WIN32_ - static void Flush(); - HDC BeginGdi(); - void EndGdi(); -#endif -}; - -void DrawImageBandRLE(Draw& w, int x, int y, const Image& m, int minp); - -class DataDrawer { - typedef DataDrawer *(*Factory)(); - template static DataDrawer *FactoryFn() { return new T; } - static void AddFormat(const char *id, Factory f); - static VectorMap& Map(); - -public: - virtual void Open(const String& data, int cx, int cy) = 0; - virtual void Render(ImageBuffer& ib) = 0; - virtual ~DataDrawer(); - - static One Create(const String& id); - - template static void Register(const char *id) { AddFormat(id, &DataDrawer::FactoryFn); } -}; - -class Drawing : AssignValueTypeNo > { - Size size; - String data; - ValueArray val; - - friend class DrawingDraw; - friend class Draw; - -public: - operator bool() const { return !data.IsEmpty(); } - Size GetSize() const { return size; } - void SetSize(Size sz) { size = sz; } - void SetSize(int cx, int cy) { size = Size(cx, cy); } - - Size RatioSize(int cx, int cy) const; - Size RatioSize(Size sz) const { return RatioSize(sz.cx, sz.cy); } - - void Clear() { data.Clear(); size = Null; } - - void Append(Drawing& dw); - - void Serialize(Stream& s); - - bool IsNullInstance() const { return data.IsEmpty(); } - bool operator==(const Drawing& b) const { return val == b.val && data == b.data && size == b.size; } - String ToString() const { return "drawing " + AsString(size); } - unsigned GetHashValue() const { return CombineHash(data, val); } - - operator Value() const { return RichValue(*this); } - Drawing(const Value& src); - - Drawing() { size = Null; } - Drawing(const Nuller&) { size = Null; } -}; - -class DrawingDraw : 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 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 DrawDataOp(int x, int y, int cx, int cy, const String& data, const char *id); - 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 DrawEllipseOp(const Rect& r, Color color, int pen, Color pencolor); - virtual void DrawArcOp(const Rect& rc, Point start, Point end, 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 void DrawDrawingOp(const Rect& target, const Drawing& w); - virtual void DrawPaintingOp(const Rect& target, const Painting& w); - -private: - Size size; - StringStream drawing; - ValueArray val; - - Stream& DrawingOp(int code); - -public: - void Create(int cx, int cy); - void Create(Size sz); - - Size GetSize() const { return size; } - - Drawing GetResult(); - operator Drawing() { return GetResult(); } - - DrawingDraw(); - DrawingDraw(int cx, int cy); - DrawingDraw(Size sz); -}; - -class NilDraw : 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 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 DrawDataOp(int x, int y, int cx, int cy, const String& data, const char *id); - 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 void DrawDrawingOp(const Rect& target, const Drawing& w); - virtual void DrawPaintingOp(const Rect& target, const Painting& w); -}; - -void AddNotEmpty(Vector& result, int left, int right, int top, int bottom); -bool Subtract(const Rect& r, const Rect& sub, Vector& result); -bool Subtract(const Vector& rr, const Rect& sub, Vector& result); -Vector Subtract(const Vector& rr, const Rect& sub, bool& changed); -Vector Intersect(const Vector& b, const Rect& a, bool& changed); - -void Subtract(Vector& rr, const Rect& sub); -void Union(Vector& rr, const Rect& add); - -#ifdef PLATFORM_X11 -void SetClip(GC gc, XftDraw *xftdraw, const Vector& cl); -#endif - -void DrawRect(Draw& w, const Rect& rect, const Image& img, bool ralgn = false); //??? TODO -void DrawRect(Draw& w, int x, int y, int cx, int cy, const Image& img, bool ra = false); - -void DrawTiles(Draw& w, int x, int y, int cx, int cy, const Image& img); -void DrawTiles(Draw& w, const Rect& rect, const Image& img); - -void DrawFatFrame(Draw& w, int x, int y, int cx, int cy, Color color, int n); -void DrawFatFrame(Draw& w, const Rect& r, Color color, int n); - -void DrawFrame(Draw& w, int x, int y, int cx, int cy, - Color leftcolor, Color topcolor, Color rightcolor, Color bottomcolor); -void DrawFrame(Draw& w, const Rect& r, - Color leftcolor, Color topcolor, Color rightcolor, Color bottomcolor); -void DrawFrame(Draw& w, int x, int y, int cx, int cy, - Color topleftcolor, Color bottomrightcolor); -void DrawFrame(Draw& w, const Rect& r, - Color topleftcolor, Color bottomrightcolor); -void DrawFrame(Draw& w, int x, int y, int cx, int cy, Color color); -void DrawFrame(Draw& w, const Rect& r, Color color); - -void DrawBorder(Draw& w, int x, int y, int cx, int cy, const ColorF *colors_ltrd); //TODO -void DrawBorder(Draw& w, const Rect& r, const ColorF *colors_ltrd); - -const ColorF *BlackBorder(); -const ColorF *ButtonPushBorder(); -const ColorF *EdgeButtonBorder(); -const ColorF *DefButtonBorder(); -const ColorF *ButtonBorder(); -const ColorF *InsetBorder(); -const ColorF *OutsetBorder(); -const ColorF *ThinOutsetBorder(); -const ColorF *ThinInsetBorder(); - -void DrawBorder(Draw& w, int x, int y, int cx, int cy, const ColorF *(*colors_ltrd)()); -void DrawBorder(Draw& w, const Rect& r, const ColorF *(*colors_ltrd)()); - -void DrawRectMinusRect(Draw& w, const Rect& rect, const Rect& inner, Color color); - -void DrawHighlightImage(Draw& w, int x, int y, const Image& img, bool highlight = true, - bool enabled = true, Color maskcolor = SColorPaper); - -Color GradientColor(Color fc, Color tc, int i, int n); - -void DrawDragRect(SystemDraw& w, const Rect& rect1, const Rect& rect2, const Rect& clip, int n, Color color, uint64 pattern); - -enum { - BUTTON_NORMAL, BUTTON_OK, BUTTON_HIGHLIGHT, BUTTON_PUSH, BUTTON_DISABLED, BUTTON_CHECKED, - BUTTON_VERTICAL = 0x100, - BUTTON_EDGE = 0x200, - BUTTON_TOOL = 0x400, - BUTTON_SCROLL = 0x800, -}; - -void DrawXPButton(Draw& w, Rect r, int type); - -void DrawTextEllipsis(Draw& w, int x, int y, int cx, const char *text, const char *ellipsis, - Font font = StdFont(), Color ink = SColorText(), int n = -1); -void DrawTextEllipsis(Draw& w, int x, int y, int cx, const wchar *text, const char *ellipsis, - Font font = StdFont(), Color ink = SColorText(), int n = -1); -Size GetTLTextSize(const wchar *text, Font font = StdFont()); -int GetTLTextHeight(const wchar *s, Font font = StdFont()); -void DrawTLText(Draw& draw, int x, int y, int cx, const wchar *text, Font font = StdFont(), - Color ink = SColorText(), int accesskey = 0); - - -typedef String (*DrawingToPdfFnType)(const Array& report, Size pagesize, int margin); - -void SetDrawingToPdfFn(DrawingToPdfFnType Pdf); -DrawingToPdfFnType GetDrawingToPdfFn(); - -#ifdef PLATFORM_WIN32 -#include "DrawWin32.h" -#endif - -#ifdef PLATFORM_X11 -#include "DrawX11.h" -#endif - -#include "BackDraw.h" - -#include "Display.h" -#include "ImageDraw.h" -#include "Debug.h" -#include "Cham.h" - -typedef ImageDraw SystemImageDraw; - -END_UPP_NAMESPACE - -#endif +#ifndef DRAW_H +#define DRAW_H + +#define SYSTEMDRAW 1 + +#include + +#ifdef PLATFORM_X11 + +#define Time XTime +#define Font XFont +#define Display XDisplay +#define Picture XPicture + +#include +#include +#include + +#include +#include + +#undef Picture +#undef Time +#undef Font +#undef Display + +#undef True +#undef False + +#define XFalse 0 +#define XTrue 1 +#endif + + +NAMESPACE_UPP + +#ifdef PLATFORM_X11 + +extern XDisplay *Xdisplay; +extern Visual *Xvisual; +extern int Xscreenno; +extern Window Xroot; +extern Screen *Xscreen; +extern Colormap Xcolormap; +extern int Xheight; +extern int Xwidth; +extern int XheightMM; +extern int XwidthMM; +extern int Xdepth; +extern dword Xblack; +extern dword Xwhite; +extern int Xconnection; + +extern dword (*Xgetpixel)(int r, int g, int b); + +void InitX11Draw(const char *dispname = NULL); +void InitX11Draw(XDisplay *display); + +void XError(); +void XError(const char *s); + +inline dword GetXPixel(int r, int g, int b) { return (*Xgetpixel)(r, g, b); } +inline dword GetXPixel(Color color) { return (*Xgetpixel)(color.GetR(), color.GetG(), color.GetB()); } + +enum { + X11_ROP2_ZERO, + X11_ROP2_AND, + X11_ROP2_AND_NOT, + X11_ROP2_COPY, + X11_ROP2_NOT_AND, + X11_ROP2_NOP, + X11_ROP2_XOR, + X11_ROP2_OR, + X11_ROP2_NOT_AND_NOT, + X11_ROP2_NOT_XOR, + X11_ROP2_INVERT, + X11_ROP2_OR_NOT, + X11_ROP2_NOT_COPY, + X11_ROP2_NOT_OR, + X11_ROP2_NOT_OR_NOT, + X11_ROP2_ONE, +}; + +#endif + +class Drawing; +class Draw; +class Painting; +class SystemDraw; + +#ifdef PLATFORM_WIN32 +HDC ScreenHDC(); +#endif + +bool ScreenInPaletteMode(); +Size GetScreenSize(); + +#include "Image.h" + +#ifdef _MULTITHREADED +void EnterGuiMutex(); +void EnterGuiMutex(int n); +void LeaveGuiMutex(); +int LeaveGuiMutexAll(); + +struct GuiLock { + GuiLock() { EnterGuiMutex(); } + ~GuiLock() { LeaveGuiMutex(); } +}; +#else +inline void EnterGuiMutex() {} +inline void EnterGuiMutex(int n) {} +inline void LeaveGuiMutex() {} +inline int LeaveGuiMutexAll() { return 0; } + +struct GuiLock { + GuiLock() {} + ~GuiLock() {} +}; +#endif + +typedef GuiLock DrawLock; + +const int FONT_V = 40; + +class FontInfo; + +class Font : AssignValueTypeNo >{ + union { + int64 data; + struct { + word face; + word flags; + int16 height; + int16 width; + } v; + }; + +public: + enum { + FIXEDPITCH = 0x0001, + SCALEABLE = 0x0002, + SYMBOLTYPE = 0x0004, + COMPOSED = 0x0008, + LOCAL = 0x0010, + }; + + static int GetFaceCount(); + static String GetFaceName(int index); + static int FindFaceNameIndex(const char *name); + static dword GetFaceInfo(int index); + + enum { + STDFONT, + SCREEN_SERIF, + SCREEN_SANS, + SCREEN_FIXED, + ROMAN, + ARIAL, + COURIER, + SYMBOL, + #ifdef PLATFORM_WIN32 + WINGDINGS, + TAHOMA, + #endif + OTHER, + }; + + int GetFace() const { return v.face; } + int GetHeight() const { return v.height; } + int GetWidth() const { return v.width; } + bool IsBold() const { return v.flags & 0x8000; } + bool IsItalic() const { return v.flags & 0x4000; } + bool IsUnderline() const { return v.flags & 0x2000; } + bool IsStrikeout() const { return v.flags & 0x1000; } + bool IsNonAntiAliased() const { return v.flags & 0x800; } + bool IsTrueTypeOnly() const { return v.flags & 0x400; } + String GetFaceName() const; + dword GetFaceInfo() const; + + FontInfo Info() const; + + Font& Face(int n) { v.face = n; return *this; } + Font& Height(int n) { v.height = n; return *this; } + Font& Width(int n) { v.width = n; return *this; } + Font& Bold() { v.flags |= 0x8000; return *this; } + Font& NoBold() { v.flags &= ~0x8000; return *this; } + Font& Bold(bool b) { return b ? Bold() : NoBold(); } + Font& Italic() { v.flags |= 0x4000; return *this; } + Font& NoItalic() { v.flags &= ~0x4000; return *this; } + Font& Italic(bool b) { return b ? Italic() : NoItalic(); } + Font& Underline() { v.flags |= 0x2000; return *this; } + Font& NoUnderline() { v.flags &= ~0x2000; return *this; } + Font& Underline(bool b) { return b ? Underline() : NoUnderline(); } + Font& Strikeout() { v.flags |= 0x1000; return *this; } + Font& NoStrikeout() { v.flags &= ~0x1000; return *this; } + Font& Strikeout(bool b) { return b ? Strikeout() : NoStrikeout(); } + Font& NonAntiAliased() { v.flags |= 0x800; return *this; } + Font& NoNonAntiAliased() { v.flags &= ~0x800; return *this; } + Font& NonAntiAliased(bool b) { return b ? NonAntiAliased() : NoNonAntiAliased(); } + Font& TrueTypeOnly() { v.flags |= 0x400; return *this; } + Font& NoTrueTypeOnly() { v.flags &= ~0x400; return *this; } + Font& TrueTypeOnly(bool b) { return b ? TrueTypeOnly() : NoTrueTypeOnly(); } + Font& FaceName(const String& name); + + Font operator()() const { return *this; } + Font operator()(int n) const { return Font(*this).Height(n); } + + void Serialize(Stream& s); + + bool operator==(Font f) const { return v.face == f.v.face && v.flags == f.v.flags && + v.width == f.v.width && v.height == f.v.height; } + bool operator!=(Font f) const { return !operator==(f); } + + dword GetHashValue() const { return CombineHash(v.width, v.flags, v.height, v.face); } + bool IsNull() const { return v.face == 0xffff; } + + Font() { v.height = v.width = 0; v.face = v.flags = 0; } + Font(int face, int height) { v.face = face; v.height = height; v.flags = 0; v.width = 0; } + Font(const Nuller&) { v.face = 0xffff; v.height = v.width = 0; v.flags = 0; } + + operator Value() const { return RichValue(*this); } + Font(const Value& q) { *this = RichValue::Extract(q); } +}; + +template<> +inline bool IsNull(const Font& f) { return f.IsNull(); } + +template<> +inline unsigned GetHashValue(const Font& f) { return f.GetHashValue(); } + +template<> +String AsString(const Font& f); + +class FontInfo : Moveable { + struct CharMetrics : Moveable { + int width; + int lspc; + int rspc; + + bool operator==(const CharMetrics& b) const + { return width == b.width && lspc == b.lspc && rspc == b.rspc; } + }; + + struct Kinfo : Moveable { + CharMetrics std; + byte *flags; + + Kinfo() { + flags = NULL; + } + ~Kinfo() { + if(flags) + delete[] flags; + } + }; + + struct Data : public Link { + bool HasChar(int ch) const; + void GetMetrics(CharMetrics *t, int from, int count); + #ifdef PLATFORM_X11 + void CreateFont(int i, int cs); + #endif + + int refcount; + Font font; + int angle; + #ifdef PLATFORM_WIN32 + HFONT hfont; + #endif + #ifdef PLATFORM_X11 + XftFont *xftfont; + XftFont *xftfont0; + #endif + int ascent; + int descent; + int external; + int internal; + int height; + int lineheight; + int overhang; + Size offset; + int avewidth; + int maxwidth; + int firstchar; + int charcount; + int default_char; + + CharMetrics *base[64]; + + Mutex xmutex; + Vector kinfo; + VectorMap xx; + + bool fixedpitch; + bool scaleable; + int spacebefore; + int spaceafter; + #ifdef PLATFORM_X11 + int underline_position; + int underline_thickness; + double sina; + double cosa; + bool twobyte; + String filename; + #endif + + VectorMap kerning; + + Data(); + ~Data(); + }; + + Data *ptr; + int charset; + + CharMetrics *CreateMetricsPage(int page) const; + CharMetrics *GetPage(int page) const; + void ComposeMetrics(Font fnt, CharMetrics *m, int from) const; + CharMetrics GetCM(int c) const; + + void Release(); + void Retain(const FontInfo& f); + FontInfo(Data *ptr) : ptr(ptr) { charset = CHARSET_UNICODE; } + + bool IsEqual(byte charset, Font f, int angle) const; + CharMetrics GetComposedMetrics(int c); + + static void InitPlatformFonts(); + static Size StdFontSize; + static Font AStdFont; + static int FontCacheMax; + static int FontCached; + + enum { LRU, HASH, FONTHASH = 97 }; + + + static Data *GetFontHash(int i); + static Data *GetFontLru(); + static void InitFonts(); + static void SyncStdFont(); + static void FreeFonts(); + static FontInfo AcquireFontInfo(Font font, int angle); + + typedef Link FontLink; + +#ifdef PLATFORM_WIN32 + static int CALLBACK AddFace(const LOGFONT *logfont, const TEXTMETRIC *, dword type, LPARAM param); + static int EnumFace(HDC hdc, const char *face); + static void ForceFace(HDC hdc, const char *face, const char *aface); + static FontInfo AcquireFontInfo0(Font font, HDC hdc, int angle); +#endif + +#ifdef PLATFORM_X11 + static XftFont *CreateXftFont(Font font, int angle); +#endif + + friend class Font; + friend class Draw; + friend class SystemDraw; + friend void StaticExitDraw_(); + +public: + int GetAscent() const { return ptr->ascent; } + int GetDescent() const { return ptr->descent; } + int GetExternal() const { return ptr->external; } + int GetInternal() const { return ptr->internal; } + int GetHeight() const { return ptr->height; } + int GetLineHeight() const { return ptr->lineheight; } + int GetOverhang() const { return ptr->overhang; } + int GetAveWidth() const { return ptr->avewidth; } + int GetMaxWidth() const { return ptr->maxwidth; } + int HasChar(int ch) const { return ptr->HasChar(ch); } + int GetWidth(int c) const; + int operator[](int c) const { return GetWidth(c); } + int GetLeftSpace(int c) const; + int GetRightSpace(int c) const; + int GetKerning(int c1, int c2) const { return ptr->kerning.Get(MAKELONG(c1, c2), 0); } + bool IsFixedPitch() const { return ptr->fixedpitch; } + bool IsScaleable() const { return ptr->scaleable; } + + Font GetFont() const { return ptr->font; } + int GetFontHeight() const { return ptr->font.GetHeight(); } + +#ifdef PLATFORM_X11 + String GetFileName() const; + XftFont *GetXftFont() const { return ptr->xftfont0; } +#endif +#ifdef PLATFORM_WIN32 + HFONT GetHFONT() const { return ptr->hfont; } +#endif + + void Clear() { Release(); ptr = NULL; } + bool IsEmpty() const { return !ptr; } + operator bool() const { return ptr; } + + FontInfo(const FontInfo& f); + FontInfo& operator=(const FontInfo& f); + + FontInfo(); + ~FontInfo() { Release(); } + + static void SetStdFont(Font font); + static Font GetStdFont() { return AStdFont; } + static Size GetStdFontSize(); +}; + +inline void SetStdFont(Font font) { FontInfo::SetStdFont(font); } +inline Font GetStdFont() { return FontInfo::GetStdFont(); } +inline Size GetStdFontSize() { return FontInfo::GetStdFontSize(); } +inline int GetStdFontCy() { return GetStdFontSize().cy; } + +Font StdFont(); + +inline Font StdFont(int h) { return StdFont().Height(h); } + +struct ScreenSans : public Font { ScreenSans(int n = 0) : Font(SCREEN_SANS, n) {} }; +struct ScreenSerif : public Font { ScreenSerif(int n = 0) : Font(SCREEN_SERIF, n) {} }; +struct ScreenFixed : public Font { ScreenFixed(int n = 0) : Font(SCREEN_FIXED, n) {} }; + +struct Roman : public Font { Roman(int n) : Font(ROMAN, n) {} }; +struct Arial : public Font { Arial(int n) : Font(ARIAL, n) {} }; +struct Courier : public Font { Courier(int n) : Font(COURIER, n) {} }; +struct Symbol : public Font { Symbol(int n) : Font(SYMBOL, n) {} }; + +#ifdef PLATFORM_WIN32 +struct WingDings : public Font { WingDings(int n) : Font(WINGDINGS, n) {} }; +struct Tahoma : public Font { Tahoma(int n) : Font(TAHOMA, n) {} }; +#endif + +#ifdef PLATFORM_WIN32 +#ifndef PLATFORM_WINCE +HPALETTE GetQlibPalette(); +#endif +#endif + +Size GetTextSize(const wchar *text, Font font, int n = -1); +Size GetTextSize(const WString& text, Font font); +Size GetTextSize(const char *text, byte charset, Font font, int n = -1); +Size GetTextSize(const char *text, Font font, int n = -1); +Size GetTextSize(const String& text, Font font); + +enum { + PEN_NULL = -1, + PEN_SOLID = -2, + PEN_DASH = -3, +#ifndef PLATFORM_WINCE + PEN_DOT = -4, + PEN_DASHDOT = -5, + PEN_DASHDOTDOT = -6, +#endif +}; + +class Image; + +//DEPRECATED: TODO +Color SBlack(); +Color SGray(); +Color SLtGray(); +Color SWhiteGray(); +Color SWhite(); +Color SRed(); +Color SGreen(); +Color SBrown(); +Color SBlue(); +Color SMagenta(); +Color SCyan(); +Color SYellow(); +Color SLtRed(); +Color SLtGreen(); +Color SLtYellow(); +Color SLtBlue(); +Color SLtMagenta(); +Color SLtCyan(); +//END OF DEPRECATED + +Color SColorPaper(); +Color SColorText(); +Color SColorHighlight(); +Color SColorHighlightText();// +Color SColorMenu(); +Color SColorMenuText(); +Color SColorInfo(); +Color SColorInfoText();// +Color SColorMark(); +Color SColorDisabled(); +Color SColorLight(); +Color SColorFace(); +Color SColorLabel(); +Color SColorShadow(); + +Color SColorLtFace(); +Color SColorDkShadow(); + + +void SBlack_Write(Color c); +void SGray_Write(Color c); +void SLtGray_Write(Color c); +void SWhiteGray_Write(Color c); +void SWhite_Write(Color c); +void SRed_Write(Color c); +void SGreen_Write(Color c); +void SBrown_Write(Color c); +void SBlue_Write(Color c); +void SMagenta_Write(Color c); +void SCyan_Write(Color c); +void SYellow_Write(Color c); +void SLtRed_Write(Color c); +void SLtGreen_Write(Color c); +void SLtYellow_Write(Color c); +void SLtBlue_Write(Color c); +void SLtMagenta_Write(Color c); +void SLtCyan_Write(Color c); + +void SColorPaper_Write(Color c); +void SColorText_Write(Color c); +void SColorHighlight_Write(Color c); +void SColorHighlightText_Write(Color c);// +void SColorMenu_Write(Color c); +void SColorMenuText_Write(Color c); +void SColorInfo_Write(Color c); +void SColorInfoText_Write(Color c);// +void SColorMark_Write(Color c); +void SColorDisabled_Write(Color c); +void SColorLight_Write(Color c); +void SColorFace_Write(Color c); +void SColorLabel_Write(Color c); +void SColorShadow_Write(Color c); + +void SColorLtFace_Write(Color c); +void SColorDkShadow_Write(Color c); + + +inline Color InvertColor() { return Color(255, 0); } +inline Color DefaultInk() { return Black(); } //TODO! + +class Painting : AssignValueTypeNo > { + String cmd; + ValueArray data; + Sizef size; + + friend class PaintingPainter; + friend class Painter; + +public: + Sizef GetSize() const { return size; } + + void Clear() { size = Null; data.Clear(); cmd.Clear(); } + void Serialize(Stream& s) { s % cmd % data % size; } + bool IsNullInstance() const { return cmd.IsEmpty(); } + bool operator==(const Painting& b) const { return cmd == b.cmd && data == b.data && size == b.size; } + unsigned GetHashValue() const { return CombineHash(cmd, data); } + String ToString() const { return "painting " + AsString(size); } + + operator Value() const { return RichValue(*this); } + Painting(const Value& q) { *this = RichValue::Extract(q); } + + Painting() { size = Null; } + Painting(const Nuller&) { size = Null; } +}; + +enum { + MODE_ANTIALIASED = 0, + MODE_NOAA = 1, + MODE_SUBPIXEL = 2, +}; + +bool HasPainter(); +void PaintImageBuffer(ImageBuffer& ib, const Painting& p, Size sz, Point pos, int mode = MODE_ANTIALIASED); +void PaintImageBuffer(ImageBuffer& ib, const Painting& p, int mode = MODE_ANTIALIASED); +void PaintImageBuffer(ImageBuffer& ib, const Drawing& p, int mode = MODE_ANTIALIASED); + +class Draw : NoCopy { +private: + struct DrawingPos; + + void ComposeText(int x, int y, int angle, const wchar *text, Font font, Color ink, int n, const int *dx); + +public: + enum { + DOTS = 0x001, + GUI = 0x002, + PRINTER = 0x004, + NATIVE = 0x008, + }; + + virtual dword GetInfo() const = 0; + + virtual Size GetPageSize() const; + virtual void StartPage(); + virtual void EndPage(); + + virtual void BeginOp() = 0; + virtual void EndOp() = 0; + virtual void OffsetOp(Point p) = 0; + virtual bool ClipOp(const Rect& r) = 0; + virtual bool ClipoffOp(const Rect& r) = 0; + virtual bool ExcludeClipOp(const Rect& r) = 0; + virtual bool IntersectClipOp(const Rect& r) = 0; + virtual bool IsPaintingOp(const Rect& r) const = 0; + + virtual void DrawRectOp(int x, int y, int cx, int cy, Color color) = 0; + virtual void DrawImageOp(int x, int y, int cx, int cy, const Image& img, const Rect& src, Color color) = 0; + virtual void DrawDataOp(int x, int y, int cx, int cy, const String& data, const char *id); + virtual void DrawLineOp(int x1, int y1, int x2, int y2, int width, Color color) = 0; + + virtual void DrawPolyPolylineOp(const Point *vertices, int vertex_count, + const int *counts, int count_count, + int width, Color color, Color doxor) = 0; + 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) = 0; + virtual void DrawArcOp(const Rect& rc, Point start, Point end, int width, Color color) = 0; + + virtual void DrawEllipseOp(const Rect& r, Color color, int pen, Color pencolor) = 0; + virtual void DrawTextOp(int x, int y, int angle, const wchar *text, Font font, + Color ink, int n, const int *dx) = 0; + virtual void DrawDrawingOp(const Rect& target, const Drawing& w); + virtual void DrawPaintingOp(const Rect& target, const Painting& w); + + virtual Size GetNativeDpi() const; + virtual void BeginNative(); + virtual void EndNative(); + + virtual int GetCloffLevel() const; + + virtual ~Draw(); + +// -------------- + Size GetPixelsPerInch() const; + Size GetPageMMs() const; + + bool Dots() const { return GetInfo() & DOTS; } + bool Pixels() const { return !Dots(); } + bool IsGui() const { return GetInfo() & GUI; } + bool IsPrinter() const { return GetInfo() & PRINTER; } + bool IsNative() const { return GetInfo() & NATIVE; } + + int GetNativeX(int x) const; + int GetNativeY(int x) const; + void Native(int& x, int& y) const; + void Native(Point& p) const; + void Native(Size& sz) const; + void Native(Rect& r) const; + + void Begin() { BeginOp(); } + void End() { EndOp(); } + void Offset(Point p) { OffsetOp(p); } + void Offset(int x, int y); + bool Clip(const Rect& r) { return ClipOp(r); } + bool Clip(int x, int y, int cx, int cy); + bool Clipoff(const Rect& r) { return ClipoffOp(r); } + bool Clipoff(int x, int y, int cx, int cy); + bool ExcludeClip(const Rect& r) { return ExcludeClipOp(r); } + bool ExcludeClip(int x, int y, int cx, int cy); + bool IntersectClip(const Rect& r) { return IntersectClipOp(r); } + bool IntersectClip(int x, int y, int cx, int cy); + bool IsPainting(const Rect& r) const { return IsPaintingOp(r); } + bool IsPainting(int x, int y, int cx, int cy) const; + + void DrawRect(int x, int y, int cx, int cy, Color color); + void DrawRect(const Rect& rect, Color color); + + void DrawImage(int x, int y, int cx, int cy, const Image& img, const Rect& src); + void DrawImage(int x, int y, int cx, int cy, const Image& img); + void DrawImage(int x, int y, int cx, int cy, const Image& img, const Rect& src, Color color); + void DrawImage(int x, int y, int cx, int cy, const Image& img, Color color); + + void DrawImage(const Rect& r, const Image& img, const Rect& src); + void DrawImage(const Rect& r, const Image& img); + void DrawImage(const Rect& r, const Image& img, const Rect& src, Color color); + void DrawImage(const Rect& r, const Image& img, Color color); + + void DrawImage(int x, int y, const Image& img, const Rect& src); + void DrawImage(int x, int y, const Image& img); + void DrawImage(int x, int y, const Image& img, const Rect& src, Color color); + void DrawImage(int x, int y, const Image& img, Color color); + + void DrawData(int x, int y, int cx, int cy, const String& data, const char *type); + void DrawData(const Rect& r, const String& data, const char *type); + + void DrawLine(int x1, int y1, int x2, int y2, int width = 0, Color color = DefaultInk); + void DrawLine(Point p1, Point p2, int width = 0, Color color = DefaultInk); + + void DrawEllipse(const Rect& r, Color color = DefaultInk, + int pen = Null, Color pencolor = DefaultInk); + void DrawEllipse(int x, int y, int cx, int cy, Color color = DefaultInk, + int pen = Null, Color pencolor = DefaultInk); + + void DrawArc(const Rect& rc, Point start, Point end, int width = 0, Color color = DefaultInk); + + void DrawPolyPolyline(const Point *vertices, int vertex_count, + const int *counts, int count_count, + int width = 0, Color color = DefaultInk, Color doxor = Null); + void DrawPolyPolyline(const Vector& vertices, const Vector& counts, + int width = 0, Color color = DefaultInk, Color doxor = Null); + void DrawPolyline(const Point *vertices, int count, + int width = 0, Color color = DefaultInk, Color doxor = Null); + void DrawPolyline(const Vector& vertices, + int width = 0, Color color = DefaultInk, Color doxor = Null); + + void DrawPolyPolyPolygon(const Point *vertices, int vertex_count, + const int *subpolygon_counts, int subpolygon_count_count, + const int *disjunct_polygon_counts, int disjunct_polygon_count_count, + Color color = DefaultInk, int width = 0, Color outline = Null, + uint64 pattern = 0, Color doxor = Null); + void DrawPolyPolyPolygon(const Vector& vertices, + const Vector& subpolygon_counts, + const Vector& disjunct_polygon_counts, + Color color = DefaultInk, int width = 0, Color outline = Null, uint64 pattern = 0, Color doxor = Null); + void DrawPolyPolygon(const Point *vertices, int vertex_count, + const int *subpolygon_counts, int subpolygon_count_count, + Color color = DefaultInk, int width = 0, Color outline = Null, uint64 pattern = 0, Color doxor = Null); + void DrawPolyPolygon(const Vector& vertices, const Vector& subpolygon_counts, + Color color = DefaultInk, int width = 0, Color outline = Null, uint64 pattern = 0, Color doxor = Null); + void DrawPolygons(const Point *vertices, int vertex_count, + const int *polygon_counts, int polygon_count_count, + Color color = DefaultInk, int width = 0, Color outline = Null, uint64 pattern = 0, Color doxor = Null); + void DrawPolygons(const Vector& vertices, const Vector& polygon_counts, + Color color = DefaultInk, int width = 0, Color outline = Null, uint64 pattern = 0, Color doxor = Null); + void DrawPolygon(const Point *vertices, int vertex_count, + Color color = DefaultInk, int width = 0, Color outline = Null, uint64 pattern = 0, Color doxor = Null); + void DrawPolygon(const Vector& vertices, + Color color = DefaultInk, int width = 0, Color outline = Null, uint64 pattern = 0, Color doxor = Null); + + void DrawDrawing(const Rect& r, const Drawing& iw) { DrawDrawingOp(r, iw); } + void DrawDrawing(int x, int y, int cx, int cy, const Drawing& iw); + + void DrawPainting(const Rect& r, const Painting& iw) { DrawPaintingOp(r, iw); } + void DrawPainting(int x, int y, int cx, int cy, const Painting& iw); + + void DrawText(int x, int y, int angle, const wchar *text, Font font = StdFont(), + Color ink = DefaultInk, int n = -1, const int *dx = NULL); + void DrawText(int x, int y, const wchar *text, Font font = StdFont(), + Color ink = DefaultInk, int n = -1, const int *dx = NULL); + + void DrawText(int x, int y, const WString& text, Font font = StdFont(), + Color ink = DefaultInk, const int *dx = NULL); + void DrawText(int x, int y, int angle, const WString& text, Font font = StdFont(), + Color ink = DefaultInk, const int *dx = NULL); + + void DrawText(int x, int y, int angle, const char *text, byte charset, + Font font = StdFont(), Color ink = DefaultInk, int n = -1, const int *dx = NULL); + void DrawText(int x, int y, const char *text, byte charset, Font font = StdFont(), + Color ink = DefaultInk, int n = -1, const int *dx = NULL); + + void DrawText(int x, int y, int angle, const char *text, + Font font = StdFont(), Color ink = DefaultInk, int n = -1, const int *dx = NULL); + void DrawText(int x, int y, const char *text, Font font = StdFont(), + Color ink = DefaultInk, int n = -1, const int *dx = NULL); + + void DrawText(int x, int y, const String& text, Font font = StdFont(), + Color ink = DefaultInk, const int *dx = NULL); + void DrawText(int x, int y, int angle, const String& text, Font font = StdFont(), + Color ink = DefaultInk, const int *dx = NULL); + + static void SinCos(int angle, double& sina, double& cosa); + + // deprecated: + static void SetStdFont(Font font) { UPP::SetStdFont(font); } + static Font GetStdFont() { return UPP::GetStdFont(); } + static Size GetStdFontSize() { return UPP::GetStdFontSize(); } + static int GetStdFontCy() { return GetStdFontSize().cy; } + + +#ifdef PLATFORM_WIN32_ + static void Flush(); + HDC BeginGdi(); + void EndGdi(); +#endif +}; + +void DrawImageBandRLE(Draw& w, int x, int y, const Image& m, int minp); + +class DataDrawer { + typedef DataDrawer *(*Factory)(); + template static DataDrawer *FactoryFn() { return new T; } + static void AddFormat(const char *id, Factory f); + static VectorMap& Map(); + +public: + virtual void Open(const String& data, int cx, int cy) = 0; + virtual void Render(ImageBuffer& ib) = 0; + virtual ~DataDrawer(); + + static One Create(const String& id); + + template static void Register(const char *id) { AddFormat(id, &DataDrawer::FactoryFn); } +}; + +class Drawing : AssignValueTypeNo > { + Size size; + String data; + ValueArray val; + + friend class DrawingDraw; + friend class Draw; + +public: + operator bool() const { return !data.IsEmpty(); } + Size GetSize() const { return size; } + void SetSize(Size sz) { size = sz; } + void SetSize(int cx, int cy) { size = Size(cx, cy); } + + Size RatioSize(int cx, int cy) const; + Size RatioSize(Size sz) const { return RatioSize(sz.cx, sz.cy); } + + void Clear() { data.Clear(); size = Null; } + + void Append(Drawing& dw); + + void Serialize(Stream& s); + + bool IsNullInstance() const { return data.IsEmpty(); } + bool operator==(const Drawing& b) const { return val == b.val && data == b.data && size == b.size; } + String ToString() const { return "drawing " + AsString(size); } + unsigned GetHashValue() const { return CombineHash(data, val); } + + operator Value() const { return RichValue(*this); } + Drawing(const Value& src); + + Drawing() { size = Null; } + Drawing(const Nuller&) { size = Null; } +}; + +class DrawingDraw : 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 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 DrawDataOp(int x, int y, int cx, int cy, const String& data, const char *id); + 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 DrawEllipseOp(const Rect& r, Color color, int pen, Color pencolor); + virtual void DrawArcOp(const Rect& rc, Point start, Point end, 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 void DrawDrawingOp(const Rect& target, const Drawing& w); + virtual void DrawPaintingOp(const Rect& target, const Painting& w); + +private: + Size size; + StringStream drawing; + ValueArray val; + + Stream& DrawingOp(int code); + +public: + void Create(int cx, int cy); + void Create(Size sz); + + Size GetSize() const { return size; } + + Drawing GetResult(); + operator Drawing() { return GetResult(); } + + DrawingDraw(); + DrawingDraw(int cx, int cy); + DrawingDraw(Size sz); +}; + +class NilDraw : 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 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 DrawDataOp(int x, int y, int cx, int cy, const String& data, const char *id); + 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 void DrawDrawingOp(const Rect& target, const Drawing& w); + virtual void DrawPaintingOp(const Rect& target, const Painting& w); +}; + +void AddNotEmpty(Vector& result, int left, int right, int top, int bottom); +bool Subtract(const Rect& r, const Rect& sub, Vector& result); +bool Subtract(const Vector& rr, const Rect& sub, Vector& result); +Vector Subtract(const Vector& rr, const Rect& sub, bool& changed); +Vector Intersect(const Vector& b, const Rect& a, bool& changed); + +void Subtract(Vector& rr, const Rect& sub); +void Union(Vector& rr, const Rect& add); + +#ifdef PLATFORM_X11 +void SetClip(GC gc, XftDraw *xftdraw, const Vector& cl); +#endif + +void DrawRect(Draw& w, const Rect& rect, const Image& img, bool ralgn = false); //??? TODO +void DrawRect(Draw& w, int x, int y, int cx, int cy, const Image& img, bool ra = false); + +void DrawTiles(Draw& w, int x, int y, int cx, int cy, const Image& img); +void DrawTiles(Draw& w, const Rect& rect, const Image& img); + +void DrawFatFrame(Draw& w, int x, int y, int cx, int cy, Color color, int n); +void DrawFatFrame(Draw& w, const Rect& r, Color color, int n); + +void DrawFrame(Draw& w, int x, int y, int cx, int cy, + Color leftcolor, Color topcolor, Color rightcolor, Color bottomcolor); +void DrawFrame(Draw& w, const Rect& r, + Color leftcolor, Color topcolor, Color rightcolor, Color bottomcolor); +void DrawFrame(Draw& w, int x, int y, int cx, int cy, + Color topleftcolor, Color bottomrightcolor); +void DrawFrame(Draw& w, const Rect& r, + Color topleftcolor, Color bottomrightcolor); +void DrawFrame(Draw& w, int x, int y, int cx, int cy, Color color); +void DrawFrame(Draw& w, const Rect& r, Color color); + +void DrawBorder(Draw& w, int x, int y, int cx, int cy, const ColorF *colors_ltrd); //TODO +void DrawBorder(Draw& w, const Rect& r, const ColorF *colors_ltrd); + +const ColorF *BlackBorder(); +const ColorF *ButtonPushBorder(); +const ColorF *EdgeButtonBorder(); +const ColorF *DefButtonBorder(); +const ColorF *ButtonBorder(); +const ColorF *InsetBorder(); +const ColorF *OutsetBorder(); +const ColorF *ThinOutsetBorder(); +const ColorF *ThinInsetBorder(); + +void DrawBorder(Draw& w, int x, int y, int cx, int cy, const ColorF *(*colors_ltrd)()); +void DrawBorder(Draw& w, const Rect& r, const ColorF *(*colors_ltrd)()); + +void DrawRectMinusRect(Draw& w, const Rect& rect, const Rect& inner, Color color); + +void DrawHighlightImage(Draw& w, int x, int y, const Image& img, bool highlight = true, + bool enabled = true, Color maskcolor = SColorPaper); + +Color GradientColor(Color fc, Color tc, int i, int n); + +void DrawDragRect(SystemDraw& w, const Rect& rect1, const Rect& rect2, const Rect& clip, int n, Color color, uint64 pattern); + +enum { + BUTTON_NORMAL, BUTTON_OK, BUTTON_HIGHLIGHT, BUTTON_PUSH, BUTTON_DISABLED, BUTTON_CHECKED, + BUTTON_VERTICAL = 0x100, + BUTTON_EDGE = 0x200, + BUTTON_TOOL = 0x400, + BUTTON_SCROLL = 0x800, +}; + +void DrawXPButton(Draw& w, Rect r, int type); + +void DrawTextEllipsis(Draw& w, int x, int y, int cx, const char *text, const char *ellipsis, + Font font = StdFont(), Color ink = SColorText(), int n = -1); +void DrawTextEllipsis(Draw& w, int x, int y, int cx, const wchar *text, const char *ellipsis, + Font font = StdFont(), Color ink = SColorText(), int n = -1); +Size GetTLTextSize(const wchar *text, Font font = StdFont()); +int GetTLTextHeight(const wchar *s, Font font = StdFont()); +void DrawTLText(Draw& draw, int x, int y, int cx, const wchar *text, Font font = StdFont(), + Color ink = SColorText(), int accesskey = 0); + + +typedef String (*DrawingToPdfFnType)(const Array& report, Size pagesize, int margin); + +void SetDrawingToPdfFn(DrawingToPdfFnType Pdf); +DrawingToPdfFnType GetDrawingToPdfFn(); + +#ifdef PLATFORM_WIN32 +#include "DrawWin32.h" +#endif + +#ifdef PLATFORM_X11 +#include "DrawX11.h" +#endif + +#include "BackDraw.h" + +#include "Display.h" +#include "ImageDraw.h" +#include "Debug.h" +#include "Cham.h" + +typedef ImageDraw SystemImageDraw; + +END_UPP_NAMESPACE + +#endif diff --git a/newdraw/Draw/Draw.upp b/newdraw/Draw/Draw.upp index e8b2422bc..c01f7d831 100644 --- a/newdraw/Draw/Draw.upp +++ b/newdraw/Draw/Draw.upp @@ -52,6 +52,7 @@ file DrawX11.h, DrawX11.cpp, DrawOpX11.cpp, + DrawTextX11.cpp, BackDraw.h, BackDraw.cpp, Image readonly separator, diff --git a/newdraw/Draw/DrawOpX11.cpp b/newdraw/Draw/DrawOpX11.cpp index 05a1d3c13..5a70420c8 100644 --- a/newdraw/Draw/DrawOpX11.cpp +++ b/newdraw/Draw/DrawOpX11.cpp @@ -298,93 +298,6 @@ void SystemDraw::DrawArcOp(const Rect& rc, Point start, Point end, int width, Co XChangeGC(Xdisplay, GetGC(), GCForeground, &gcv_old); } -void SystemDraw::DrawTextOp(int x, int y, int angle, const wchar *text, Font font, - Color ink, int n, const int *dx) { - LTIMING("DrawText"); - LLOG("DrawText " << ToUtf8(WString(text, n)) << " color:" << ink << " font:" << font); - //TODO - X11 seems to crash when displaying too long strings (?) - 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; - c.color.blue = ink.GetB() << 8; - c.color.alpha = 0xffff; - c.pixel = GetXPixel(ink.GetR(), ink.GetG(), ink.GetB()); - if(angle) { - int xpos = 0; - for(int i = 0; i < n; i++) { - wchar h = text[i]; - XftDrawString16(xftdraw, &c, fd->xftfont, - int(ox + xpos * fd->cosa + fd->offset.cx), - int(oy - xpos * fd->sina + fd->offset.cy), - (FcChar16 *)&h, 1); - xpos += dx ? dx[i] : lastFont[text[i]]; - } - if(font.IsUnderline() || font.IsStrikeout()) { - x += fd->offset.cx; - y += fd->offset.cy; - if(font.IsUnderline()) - DrawLine( - int(x + fd->underline_position * fd->sina), - int(y + fd->underline_position * fd->cosa), - int(x + xpos * fd->cosa + fd->underline_position * fd->sina), - int(y - xpos * fd->sina + fd->underline_position * fd->cosa), - fd->underline_thickness, - ink - ); - if(font.IsStrikeout()) { - int p = 2 * fd->ascent / 3; - DrawLine( - int(x + p * fd->sina), - int(y + p * fd->cosa), - int(x + xpos * fd->cosa + p * fd->sina), - int(y - xpos * fd->sina + p * fd->cosa), - fd->underline_thickness, - ink - ); - } - } - } - else { - if(dx) { - int xpos = ox; - Buffer ch(n); - for(int i = 0; i < n; i++) { - ch[i].ucs4 = text[i]; - ch[i].x = xpos; - ch[i].y = oy + fd->ascent; - xpos += dx[i]; - } - XftDrawCharSpec(xftdraw, &c, fd->xftfont, ch, n); - } - else - XftDrawString16(xftdraw, &c, fd->xftfont, ox, oy + fd->ascent, - (FcChar16 *)text, n); - LLOG("XftColor: r=" << c.color.red << ", g=" << c.color.green << ", b=" << c.color.blue - << ", alpha=" << c.color.alpha << ", pixel=" << FormatIntHex(c.pixel)); - if(font.IsUnderline() || font.IsStrikeout()) { - int cx; - if(dx && n > 0) { - cx = 0; - Sum(cx, dx, dx + n - 1); - cx += lastFont[text[n - 1]]; - } - 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); - if(font.IsStrikeout()) - DrawRect(x, y + 2 * lastFont.GetAscent() / 3, - cx, lastFont.ptr->underline_thickness, ink); - } - } -} - #endif END_UPP_NAMESPACE diff --git a/newdraw/Draw/DrawTextX11.cpp b/newdraw/Draw/DrawTextX11.cpp new file mode 100644 index 000000000..92740f832 --- /dev/null +++ b/newdraw/Draw/DrawTextX11.cpp @@ -0,0 +1,221 @@ +#include "Draw.h" + +NAMESPACE_UPP + +#ifdef PLATFORM_X11 + +#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()); +} + +XftFont *CreateXftFont(Font font, int angle) +{ + LTIMING("CreateXftFont"); + XftFont *xftfont; + double sina, cosa; + Std(font); + int hg = abs(font.GetHeight()); + if(hg == 0) hg = 10; + int i = font.GetFace(); + if(i < 0 || i >= Font::GetFaceCount()) + i = 0; + String face = font.GetFaceName(); + FcPattern *p = FcPatternCreate(); + FcPatternAddString(p, FC_FAMILY, (FcChar8*)~face); + FcPatternAddInteger(p, FC_SLANT, font.IsItalic() ? 110 : 0); + FcPatternAddInteger(p, FC_PIXEL_SIZE, hg); + FcPatternAddInteger(p, FC_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; +} + +#define FONTCACHE 37 + +struct XftEntry { + Font font; + int angle; + XftFont *xftfont; +}; + +XftFont *GetXftFont(Font fnt, int angle) +{ + static XftEntry cache[FONTCACHE]; + ONCELOCK { + for(int i = 0; i < FONTCACHE; i++) + cache[i].font.Height(-30000); + } + XftEntry be; + be = cache[0]; + for(int i = 0; i < FONTCACHE; i++) { + XftEntry e = cache[i]; + if(i) + cache[i] = be; + if(e.font == fnt && e.angle == angle) { + if(i) + cache[0] = e; + return e.xftfont; + } + be = e; + } + if(be.xftfont) { + XftFontClose(Xdisplay, be.xftfont); + } + be.font = fnt; + be.angle = angle; + be.xftfont = CreateXftFont(fnt, angle); + cache[0] = be; + return be.xftfont; +} + +void SystemDraw::DrawTextOp(int x, int y, int angle, const wchar *text, Font font, + Color ink, int n, const int *dx) { + DrawLock __; + LTIMING("DrawText"); + LLOG("DrawText " << ToUtf8(WString(text, n)) << " color:" << ink << " font:" << font); + //TODO - X11 seems to crash when displaying too long strings (?) + 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; + c.color.blue = ink.GetB() << 8; + c.color.alpha = 0xffff; + c.pixel = GetXPixel(ink.GetR(), ink.GetG(), ink.GetB()); + XftFont *xftfont = GetXftFont(font, angle); + Size offset = Point(0, 0); + double sina, cosa; + int ascent = font.Info().GetAscent(); + if(angle) { + SinCos(angle, sina, cosa); + offset.cx = fround(ascent * sina); + offset.cy = fround(ascent * cosa); + } + int hg = abs(font.GetHeight()); + if(hg == 0) hg = 10; + int underline_thickness = max(hg / 20, 1); + int underline_position = max(hg / 15, int(font.Info().GetDescent() > 0)); + if(angle) { + int xpos = 0; + for(int i = 0; i < n; i++) { + wchar h = text[i]; + XftDrawString16(xftdraw, &c, xftfont, + int(ox + xpos * cosa + offset.cx), + int(oy - xpos * sina + offset.cy), + (FcChar16 *)&h, 1); + xpos += dx ? dx[i] : lastFont[text[i]]; + } + if(font.IsUnderline() || font.IsStrikeout()) { + x += offset.cx; + y += offset.cy; + if(font.IsUnderline()) + DrawLine( + int(x + underline_position * sina), + int(y + underline_position * cosa), + int(x + xpos * cosa + underline_position * sina), + int(y - xpos * sina + underline_position * cosa), + underline_thickness, + ink + ); + if(font.IsStrikeout()) { + int p = 2 * ascent / 3; + DrawLine( + int(x + p * sina), + int(y + p * cosa), + int(x + xpos * cosa + p * sina), + int(y - xpos * sina + p * cosa), + underline_thickness, + ink + ); + } + } + } + else { + if(dx) { + int xpos = ox; + Buffer ch(n); + for(int i = 0; i < n; i++) { + ch[i].ucs4 = text[i]; + ch[i].x = xpos; + ch[i].y = oy + ascent; + xpos += dx[i]; + } + XftDrawCharSpec(xftdraw, &c, xftfont, ch, n); + } + else + XftDrawString16(xftdraw, &c, xftfont, ox, oy + ascent, + (FcChar16 *)text, n); + LLOG("XftColor: r=" << c.color.red << ", g=" << c.color.green << ", b=" << c.color.blue + << ", alpha=" << c.color.alpha << ", pixel=" << FormatIntHex(c.pixel)); + if(font.IsUnderline() || font.IsStrikeout()) { + int cx; + if(dx && n > 0) { + cx = 0; + Sum(cx, dx, dx + n - 1); + cx += lastFont[text[n - 1]]; + } + 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); + if(font.IsStrikeout()) + DrawRect(x, y + 2 * lastFont.GetAscent() / 3, + cx, lastFont.ptr->underline_thickness, ink); + } + } +} + +#endif + +END_UPP_NAMESPACE diff --git a/newdraw/Draw/Font.cpp b/newdraw/Draw/Font.cpp index 723b8664f..b4f393d87 100644 --- a/newdraw/Draw/Font.cpp +++ b/newdraw/Draw/Font.cpp @@ -1,306 +1,306 @@ -#include "Draw.h" - -#define LLOG(x) - -NAMESPACE_UPP - -void InitPlatformFonts(); - -Size FontInfo::StdFontSize; -Font FontInfo::AStdFont; - -int FontInfo::FontCacheMax = 32; -int FontInfo::FontCached; - -void FreeFonts(); - -enum FontHashConst { FONTHASH = 97 }; - -//# Pretty ugly code.... -FontInfo::Data *FontInfo::GetFontHash(int i) { - static byte buff[FONTHASH * sizeof(FontLink)]; - static FontLink *fonthash; - ONCELOCK { - fonthash = (FontLink *)buff; - for(int i = 0; i < FONTHASH; i++) - fonthash[i].LinkSelfAll(); - } - ASSERT(i >= 0 && i < FONTHASH); - return (FontInfo::Data *)&fonthash[i]; -} - -//# Pretty ugly code.... -FontInfo::Data *FontInfo::GetFontLru() { - static byte buff[sizeof(FontLink)]; - static FontLink *fontlru; - ONCELOCK { - fontlru = new(buff) FontLink; - } - return (FontInfo::Data *)fontlru; -} - -INITBLOCK { - RichValue::Register(); -} - -void FontInfo::InitFonts() -{ - ONCELOCK { - static bool b; - if(b) return; - b = true; - DrawLock __; - GetFontHash(0); - GetFontLru(); - InitPlatformFonts(); - } -} - -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 char *name) { - FontInfo::InitFonts(); - 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; -} - -FontInfo::FontInfo() -{ - ptr = NULL; - charset = CHARSET_UNICODE; - InitFonts(); -} - -SystemDraw& ScreenInfo(); - -FontInfo Font::Info() const -{ - DrawLock __; - return FontInfo::AcquireFontInfo(*this, 0); -} - -void FontInfo::SyncStdFont() -{ - FontInfo fi = AStdFont.Info(); - FontInfo bfi = AStdFont().Bold().Info(); - StdFontSize = Size(fi.GetAveWidth(), bfi.GetHeight()); -} - -void FontInfo::SetStdFont(Font font) -{ - DrawLock __; - InitFonts(); - AStdFont = font; - SyncStdFont(); -} - -Size FontInfo::GetStdFontSize() -{ - ONCELOCK { - SyncStdFont(); - } - return StdFontSize; -} - -Font StdFont() -{ - return Font(0, FontInfo::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 % flags % height % width; -} - -template<> -String AsString(const Font& f) { - if(IsNull(f)) return ""; - 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 + '>'; -} - -void FontInfo::FreeFonts() { - FontCacheMax = FontCached = 0; - for(int i = 0; i < FONTHASH; i++) - GetFontHash(i)->DeleteList(HASH); -} - -FontInfo::FontInfo(const FontInfo& f) -{ - Retain(f); -} - -FontInfo& FontInfo::operator=(const FontInfo& f) -{ - Release(); - Retain(f); - return *this; -} - -bool FontInfo::IsEqual(byte _charset, Font f, int angle) const -{ - return ptr && ptr->font == f && ptr->angle == angle && charset == _charset; -} - -FontInfo::CharMetrics FontInfo::GetCM(int c) const -{ - if(c < 0) c = (byte)c; - if(charset != CHARSET_UNICODE) - c = ToUnicode(c, charset); - ASSERT(c < 65536); - if(c >= 65536) { - CharMetrics h; - h.width = h.lspc = h.rspc = 0; - return h; - } - if(c < 2048) - return GetPage(c >> 5)[c & 31]; - Mutex::Lock __(ptr->xmutex); - Kinfo& ki = ptr->kinfo.At((c >> 10) - 2); - if(!ki.flags) { - ki.flags = new byte[128]; - memset(ki.flags, 0, 128); - ptr->GetMetrics(&ki.std, c, 1); - } - int fi = (c >> 3) & 127; - int fm = 1 << (c & 7); - if(ki.flags[fi] & fm) - return ki.std; - int q = ptr->xx.Find(c); - if(q >= 0) - return ptr->xx[q]; - CharMetrics m; - ptr->GetMetrics(&m, c, 1); - if(m == ki.std) - ki.flags[fi] |= fm; - else - ptr->xx.Add(c, m); - return m; -} - -int FontInfo::GetWidth(int c) const { - return GetCM(c).width; -} - -int FontInfo::GetLeftSpace(int c) const { - return GetCM(c).lspc; -} - -int FontInfo::GetRightSpace(int c) const { - return GetCM(c).rspc; -} - -void FontInfo::Release() -{ - DrawLock __; - if(ptr) { - ASSERT(ptr->refcount > 0); - LLOG("Release " << (void *)ptr << " count:" << ptr->count); - if(--ptr->refcount == 0) { - if(FontCacheMax == 0) { - delete ptr; - return; - } - FontInfo::Data *lru = GetFontLru(); - ptr->LinkAfter(lru, LRU); - FontCached++; - LLOG("Placed to cache " << ptr->ptr << " cached:" << FontCached); - while(FontCached > FontCacheMax) { - ASSERT(lru->GetPrev(LRU) != lru); - FontCached--; - LLOG("Deleting from cache " << lru->GetPrev(LRU)->ptr << - " cached: " << FontCached); - delete lru->GetPrev(LRU); - } - } - } -} - -void FontInfo::Retain(const FontInfo& f) -{ - DrawLock __; - ptr = f.ptr; - ptr->refcount++; - charset = f.charset; -} - -FontInfo::CharMetrics *FontInfo::CreateMetricsPage(int page) const -{ - DrawLock __; - CharMetrics *cm; - cm = new CharMetrics[32]; - ptr->GetMetrics(cm, page << 5, 32); - if(page >= 8 && page < 12) - ComposeMetrics(ptr->font, cm, page); - return cm; -} - -FontInfo::CharMetrics *FontInfo::GetPage(int page) const -{ - ASSERT(page >= 0 && page < 64); - ONCELOCK_PTR(ptr->base[page], CreateMetricsPage(page)); - return ptr->base[page]; -} - -END_UPP_NAMESPACE +#include "Draw.h" + +#define LLOG(x) + +NAMESPACE_UPP + +void InitPlatformFonts(); + +Size FontInfo::StdFontSize; +Font FontInfo::AStdFont; + +int FontInfo::FontCacheMax = 32; +int FontInfo::FontCached; + +void FreeFonts(); + +enum FontHashConst { FONTHASH = 97 }; + +//# Pretty ugly code.... +FontInfo::Data *FontInfo::GetFontHash(int i) { + static byte buff[FONTHASH * sizeof(FontLink)]; + static FontLink *fonthash; + ONCELOCK { + fonthash = (FontLink *)buff; + for(int i = 0; i < FONTHASH; i++) + fonthash[i].LinkSelfAll(); + } + ASSERT(i >= 0 && i < FONTHASH); + return (FontInfo::Data *)&fonthash[i]; +} + +//# Pretty ugly code.... +FontInfo::Data *FontInfo::GetFontLru() { + static byte buff[sizeof(FontLink)]; + static FontLink *fontlru; + ONCELOCK { + fontlru = new(buff) FontLink; + } + return (FontInfo::Data *)fontlru; +} + +INITBLOCK { + RichValue::Register(); +} + +void FontInfo::InitFonts() +{ + ONCELOCK { + static bool b; + if(b) return; + b = true; + DrawLock __; + GetFontHash(0); + GetFontLru(); + InitPlatformFonts(); + } +} + +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 char *name) { + FontInfo::InitFonts(); + 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; +} + +FontInfo::FontInfo() +{ + ptr = NULL; + charset = CHARSET_UNICODE; + InitFonts(); +} + +SystemDraw& ScreenInfo(); + +FontInfo Font::Info() const +{ + DrawLock __; + return FontInfo::AcquireFontInfo(*this, 0); +} + +void FontInfo::SyncStdFont() +{ + FontInfo fi = AStdFont.Info(); + FontInfo bfi = AStdFont().Bold().Info(); + StdFontSize = Size(fi.GetAveWidth(), bfi.GetHeight()); +} + +void FontInfo::SetStdFont(Font font) +{ + DrawLock __; + InitFonts(); + AStdFont = font; + SyncStdFont(); +} + +Size FontInfo::GetStdFontSize() +{ + ONCELOCK { + SyncStdFont(); + } + return StdFontSize; +} + +Font StdFont() +{ + return Font(0, FontInfo::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 ""; + 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 + '>'; +} + +void FontInfo::FreeFonts() { + FontCacheMax = FontCached = 0; + for(int i = 0; i < FONTHASH; i++) + GetFontHash(i)->DeleteList(HASH); +} + +FontInfo::FontInfo(const FontInfo& f) +{ + Retain(f); +} + +FontInfo& FontInfo::operator=(const FontInfo& f) +{ + Release(); + Retain(f); + return *this; +} + +bool FontInfo::IsEqual(byte _charset, Font f, int angle) const +{ + return ptr && ptr->font == f && ptr->angle == angle && charset == _charset; +} + +FontInfo::CharMetrics FontInfo::GetCM(int c) const +{ + if(c < 0) c = (byte)c; + if(charset != CHARSET_UNICODE) + c = ToUnicode(c, charset); + ASSERT(c < 65536); + if(c >= 65536) { + CharMetrics h; + h.width = h.lspc = h.rspc = 0; + return h; + } + if(c < 2048) + return GetPage(c >> 5)[c & 31]; + Mutex::Lock __(ptr->xmutex); + Kinfo& ki = ptr->kinfo.At((c >> 10) - 2); + if(!ki.flags) { + ki.flags = new byte[128]; + memset(ki.flags, 0, 128); + ptr->GetMetrics(&ki.std, c, 1); + } + int fi = (c >> 3) & 127; + int fm = 1 << (c & 7); + if(ki.flags[fi] & fm) + return ki.std; + int q = ptr->xx.Find(c); + if(q >= 0) + return ptr->xx[q]; + CharMetrics m; + ptr->GetMetrics(&m, c, 1); + if(m == ki.std) + ki.flags[fi] |= fm; + else + ptr->xx.Add(c, m); + return m; +} + +int FontInfo::GetWidth(int c) const { + return GetCM(c).width; +} + +int FontInfo::GetLeftSpace(int c) const { + return GetCM(c).lspc; +} + +int FontInfo::GetRightSpace(int c) const { + return GetCM(c).rspc; +} + +void FontInfo::Release() +{ + DrawLock __; + if(ptr) { + ASSERT(ptr->refcount > 0); + LLOG("Release " << (void *)ptr << " count:" << ptr->count); + if(--ptr->refcount == 0) { + if(FontCacheMax == 0) { + delete ptr; + return; + } + FontInfo::Data *lru = GetFontLru(); + ptr->LinkAfter(lru, LRU); + FontCached++; + LLOG("Placed to cache " << ptr->ptr << " cached:" << FontCached); + while(FontCached > FontCacheMax) { + ASSERT(lru->GetPrev(LRU) != lru); + FontCached--; + LLOG("Deleting from cache " << lru->GetPrev(LRU)->ptr << + " cached: " << FontCached); + delete lru->GetPrev(LRU); + } + } + } +} + +void FontInfo::Retain(const FontInfo& f) +{ + DrawLock __; + ptr = f.ptr; + ptr->refcount++; + charset = f.charset; +} + +FontInfo::CharMetrics *FontInfo::CreateMetricsPage(int page) const +{ + DrawLock __; + CharMetrics *cm; + cm = new CharMetrics[32]; + ptr->GetMetrics(cm, page << 5, 32); + if(page >= 8 && page < 12) + ComposeMetrics(ptr->font, cm, page); + return cm; +} + +FontInfo::CharMetrics *FontInfo::GetPage(int page) const +{ + ASSERT(page >= 0 && page < 64); + ONCELOCK_PTR(ptr->base[page], CreateMetricsPage(page)); + return ptr->base[page]; +} + +END_UPP_NAMESPACE