From 144066e5804aba71dfffa8630c47cff4e2e54546 Mon Sep 17 00:00:00 2001 From: cxl Date: Sun, 5 Jul 2009 19:55:01 +0000 Subject: [PATCH] Developing new draw git-svn-id: svn://ultimatepp.org/upp/trunk@1361 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- newdraw/Draw/Debug.cpp | 5 +- newdraw/Draw/Draw.h | 1934 +++++++++--------- newdraw/Draw/Draw.upp | 4 +- newdraw/Draw/DrawOpWin32.cpp | 31 - newdraw/Draw/DrawText.cpp | 61 +- newdraw/Draw/DrawTextWin32.cpp | 57 + newdraw/Draw/DrawWin32.cpp | 24 +- newdraw/Draw/DrawWin32.h | 3 +- newdraw/Draw/Font.cpp | 630 +++--- newdraw/Draw/{ComposeText.cpp => FontCR.cpp} | 193 +- newdraw/Draw/FontInt.h | 54 + newdraw/Draw/FontWin32.cpp | 745 +++---- 12 files changed, 1846 insertions(+), 1895 deletions(-) create mode 100644 newdraw/Draw/DrawTextWin32.cpp rename newdraw/Draw/{ComposeText.cpp => FontCR.cpp} (60%) create mode 100644 newdraw/Draw/FontInt.h diff --git a/newdraw/Draw/Debug.cpp b/newdraw/Draw/Debug.cpp index c58deec8b..ac2e9808e 100644 --- a/newdraw/Draw/Debug.cpp +++ b/newdraw/Draw/Debug.cpp @@ -67,7 +67,6 @@ String DumpFontInfo(FontInfo fi) { String out; out << "FontInfo(font = " << fi.GetFont() << "\n" - "\tempty = " << fi.IsEmpty() << "\n" "\tascent = " << fi.GetAscent() << "\n" "\tdescent = " << fi.GetDescent() << "\n" "\texternal leading = " << fi.GetExternal() << "\n" @@ -91,13 +90,13 @@ String DumpFontInfo(FontInfo fi) out << "\n\n\tright space:\n"; for(i = 0; i < 256; i++) out << NFormat(i & 15 ? " " : "\n\t%02x\t", i) << NFormat("%2>d", fi.GetRightSpace(i)); - out << "\n\n\tkerning:\n"; +/* out << "\n\n\tkerning:\n"; int kp = 0; for(i = 0; i < 256; i++) for(int j = 0; j < 256; j++) if(int k = fi.GetKerning(i, j)) out << (kp++ & 7 ? " " : "\n\t") << NFormat("(%02x,%02x)=%2>d", i, j, k); - out << (kp ? "\n" : "\tnone\n"); + out << (kp ? "\n" : "\tnone\n");*/ return out; } diff --git a/newdraw/Draw/Draw.h b/newdraw/Draw/Draw.h index 81d6d3725..5f397e9fb 100644 --- a/newdraw/Draw/Draw.h +++ b/newdraw/Draw/Draw.h @@ -1,1017 +1,917 @@ -#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 +#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; + +#include "FontInt.h" + +class FontInfo; + +class Font : AssignValueTypeNo >{ + union { + int64 data; + struct { + word face; + word flags; + int16 height; + int16 width; + } v; + }; + + static Font AStdFont; + static Size StdFontSize; + + static const Vector& List(); + static void SyncStdFont(); + static void InitStdFont(); + + const CommonFontInfo& Fi() const; + + friend void sInitFonts(); + +public: + enum { + FIXEDPITCH = 0x0001, + SCALEABLE = 0x0002, + LOCAL = 0x0010, + }; + + static int GetFaceCount(); + static String GetFaceName(int index); + static int FindFaceNameIndex(const String& name); + static dword GetFaceInfo(int index); + + static void SetStdFont(Font font); + static Font GetStdFont(); + static Size GetStdFontSize(); + + enum { + STDFONT, + SCREEN_SERIF, + SCREEN_SANS, + SCREEN_FIXED, + ROMAN, + ARIAL, + COURIER, + #ifdef PLATFORM_WIN32 + SYMBOL, + 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; + int64 AsInt64() const { return data; } + + 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); } + + + int GetAscent() const { return Fi().ascent; } + int GetDescent() const { return Fi().descent; } + int GetExternal() const { return Fi().external; } + int GetInternal() const { return Fi().internal; } + int GetGlyphsHeight() const { return Fi().height; } + int GetLineHeight() const { return Fi().lineheight; } + int GetOverhang() const { return Fi().overhang; } + int GetAveWidth() const { return Fi().avewidth; } + int GetMaxWidth() const { return Fi().maxwidth; } + int HasChar(int ch) const; + int GetWidth(int c) const; + int operator[](int c) const { return GetWidth(c); } + int GetLeftSpace(int c) const; + int GetRightSpace(int c) const; + bool IsFixedPitch() const { return Fi().fixedpitch; } + bool IsScaleable() const { return Fi().scaleable; } +#ifdef PLATFORM_X11 + String GetFontPath() const { return Fi().path; } +#endif + + 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); } + +// BW compatibility + FontInfo Info() const; +}; + +//BW compatibility +class FontInfo { + Font font; + friend class Font; +public: + int GetAscent() const { return font.GetAscent(); } + int GetDescent() const { return font.GetDescent(); } + int GetExternal() const { return font.GetExternal(); } + int GetInternal() const { return font.GetInternal(); } + int GetHeight() const { return font.GetGlyphsHeight(); } + int GetLineHeight() const { return font.GetLineHeight(); } + int GetOverhang() const { return font.GetOverhang(); } + int GetAveWidth() const { return font.GetAveWidth(); } + int GetMaxWidth() const { return font.GetMaxWidth(); } + int HasChar(int c) const { return font.HasChar(c); } + int GetWidth(int c) const { return font.GetWidth(c); } + int operator[](int c) const { return GetWidth(c); } + int GetLeftSpace(int c) const { return font.GetLeftSpace(c); } + int GetRightSpace(int c) const { return font.GetRightSpace(c); } + bool IsFixedPitch() const { return font.IsFixedPitch(); } + bool IsScaleable() const { return font.IsScaleable(); } + int GetFontHeight() const { return font.GetHeight(); } + Font GetFont() const { return font; } +#ifdef PLATFORM_X11 + String GetFileName() const { return font.GetPath(); } +#endif +}; + +struct ComposedGlyph { + wchar basic_char; + Point mark_pos; + wchar mark_char; + Font mark_font; +}; + +bool Compose(Font fnt, int chr, ComposedGlyph& cs); + +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); + +inline void SetStdFont(Font font) { Font::SetStdFont(font); } +inline Font GetStdFont() { return Font::GetStdFont(); } +inline Size GetStdFontSize() { return Font::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; + +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 c01f7d831..6798b71a5 100644 --- a/newdraw/Draw/Draw.upp +++ b/newdraw/Draw/Draw.upp @@ -29,12 +29,13 @@ library(FREEBSD) xcb; file Draw.h, Mt.cpp, + FontInt.h, Font.cpp, + FontCR.cpp, FontWin32.cpp, FontX11.cpp, Draw.cpp, DrawText.cpp, - ComposeText.cpp, DrawData.cpp, Drawing.cpp, DrawUtil.cpp, @@ -48,6 +49,7 @@ file DrawWin32.h, DrawWin32.cpp, DrawOpWin32.cpp, + DrawTextWin32.cpp, MetaFile.cpp, DrawX11.h, DrawX11.cpp, diff --git a/newdraw/Draw/DrawOpWin32.cpp b/newdraw/Draw/DrawOpWin32.cpp index 3e723713d..8232eb4ca 100644 --- a/newdraw/Draw/DrawOpWin32.cpp +++ b/newdraw/Draw/DrawOpWin32.cpp @@ -277,37 +277,6 @@ void SystemDraw::DrawEllipseOp(const Rect& r, Color color, int width, Color penc ::Ellipse(GetHandle(), r.left, r.top, r.right, r.bottom); } -void SystemDraw::DrawTextOp(int x, int y, int angle, const wchar *text, Font font, Color ink, - int n, const int *dx) { - while(n > 30000) { - DrawTextOp(x, y, angle, text, font, ink, 30000, dx); - if(dx) { - for(int i = 0; i < 30000; i++) - x += *dx++; - } - else - x += GetTextSize(text, font, 30000).cx; - n -= 30000; - text += 30000; - } - DrawLock __; - COLORREF cr = GetColor(ink); - if(cr != lastTextColor) { - LLOG("Setting text color: " << ink); - ::SetTextColor(handle, lastTextColor = cr); - } - if(angle) { - SetFont(font, angle); - ::ExtTextOutW(handle, x + lastFont.ptr->offset.cx, y + lastFont.ptr->offset.cy, - 0, NULL, (const WCHAR *)text, n, dx); - } - else { - SetFont(font); - ::ExtTextOutW(handle, x, y + lastFont.GetAscent(), 0, NULL, (const WCHAR *)text, - n, dx); - } -} - #endif END_UPP_NAMESPACE diff --git a/newdraw/Draw/DrawText.cpp b/newdraw/Draw/DrawText.cpp index 4ee5e17e4..f55fd9217 100644 --- a/newdraw/Draw/DrawText.cpp +++ b/newdraw/Draw/DrawText.cpp @@ -29,7 +29,66 @@ void Draw::DrawText(int x, int y, int angle, const wchar *text, Font font, if(IsNull(ink)) return; if(n < 0) n = wstrlen(text); - ComposeText(x, y, angle, text, font, ink, n, dx); + 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()) { + FontInfo fi = font.Info(); + Font fnt = font; + fnt.Face(gi.lspc); + FontInfo fi2 = fnt.Info(); + if(angle) + DrawTextOp(int(x + cosa * d), int(y - sina * (fi.GetAscent() - fi2.GetAscent() + d)), + angle, &chr, fnt, ink, 1, NULL); + else + DrawTextOp(x + d, y + fi.GetAscent() - fi2.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; + } } // ---------------------------- diff --git a/newdraw/Draw/DrawTextWin32.cpp b/newdraw/Draw/DrawTextWin32.cpp new file mode 100644 index 000000000..80cdf12f8 --- /dev/null +++ b/newdraw/Draw/DrawTextWin32.cpp @@ -0,0 +1,57 @@ +#include "Draw.h" + +NAMESPACE_UPP + +#ifdef PLATFORM_WIN32 + +#define LLOG(x) + +HFONT GetWin32Font(Font fnt, int angle); + +void SystemDraw::SetFont(Font font, int angle) { + DrawLock __; + LLOG("Set font: " << font << " face: " << font.GetFaceName()); + if(lastFont == font && lastAngle == angle) + return; + lastFont = font; + lastAngle = angle; + HFONT h = (HFONT) SelectObject(handle, GetWin32Font(font, angle)); + if(!orgFont) orgFont = h; +} + +void SystemDraw::DrawTextOp(int x, int y, int angle, const wchar *text, Font font, Color ink, + int n, const int *dx) { + Std(font); + while(n > 30000) { + DrawTextOp(x, y, angle, text, font, ink, 30000, dx); + if(dx) { + for(int i = 0; i < 30000; i++) + x += *dx++; + } + else + x += GetTextSize(text, font, 30000).cx; + n -= 30000; + text += 30000; + } + DrawLock __; + COLORREF cr = GetColor(ink); + if(cr != lastTextColor) { + LLOG("Setting text color: " << ink); + ::SetTextColor(handle, lastTextColor = cr); + } + SetFont(font, angle); + int ascent = font.Info().GetAscent(); + if(angle) { + double sina, cosa; + Draw::SinCos(angle, sina, cosa); + Size offset; + ::ExtTextOutW(handle, x + fround(ascent * sina), y + fround(ascent * cosa), 0, NULL, (const WCHAR *)text, n, dx); + } + else + ::ExtTextOutW(handle, x, y + ascent, 0, NULL, (const WCHAR *)text, + n, dx); +} + +#endif + +END_UPP_NAMESPACE diff --git a/newdraw/Draw/DrawWin32.cpp b/newdraw/Draw/DrawWin32.cpp index ca420bcbe..06ecb1c4f 100644 --- a/newdraw/Draw/DrawWin32.cpp +++ b/newdraw/Draw/DrawWin32.cpp @@ -24,16 +24,6 @@ Size SystemDraw::GetNativeDpi() const return Dots() ? nativeDpi : Size(96, 96); } -void StaticExitDraw_() -{ - FontInfo::FreeFonts(); -} - -EXITBLOCK -{ - StaticExitDraw_(); -} - #ifndef PLATFORM_WINCE void Add(LOGPALETTE *pal, int r, int g, int b) { @@ -164,16 +154,6 @@ void SystemDraw::SetDrawPen(int width, Color color) { } } -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::AcquireFontInfo0(font, GetHandle(), angle); - HFONT h = (HFONT) SelectObject(handle, lastFont.ptr->hfont); - if(!orgFont) orgFont = h; -} - void SystemDraw::SetOrg() { DrawLock __; #ifdef PLATFORM_WINCE @@ -271,7 +251,7 @@ void SystemDraw::Cinit() { actBrush = orgBrush = NULL; actPen = orgPen = NULL; orgFont = NULL; - lastFont.Clear(); + lastAngle = INT_MIN; } void SystemDraw::Init() { @@ -296,7 +276,6 @@ SystemDraw::SystemDraw() { DrawLock __; native = 0; InitColors(); - FontInfo::InitFonts(); actual_offset = Point(0, 0); Reset(); handle = NULL; @@ -306,7 +285,6 @@ SystemDraw::SystemDraw(HDC hdc) { DrawLock __; native = 0; InitColors(); - FontInfo::InitFonts(); Reset(); Attach(hdc); } diff --git a/newdraw/Draw/DrawWin32.h b/newdraw/Draw/DrawWin32.h index d4310c791..acdec65af 100644 --- a/newdraw/Draw/DrawWin32.h +++ b/newdraw/Draw/DrawWin32.h @@ -53,7 +53,8 @@ private: friend void StaticExitDraw_(); - FontInfo lastFont; + Font lastFont; + int lastAngle; Point actual_offset_bak; diff --git a/newdraw/Draw/Font.cpp b/newdraw/Draw/Font.cpp index b4f393d87..9bf361961 100644 --- a/newdraw/Draw/Font.cpp +++ b/newdraw/Draw/Font.cpp @@ -1,306 +1,324 @@ -#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 +#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 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::Register(); +} + +const Vector& Font::List() +{ + static Vector *q; + ONCELOCK { + static Vector 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& l = List(); + if(index >= 0 && index < l.GetCount()) + return l[index].name; + return Null; +} + +dword Font::GetFaceInfo(int index) +{ + const Vector& 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().GetGlyphsHeight()); +} + +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 ""; + 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(); + 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), 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 diff --git a/newdraw/Draw/ComposeText.cpp b/newdraw/Draw/FontCR.cpp similarity index 60% rename from newdraw/Draw/ComposeText.cpp rename to newdraw/Draw/FontCR.cpp index 9576ee61b..c33ee85ba 100644 --- a/newdraw/Draw/ComposeText.cpp +++ b/newdraw/Draw/FontCR.cpp @@ -165,111 +165,104 @@ gc_info[128] = { { CG_NONE, 0, 0 } // CG_SMALL, 'LONG S }; -SystemDraw& ScreenInfo(); - -void FontInfo::ComposeMetrics(Font fnt, CharMetrics *m, int page) const +bool Compose(Font font, int chr, ComposedGlyph& cg) { - if(fnt.GetFaceInfo() & Font::COMPOSED) { - FontInfo fi = fnt.Info(); - for(int i = 0; i < 32; i++) { - int c = gc_info[i + (page - 8) * 32].ascii; - m[i].lspc = fi.GetLeftSpace(c); - m[i].width = fi[c]; - m[i].rspc = fi.GetRightSpace(c); - if(gc_info[i].type == CG_COMMA_UR && !fi.IsFixedPitch()) - m[i].rspc += m[i].width / 2; - } + if(chr < 256 || chr > 256 + 128) + return false; + CGInfo f = gc_info[chr - 256]; + if(f.type == CG_NONE) + return false; + GlyphInfo gi = GetGlyphInfo(font, f.ascii); + if(!gi.IsNormal()) + return false; + int cw = gi.width; + CommonFontInfo fi = GetFontInfo(font); + gi = GetGlyphInfo(font, f.mark); + if(!gi.IsNormal()) + return false; + int mw = gi.width; + cg.mark_font = font; + cg.mark_pos.x = cg.mark_pos.y = 0; + cg.basic_char = f.ascii; + cg.mark_char = f.mark; + if(cg.mark_char == CG_COMMA_UR && fi.fixedpitch) + cg.mark_char = CG_CARON; + if(cg.mark_char == CG_COMMA_T) { + cg.mark_pos.y -= 3 * font.GetHeight() / 4; + cg.mark_pos.x += 4 * cw / 10; + if(font.IsItalic()) + cg.mark_pos.x += mw / 2; } + else + if(cg.mark_char == CG_COMMA_UR) { + cg.mark_pos.y -= 2 * font.GetHeight() / 3; + cg.mark_pos.x += cw - mw / 4; + cg.mark_char = ','; + if(font.IsItalic()) + cg.mark_pos.x += mw / 3; + } + else + if(cg.mark_char == CG_COMMA_URI) { + cg.mark_pos.y -= 2 * font.GetHeight() / 3; + cg.mark_pos.x += cw - mw / 2; + cg.mark_char = ','; + if(font.IsItalic()) + cg.mark_pos.x += mw / 3; + } + else + if(cg.mark_char != CG_STROKE) { + if(cg.mark_char != CG_OGONEK && cg.mark_char != CG_CEDILLA && f.type == CG_CAPITAL) { + cg.mark_font = font(9 * font.GetHeight() / 10); + mw = GetGlyphInfo(cg.mark_font, f.mark).width; + cg.mark_pos.y -= cg.mark_char == CG_RING_ABOVE ? font.GetHeight() / 19 + : font.GetHeight() / 10; + } + cg.mark_pos.x += (cw - mw) / 2; + if(font.IsItalic()) + cg.mark_pos.x += mw / 5; + } + return true; } -void Draw::ComposeText(int x, int y, int angle, const wchar *text, Font font, Color ink, - int n, const int *dx) { - if(font.GetFaceInfo() & Font::COMPOSED) { - for(int i = 0; i < n; i++) - if(text[i] >= 256 && text[i] < 256 + 128) { - FontInfo fi = font.Info(); - Clip(x, y, 9999, fi.GetHeight()); - Buffer ntext(n); - double sina; - double cosa; - Size offset; - if(angle) - SinCos(angle, sina, cosa); //TODO global sin tables! - int xp = 0; - for(int i = 0; i < n; i++) { - wchar chr = text[i]; - ntext[i] = chr; - if(chr >= 256 && chr < 256 + 128) { - CGInfo f = gc_info[chr - 256]; - if(f.type != CG_NONE) { - ntext[i] = chr = f.ascii; - Font mfnt = font; - FontInfo mfi = fi; - int my = 0; - int mx = 0; - int cw = fi[f.ascii]; - int mw = mfi[f.mark]; - wchar mark = f.mark; - if(mark == CG_COMMA_UR && fi.IsFixedPitch()) - mark = CG_CARON; - if(mark == CG_COMMA_T) { - my -= 3 * font.GetHeight() / 4; - mx += 4 * cw / 10; - if(font.IsItalic()) - mx += mw / 2; - } - else - if(mark == CG_COMMA_UR) { - my -= 2 * font.GetHeight() / 3; - mx += cw - mw / 4; - mark = ','; - if(font.IsItalic()) - mx += mw / 3; - } - else - if(mark == CG_COMMA_URI) { - my -= 2 * font.GetHeight() / 3; - mx += cw - mw / 2; - mark = ','; - if(font.IsItalic()) - mx += mw / 3; - } - else - if(mark != CG_STROKE) { - if(f.mark != CG_OGONEK && f.mark != CG_CEDILLA && f.type == CG_CAPITAL) { - mfnt = font(9 * font.GetHeight() / 10); - mfi = mfnt.Info(); - my -= mark == CG_RING_ABOVE ? font.GetHeight() / 19 - : font.GetHeight() / 13; - } - mw = mfi[f.mark]; - mx += (cw - mw) / 2; - if(font.IsItalic()) - mx += mw / 5; - } - if(angle) - DrawText(int(x + cosa * (xp + mx) + sina * my), - int(y - sina * (xp + mx) + cosa * my), - angle, &mark, mfnt, ink, 1); - else - DrawText(x + xp + mx, y + my, &mark, mfnt, ink, 1); - } - } - if(angle) - DrawTextOp(int(x + cosa * xp), int(y - sina * xp), - angle, &chr, font, ink, 1, dx); - if(dx) - xp += dx[i]; - else - xp += fi[chr]; - } - if(!angle) - DrawTextOp(x, y, angle, ntext, font, ink, n, dx); - End(); - return; - } +static const char *sFontReplacements[] = { + "sans-serif", + "Arial", + "Arial Unicode MS", + "Symbol", + "???????", + "?????", + "MS UI Gothic", + "MS Mincho", + "Arial", + "AlArabiya" + "FreeSerif", + "Kochi Mincho", + "Kochi Gothic", + "Sazanami Mincho", + "Sazanami Gothic", + "Gulim", + "SimSun", + "PMingLiU", +}; + +bool Replace(Font fnt, int chr, Font& rfnt) +{ + static Vector rface; + ONCELOCK { + for(int i = 0; i < __countof(sFontReplacements) && rface.GetCount() < 20; i++) { + int q = Font::FindFaceNameIndex(sFontReplacements[i]); + if(q > 0) + rface.Add(q); + } } - DrawTextOp(x, y, angle, text, font, ink, n, dx); + + Font f = fnt; + for(int i = 0; i < rface.GetCount(); i++) + if(IsNormal(f.Face(rface[i]), chr)) { + rfnt = f; + return true; + } + return false; } END_UPP_NAMESPACE diff --git a/newdraw/Draw/FontInt.h b/newdraw/Draw/FontInt.h new file mode 100644 index 000000000..9b0f6b3f5 --- /dev/null +++ b/newdraw/Draw/FontInt.h @@ -0,0 +1,54 @@ +#ifndef _Draw_FontInt_h_ +#define _Draw_FontInt_h_ + +// Internal header! + +struct FaceInfo : Moveable { + String name; + dword info; +}; + +struct CommonFontInfo : Moveable { + int ascent; + int descent; + int external; + int internal; + int height; + int lineheight; + int overhang; + int avewidth; + int maxwidth; + int firstchar; + int charcount; + int default_char; + int spacebefore; + int spaceafter; + bool fixedpitch; + bool scaleable; + +#ifdef PLATFORM_POSIX + String path; +#endif +}; + +class Font; + +struct GlyphInfo : Moveable { + int16 width; + int16 lspc; + int16 rspc; + + bool IsNormal() const { return (word)width != 0x8000; } + bool IsComposed() const { return !IsNormal() && (lspc == -1 || lspc == -11); } + bool IsComposedLM() const { return !IsNormal() && lspc == -11; } + bool IsReplaced() const { return !IsNormal() && lspc >= 0; } + bool IsMissing() const { return !IsNormal() && lspc == -2; } +}; + +void Std(Font& font); +GlyphInfo GetGlyphInfo(Font font, int chr); +const CommonFontInfo& GetFontInfo(Font font); +bool IsNormal(Font font, int chr); +void GlyphMetrics(GlyphInfo& f, Font font, int chr); + +#endif diff --git a/newdraw/Draw/FontWin32.cpp b/newdraw/Draw/FontWin32.cpp index 13df3710d..cf2e53159 100644 --- a/newdraw/Draw/FontWin32.cpp +++ b/newdraw/Draw/FontWin32.cpp @@ -1,412 +1,333 @@ -#include "Draw.h" - -NAMESPACE_UPP - -#ifdef PLATFORM_WIN32 - -#define LLOG(x) // LOG(x) -#define LTIMING(x) // TIMING(x) - -struct FontFaceInfo : Moveable { - String name; - dword info; - - FontFaceInfo() { info = 0; } -}; - -static VectorMap& sFontFace() -{ - static VectorMap s; - return s; -} - -int Font::GetFaceCount() -{ - ONCELOCK { - FontInfo::InitFonts(); - } - return sFontFace().GetCount(); -} - -String Font::GetFaceName(int index) { - ONCELOCK { - FontInfo::InitFonts(); - } - return index >= 0 && index < sFontFace().GetCount() ? sFontFace()[index].name - : Null; -} - -dword Font::GetFaceInfo(int index) { - ONCELOCK { - FontInfo::InitFonts(); - } - return index >= 0 && index < sFontFace().GetCount() ? sFontFace()[index].info - : 0; -} - -void Win32_GetGlyphIndices(HDC hdc, LPCWSTR s, int n, LPWORD r, DWORD flag) -{ - typedef DWORD (WINAPI *GGIW)(HDC, LPCWSTR, int, LPWORD, DWORD); - static GGIW fn; - ONCELOCK - if(HMODULE hDLL = LoadLibrary("gdi32")) - fn = (GGIW) GetProcAddress(hDLL, "GetGlyphIndicesW"); - if(fn) - fn(hdc, s, n, r, flag); - else - memset(r, 0, n * sizeof(WORD)); -} - -int CALLBACK FontInfo::AddFace(const LOGFONT *logfont, const TEXTMETRIC *, dword type, LPARAM param) -{ -#ifdef PLATFORM_WINCE - const wchar *facename = (const wchar *)param; - if(facename && _wcsicmp(logfont->lfFaceName, facename)) - return 1; -#else - const char *facename = (const char *)param; - if(facename && stricmp(logfont->lfFaceName, facename)) - return 1; -#endif - - dword typ = 0; - if((logfont->lfPitchAndFamily & 3) == FIXED_PITCH) - typ |= Font::FIXEDPITCH; - if(type & TRUETYPE_FONTTYPE) - typ |= Font::SCALEABLE; - if(logfont->lfCharSet == SYMBOL_CHARSET) - typ |= Font::SYMBOLTYPE; - else - if(logfont->lfCharSet != 0) - typ |= Font::LOCAL; -#ifndef PLATFORM_WINCE - { - HDC hdc = CreateIC("DISPLAY", NULL, NULL, NULL); - HFONT hfnt = (HFONT) CreateFontIndirect(logfont); - HFONT o = (HFONT) SelectObject(hdc, hfnt); - wchar wch[128]; - WORD pos[128]; - for(int i = 0; i < 128; i++) - wch[i] = i + 256; - Win32_GetGlyphIndices(hdc, (LPCWSTR) wch, 128, pos, 1); - SelectObject(hdc, o); - DeleteObject(hfnt); - DeleteDC(hdc); - int n = 0; - for(int i = 0; i < 128; i++) - if(pos[i] == 0xffff) - n++; - if(n > 10) - typ |= Font::COMPOSED; - } -#endif -#ifdef PLATFORM_WINCE - if(facename) { - FontFaceInfo& f = sFontFace().Add(WString(logfont->lfFaceName).ToString()); - f.name = WString(facename).ToString(); - return 0; - } - FontFaceInfo& f = sFontFace().Add(WString(logfont->lfFaceName).ToString()); - f.name = FromSystemCharset(logfont->lfFaceName); -#else - if(facename) { - FontFaceInfo& f = sFontFace().Add(logfont->lfFaceName); - f.name = facename; - f.info = typ; - return 0; - } - FontFaceInfo& f = sFontFace().Add(logfont->lfFaceName); - f.name = FromSystemCharset(logfont->lfFaceName); -#endif - f.info |= typ; - return 1; -} - -int FontInfo::EnumFace(HDC hdc, const char *face) -{ -#ifdef PLATFORM_WINCE - return EnumFontFamilies(hdc, ToSystemCharset(face), AddFace, (LPARAM)~ToSystemCharset(face)); -#else - return EnumFontFamilies(hdc, face, AddFace, (LPARAM)face); -#endif -} - -void FontInfo::ForceFace(HDC hdc, const char *face, const char *aface) -{ - if(!aface) - aface = "Arial"; - if(EnumFace(hdc, face) && (aface == NULL || EnumFace(hdc, aface))) - Panic("Missing font " + String(face)); -} - -#ifdef PLATFORM_WINCE -const char *FontScreenSans = "Tahoma"; //TODO! -const char *FontScreenSerif = "Tahoma"; -const char *FontScreenFixed = "Courier New"; -const char *FontRoman = "Tahoma" ; -const char *FontArial = "Tahoma"; -const char *FontCourier = "Tahoma"; -const char *FontSymbol = "Tahoma"; -const char *FontWingdings = "Tahoma"; -const char *FontTahoma = "Tahoma"; -#else -const char *FontScreenSans = "Arial"; -const char *FontScreenSerif = "Times New Roman"; -const char *FontScreenFixed = "Courier New"; -const char *FontRoman = "Times New Roman" ; -const char *FontArial = "Arial"; -const char *FontCourier = "Courier New"; -const char *FontSymbol = "Symbol"; -const char *FontWingdings = "WingDings"; -const char *FontTahoma = "Tahoma"; -#endif - -void FontInfo::InitPlatformFonts() { -#ifdef PLATFORM_WINCE - HDC hdc = CreateDC(NULL, NULL, NULL, NULL); -#else - HDC hdc = CreateIC("DISPLAY", NULL, NULL, NULL); -#endif - ForceFace(hdc, "Arial", NULL); - ForceFace(hdc, FontScreenSerif, FontScreenSans); - ForceFace(hdc, FontScreenSans, FontScreenSans); - ForceFace(hdc, FontScreenFixed, FontScreenSans); - ForceFace(hdc, FontRoman, FontScreenSans); - ForceFace(hdc, FontArial, FontScreenSans); - ForceFace(hdc, FontCourier, FontScreenSans); - ForceFace(hdc, FontSymbol, FontScreenSans); - ForceFace(hdc, FontWingdings, FontArial); - ForceFace(hdc, FontTahoma, FontArial); - EnumFace(hdc, NULL); - DeleteDC(hdc); -#ifdef PLATFORM_WINCE - SetStdFont(Arial(10)); -#else - NONCLIENTMETRICS ncm; - ncm.cbSize = sizeof(ncm); - ::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0); - SetStdFont(Font(Font::FindFaceNameIndex(ncm.lfMenuFont.lfFaceName), - abs((int)ncm.lfMenuFont.lfHeight))); -#endif -} - -FontInfo::Data::Data() -{ - refcount = 1; - hfont = NULL; - for(int i = 0; i < 64; i++) - base[i] = NULL; -} - -FontInfo::Data::~Data() -{ - DrawLock __; - if(hfont) - DeleteObject(hfont); - for(int i = 0; i < 64; i++) - if(base[i]) delete[] base[i]; -} - -bool FontInfo::Data::HasChar(int ch) const -{ - HDC hdc = ScreenHDC(); - HFONT ohfont = (HFONT) ::SelectObject(hdc, hfont); - WCHAR c = ch; - WORD pos; - Win32_GetGlyphIndices(hdc, &c, 1, &pos, 1); - ::SelectObject(hdc, ohfont); - return pos != 0xffff; -} - -int sGetCW(HDC hdc, wchar *h, int n) -{ - SIZE sz; - return GetTextExtentPoint32W(hdc, h, n, &sz) ? sz.cx : 0; -} - -void FontInfo::Data::GetMetrics(CharMetrics *t, int from, int count) -{ - DrawLock __; - HDC hdc = ScreenHDC(); - HFONT ohfont = (HFONT) ::SelectObject(hdc, hfont); - if(from >= 8192) { - wchar h[3]; - h[0] = 'x'; - h[1] = 'x'; - h[2] = 'x'; - int w0 = sGetCW(hdc, h, 2); - for(int i = 0; i < count; i++) { - h[1] = from + i; - t[i].width = sGetCW(hdc, h, 3) - w0; - t[i].lspc = t[i].rspc = 0; - } - } - else { - bool abca = false, abcw = false; - Buffer abc(count); -#ifdef PLATFORM_WINCE - if(scaleable) - abcw = ::GetCharABCWidths(hdc, from, from + count - 1, abc); -#else - if(scaleable && !(abcw = ::GetCharABCWidthsW(hdc, from, from + count - 1, abc))) - abca = ::GetCharABCWidthsA(hdc, from, from + count - 1, abc); -#endif - if(abcw) - { - for(ABC *s = abc, *lim = abc + count; s < lim; s++, t++) - { - t->width = s->abcA + s->abcB + s->abcC; - t->lspc = s->abcA; - t->rspc = s->abcC; - } - } - else - { - Buffer wb(count); -#ifdef PLATFORM_WINCE - ::GetCharWidth32(hdc, from, from + count - 1, wb); -#else - ::GetCharWidthW(hdc, from, from + count - 1, wb); -#endif - for(int *s = wb, *lim = wb + count; s < lim; s++, t++) - { - t->width = *s - overhang; - if(abca) - { - ABC aa = abc[(byte)ToAscii(from++)]; - t->lspc = aa.abcA; - t->rspc = aa.abcC; - } - else - t->lspc = t->rspc = 0; - } - } - } - ::SelectObject(hdc, ohfont); -} - -FontInfo FontInfo::AcquireFontInfo0(Font font, HDC hdc, int angle) -{ - DrawLock __; - if(IsNull(font)) - font = StdFont(); - if(font.GetFace() == 0) - font.Face(AStdFont.GetFace()); - if(font.GetHeight() == 0) - font.Height(AStdFont.GetHeight()); -// if(font.GetFace() >= sFontFace().GetCount()) -// font.SetFace(Font::ARIAL); - FontInfo::Data *f, *fh; - f = fh = GetFontHash((font.GetHashValue() ^ angle) % FONTHASH); - LLOG("Acquire " << font); - for(;;) { - f = f->GetNext(HASH); - if(f == fh) break; - if(f->font == font && f->angle == angle) - { - LLOG("Reusing " << f->font << " count:" << f->count); - if(f->InList(LRU)) { - f->Unlink(LRU); - FontCached--; - LLOG("Removing from cache " << f->font << " count:" << f->count << - " cached:" << FontCached); - } - f->refcount++; - return f; - } - } - LLOG("New " << font); - LTIMING("Acquire New"); - f = fh->InsertNext(HASH); - f->font = font; - f->angle = angle; - - byte chrset; - if((sFontFace()[font.GetFace()].info & Font::SCALEABLE) == 0) - chrset = DEFAULT_CHARSET; - else - if(sFontFace()[font.GetFace()].info & Font::SYMBOLTYPE) - chrset = SYMBOL_CHARSET; - else - chrset = DEFAULT_CHARSET; -#ifdef PLATFORM_WINCE - LOGFONT lfnt; - Zero(lfnt); - lfnt.lfHeight = font.GetHeight() ? -abs(font.GetHeight()) : -12; - lfnt.lfWeight = font.IsBold() ? FW_BOLD : FW_NORMAL; - lfnt.lfItalic = font.IsItalic(); - lfnt.lfUnderline = font.IsUnderline(); - lfnt.lfStrikeOut = font.IsStrikeout(); - wcscpy(lfnt.lfFaceName, ToSystemCharset(font.GetFaceName())); - f->hfont = CreateFontIndirect(&lfnt); -#else - f->hfont = CreateFont(font.GetHeight() ? -abs(font.GetHeight()) : -12, - font.GetWidth(), angle, angle, font.IsBold() ? FW_BOLD : FW_NORMAL, - font.IsItalic(), font.IsUnderline(), font.IsStrikeout(), - chrset, - font.IsTrueTypeOnly() ? OUT_TT_ONLY_PRECIS : OUT_DEFAULT_PRECIS, - CLIP_DEFAULT_PRECIS, - font.IsNonAntiAliased() ? NONANTIALIASED_QUALITY - : DEFAULT_QUALITY, - DEFAULT_PITCH|FF_DONTCARE, - sFontFace().GetKey(font.GetFace())); -#endif - ASSERT(f->hfont); - TEXTMETRIC tm; - HFONT hfont = (HFONT) ::SelectObject(hdc, f->hfont); - ::GetTextMetrics(hdc, &tm); - f->ascent = tm.tmAscent; - f->descent = tm.tmDescent; - f->external = tm.tmExternalLeading; - f->internal = tm.tmInternalLeading; - f->height = f->ascent + f->descent; - f->lineheight = f->height + f->external; - f->overhang = tm.tmOverhang; - f->avewidth = tm.tmAveCharWidth; - f->maxwidth = tm.tmMaxCharWidth; - f->firstchar = tm.tmFirstChar; - f->charcount = tm.tmLastChar - tm.tmFirstChar + 1; - f->default_char = tm.tmDefaultChar; - f->fixedpitch = (tm.tmPitchAndFamily & TMPF_FIXED_PITCH) == 0; - f->scaleable = tm.tmPitchAndFamily & TMPF_TRUETYPE; - f->kerning.Clear(); - if(f->scaleable) { - ABC abc; - GetCharABCWidths(hdc, 'o', 'o', &abc); - f->spacebefore = abc.abcA; - f->spaceafter = abc.abcC; - } - else - f->spacebefore = f->spaceafter = 0; -#ifndef PLATFORM_WINCE - int n = ::GetKerningPairs(hdc, 0, NULL); - if(n) { - Buffer kp(n); - ::GetKerningPairs(hdc, n, kp); - const KERNINGPAIR *p = kp; - while(n--) { - f->kerning.Add(MAKELONG(p->wFirst, p->wSecond), p->iKernAmount); - p++; - } - } -#endif - ::SelectObject(hdc, hfont); - f->offset = Size(0, f->ascent); - if(angle) { - FontInfo font0 = AcquireFontInfo0(font, hdc, 0); - double sina, cosa; - Draw::SinCos(angle, sina, cosa); - f->offset.cx = fround(font0.GetAscent() * sina); - f->offset.cy = fround(font0.GetAscent() * cosa); - } - return FontInfo(f); -} - -FontInfo FontInfo::AcquireFontInfo(Font font, int angle) -{ - return AcquireFontInfo0(font, ScreenHDC(), angle); -} - -#endif - -END_UPP_NAMESPACE +#include "Draw.h" + +NAMESPACE_UPP + +#ifdef PLATFORM_WIN32 + +#define LLOG(x) // LOG(x) +#define LTIMING(x) // TIMING(x) + +void GetStdFontSys(String& name, int& height) +{ +#ifdef PLATFORM_WINCE + name = "Arial"; + height = 10; +#else + NONCLIENTMETRICS ncm; + ncm.cbSize = sizeof(ncm); + ::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0); + name = ncm.lfMenuFont.lfFaceName; + height = abs((int)ncm.lfMenuFont.lfHeight); +#endif +} + +#define FONTCACHE 50 + +struct HFontEntry { + Font font; + HFONT hfont; +}; + +HFONT GetWin32Font(Font fnt, int angle) +{ + RTIMING("FTFace"); + DDUMP(fnt); + static HFontEntry cache[FONTCACHE]; + ONCELOCK { + for(int i = 0; i < FONTCACHE; i++) + cache[i].font.Height(-30000); + } + HFontEntry be; + be = cache[0]; + for(int i = 0; i < FONTCACHE; i++) { + HFontEntry e = cache[i]; + if(i) + cache[i] = be; + if(e.font == fnt) { + if(i) + cache[0] = e; + return e.hfont; + } + be = e; + } + RTIMING("FTFace2"); + if(be.hfont) + DeleteObject(be.hfont); + + be.font = fnt; +#ifdef PLATFORM_WINCE + LOGFONT lfnt; + Zero(lfnt); + lfnt.lfHeight = fnt.GetHeight() ? -abs(fnt.GetHeight()) : -12; + lfnt.lfWeight = fnt.IsBold() ? FW_BOLD : FW_NORMAL; + lfnt.lfItalic = fnt.IsItalic(); + lfnt.lfUnderline = fnt.IsUnderline(); + lfnt.lfStrikeOut = fnt.IsStrikeout(); + wcscpy(lfnt.lfFaceName, ToSystemCharset(fnt.GetFaceName())); + be.hfont = CreateFontIndirect(&lfnt); +#else + be.hfont = CreateFont( + fnt.GetHeight() ? -abs(fnt.GetHeight()) : -12, + fnt.GetWidth(), angle, angle, fnt.IsBold() ? FW_BOLD : FW_NORMAL, + fnt.IsItalic(), fnt.IsUnderline(), fnt.IsStrikeout(), + fnt.GetFace() == Font::SYMBOL ? SYMBOL_CHARSET : DEFAULT_CHARSET, + fnt.IsTrueTypeOnly() ? OUT_TT_ONLY_PRECIS : OUT_DEFAULT_PRECIS, + CLIP_DEFAULT_PRECIS, + fnt.IsNonAntiAliased() ? NONANTIALIASED_QUALITY : DEFAULT_QUALITY, + DEFAULT_PITCH|FF_DONTCARE, + fnt.GetFaceName() + ); +#endif + cache[0] = be; + return be.hfont; +} + +int sGetCW(HDC hdc, wchar *h, int n) +{ + SIZE sz; + return GetTextExtentPoint32W(hdc, h, n, &sz) ? sz.cx : 0; +} + +static void Win32_GetGlyphIndices(HDC hdc, LPCWSTR s, int n, LPWORD r, DWORD flag) +{ + typedef DWORD (WINAPI *GGIW)(HDC, LPCWSTR, int, LPWORD, DWORD); + static GGIW fn; + ONCELOCK + if(HMODULE hDLL = LoadLibrary("gdi32")) + fn = (GGIW) GetProcAddress(hDLL, "GetGlyphIndicesW"); + if(fn) + fn(hdc, s, n, r, flag); + else + memset(r, 0, n * sizeof(WORD)); +} + +static HDC Win32_IC() +{ + static HDC hdc; + ONCELOCK { + hdc = CreateIC("DISPLAY", NULL, NULL, NULL); + } + return hdc; +} + +CommonFontInfo GetFontInfoSys(Font font) +{ + CommonFontInfo fi; + memset(&fi, 0, sizeof(fi)); + HFONT hfont = GetWin32Font(font, 0); + if(hfont) { + HDC hdc = Win32_IC(); + HFONT ohfont = (HFONT) ::SelectObject(hdc, hfont); + TEXTMETRIC tm; + ::GetTextMetrics(hdc, &tm); + fi.ascent = tm.tmAscent; + fi.descent = tm.tmDescent; + fi.external = tm.tmExternalLeading; + fi.internal = tm.tmInternalLeading; + fi.height = fi.ascent + fi.descent; + fi.lineheight = fi.height + fi.external; + fi.overhang = tm.tmOverhang; + fi.avewidth = tm.tmAveCharWidth; + fi.maxwidth = tm.tmMaxCharWidth; + fi.firstchar = tm.tmFirstChar; + fi.charcount = tm.tmLastChar - tm.tmFirstChar + 1; + fi.default_char = tm.tmDefaultChar; + fi.fixedpitch = (tm.tmPitchAndFamily & TMPF_FIXED_PITCH) == 0; + fi.scaleable = tm.tmPitchAndFamily & TMPF_TRUETYPE; + if(fi.scaleable) { + ABC abc; + GetCharABCWidths(hdc, 'o', 'o', &abc); + fi.spacebefore = abc.abcA; + fi.spaceafter = abc.abcC; + } + else + fi.spacebefore = fi.spaceafter = 0; + ::SelectObject(hdc, ohfont); + } + return fi; +} + +static Vector *sList; + +static int CALLBACK Win32_AddFace(const LOGFONT *logfont, const TEXTMETRIC *, dword type, LPARAM param) +{ +#ifdef PLATFORM_WINCE + const wchar *facename = (const wchar *)param; + if(facename && _wcsicmp(logfont->lfFaceName, facename)) + return 1; +#else + const char *facename = (const char *)param; + if(facename && stricmp(logfont->lfFaceName, facename)) + return 1; +#endif + + dword typ = 0; + if((logfont->lfPitchAndFamily & 3) == FIXED_PITCH) + typ |= Font::FIXEDPITCH; + if(type & TRUETYPE_FONTTYPE) + typ |= Font::SCALEABLE; + if(!(logfont->lfCharSet == SYMBOL_CHARSET) && logfont->lfCharSet != 0) + typ |= Font::LOCAL; +#ifdef PLATFORM_WINCE + FontFaceInfo& f = sFontFace().Add(WString(logfont->lfFaceName).ToString()); + f.name = FromSystemCharset(logfont->lfFaceName); +#else + FaceInfo& f = sList->Add(); + f.name = FromSystemCharset(logfont->lfFaceName); + f.info = typ; +#endif + return facename ? 0 : 1; +} + +static int Win32_EnumFace(HDC hdc, const char *face) +{ +#ifdef PLATFORM_WINCE + return EnumFontFamilies(hdc, ToSystemCharset(face), Win32_AddFace, (LPARAM)~ToSystemCharset(face)); +#else + return EnumFontFamilies(hdc, face, Win32_AddFace, (LPARAM)face); +#endif +} + +static void Win32_ForceFace(HDC hdc, const char *face, const char *aface) +{ + if(!aface) + aface = "Arial"; + if(Win32_EnumFace(hdc, face) && Win32_EnumFace(hdc, aface)) + Panic("Missing font " + String(face)); +} + +Vector GetAllFacesSys() +{ + Vector list; + sList = &list; + list.Add().name = "STDFONT"; + list.Top().info = 0; +#ifdef PLATFORM_WINCE + HDC hdc = CreateDC(NULL, NULL, NULL, NULL); + Win32_ForceFace(hdc, "Tahoma", NULL); + Win32_ForceFace(hdc, "Tahoma", "Tahoma"); + Win32_ForceFace(hdc, "Courier New", "Tahoma"); + Win32_ForceFace(hdc, "Tahoma", "Tahoma"); + Win32_ForceFace(hdc, "Tahoma", "Tahoma"); + Win32_ForceFace(hdc, "Tahoma", "Tahoma"); + Win32_ForceFace(hdc, "Tahoma", "Tahoma"); + Win32_ForceFace(hdc, "Tahoma", "Tahoma"); + Win32_ForceFace(hdc, "Tahoma", "Tahoma"); +#else + HDC hdc = CreateIC("DISPLAY", NULL, NULL, NULL); + Win32_ForceFace(hdc, "Arial", NULL); + Win32_ForceFace(hdc, "Times New Roman", "Arial"); + Win32_ForceFace(hdc, "Courier New", "Arial"); + Win32_ForceFace(hdc, "Times New Roman", "Arial"); + Win32_ForceFace(hdc, "Arial", "Arial"); + Win32_ForceFace(hdc, "Courier New", "Arial"); + Win32_ForceFace(hdc, "Symbol", "Arial"); + Win32_ForceFace(hdc, "WingDings", "Arial"); + Win32_ForceFace(hdc, "Tahoma", "Arial"); +#endif + Win32_EnumFace(hdc, NULL); + DeleteDC(hdc); + return list; +} + +#define GLYPHINFOCACHE 31 + +GlyphInfo GetGlyphInfoSys(Font font, int chr) +{ + static Font fnt[GLYPHINFOCACHE]; + static int pg[GLYPHINFOCACHE]; + static GlyphInfo li[GLYPHINFOCACHE][256]; + + ONCELOCK { + for(int i = 0; i < GLYPHINFOCACHE; i++) + pg[i] = -1; + } + + int page = chr >> 8; + int q = CombineHash(font, page) % GLYPHINFOCACHE; + + if(fnt[q] != font || pg[q] != page) { + DDUMP(font); + DDUMP(q); + fnt[q] = font; + pg[q] = page; + HFONT hfont = GetWin32Font(font, 0); + if(!hfont) { + GlyphInfo n; + memset(&n, 0, sizeof(GlyphInfo)); + return n; + } + HDC hdc = Win32_IC(); + HFONT ohfont = (HFONT) ::SelectObject(hdc, hfont); + int from = page << 8; + GlyphInfo *t = li[q]; + if(page >= 32) { + wchar h[3]; + h[0] = 'x'; + h[1] = 'x'; + h[2] = 'x'; + int w0 = sGetCW(hdc, h, 2); + for(int i = 0; i < 256; i++) { + h[1] = from + i; + t[i].width = sGetCW(hdc, h, 3) - w0; + t[i].lspc = t[i].rspc = 0; + } + } + else { + bool abca = false, abcw = false; + Buffer abc(256); + abcw = ::GetCharABCWidths(hdc, from, from + 256 - 1, abc); + #ifndef PLATFORM_WINCE + if(!abcw) + abca = ::GetCharABCWidthsA(hdc, from, from + 256 - 1, abc); + #endif + if(abcw) + { + for(ABC *s = abc, *lim = abc + 256; s < lim; s++, t++) + { + t->width = s->abcA + s->abcB + s->abcC; + t->lspc = s->abcA; + t->rspc = s->abcC; + } + } + else + { + Buffer wb(256); + #ifdef PLATFORM_WINCE + ::GetCharWidth32(hdc, from, from + 256 - 1, wb); + #else + ::GetCharWidthW(hdc, from, from + 256 - 1, wb); + #endif + for(int *s = wb, *lim = wb + 256; s < lim; s++, t++) + { + t->width = *s - GetFontInfoSys(font).overhang; + if(abca) + { + ABC aa = abc[(byte)ToAscii(from++)]; + t->lspc = aa.abcA; + t->rspc = aa.abcC; + } + else + t->lspc = t->rspc = 0; + } + } + } +#ifndef PLATFORM_WINCE + WORD pos[256]; + WCHAR wch[256]; + for(int i = 0; i < 256; i++) + wch[i] = from + i; + Win32_GetGlyphIndices(hdc, wch, 256, pos, 1); + for(int i = 0; i < 256; i++) + if(pos[i] == 0xffff) { + li[q][i].width = (int16)0x8000; + li[q][i].lspc = li[q][i].rspc = 0; + } +#endif + } + return li[q][chr & 255]; +} + +#endif + +END_UPP_NAMESPACE