Core, Draw: Applied changes for mac (thanks daveremba)

git-svn-id: svn://ultimatepp.org/upp/trunk@3688 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2011-07-21 18:11:08 +00:00
parent af75851094
commit 9ca5b1f9ed
3 changed files with 768 additions and 746 deletions

View file

@ -1,115 +1,128 @@
#if __GNUC__
#define COMPILER_GCC 1
#define GCC_VERSION (__GNUC__ * 10000 \
+ __GNUC_MINOR__ * 100 \
+ __GNUC_PATCHLEVEL__)
#if __WIN32
#define COMPILER_MINGW
#define PLATFORM_WIN32
#endif
#if __unix || __unix__ || __APPLE__
#define PLATFORM_POSIX 1
#if __linux
#define PLATFORM_LINUX 1
#else
#if __FreeBSD__ || __OpenBSD__ || __NetBSD__ || __APPLE__
#define PLATFORM_BSD 1
#if __FreeBSD__
#define PLATFORM_FREEBSD 1
#endif
#if __OpenBSD__
#define PLATFORM_OPENBSD 1
#endif
#if __NetBSD__
#define PLATFORM_NETBSD 1
#endif
#elif __sun
#define PLATFORM_SOLARIS 1
#else
#error Unknown OS
#endif
#endif
#endif
#if __x86_64
#define CPU_LE 1
#define CPU_LITTLE_ENDIAN 1
#define CPU_UNALIGNED 1
#define CPU_X86 1
#define CPU_64 1
#define CPU_AMD64 1
#define CPU_SSE2 1
#define CPU_IA64 1
#elif __i386 || __i386__ || i386
#define CPU_LE 1
#define CPU_LITTLE_ENDIAN 1
#define CPU_UNALIGNED 1
#define CPU_X86 1
#define CPU_32 1
#define CPU_IA32 1
#ifdef flagSSE2
#define CPU_SSE2 1
#endif
#elif __sparc // ToDo!
#define CPU_32 1
#define CPU_SPARC 1
#define CPU_BE 1
#define CPU_BIG_ENDIAN 1
#define CPU_ALIGNED 1
#elif __arm // ToDo!
#define CPU_32 1
#define CPU_ARM 1
#define CPU_LE 1
#define CPU_LITTLE_ENDIAN 1 // is it really?
#define CPU_ALIGNED 1
#elif __bfin
#define CPU_32 1
#define CPU_BLACKFIN
#define CPU_LE 1
#define CPU_LITTLE_ENDIAN 1
#define CPU_ALIGNED 1
#define _HAVE_NO_STDWSTRING 1
//BF toolchain has no support for __thread (TLS), so U++ Heap not possible
#define flagUSEMALLOC
#else
#error Unknown CPU architecture
#endif
#endif
#ifdef _MSC_VER
#define COMPILER_MSC 1
#ifndef _CPPRTTI
#error RTTI must be enabled !!!
#endif //_CPPRTTI
#if _MSC_VER <= 1300
#error MSC 6.0 not supported anymore
#endif
#pragma warning(disable: 4786)
#define _CRT_SECURE_NO_DEPRECATE 1 // we really need strcpy etc. to work with MSC 8.0
#define PLATFORM_WIN32 1
#define CPU_LE 1
#define CPU_LITTLE_ENDIAN 1
#define CPU_UNALIGNED 1
#define CPU_X86 1
#ifdef _WIN64
#define PLATFORM_WIN64 1
#define CPU_64 1
#define CPU_AMD64 1
#define CPU_SSE2 1
#define CPU_IA64 1
#else
#define CPU_32 1
#define CPU_IA32 1
#ifdef flagSSE2
#define CPU_SSE2 1
#endif
#endif
#endif
#if __GNUC__
#define GCC_VERSION (__GNUC__ * 10000 \
+ __GNUC_MINOR__ * 100 \
+ __GNUC_PATCHLEVEL__)
#define COMPILER_GCC 1
#if __WIN32
#define COMPILER_MINGW
#define PLATFORM_WIN32
#endif
#if __unix || __unix__ || __APPLE__
#define PLATFORM_POSIX 1
#ifdef flagGUI
#define PLATFORM_X11 1
#endif
#if __linux
#define PLATFORM_LINUX 1
// zvzv add
// __linux is undef on APPLE MACOSX, MACOSX has BSD stuff
#elif __APPLE__
// zvzv note
// s/b MACOSX
#define PLATFORM_OSX11 1
#define PLATFORM_BSD 1
#else
// zvzv mod
// was: #if __FreeBSD__ || __OpenBSD__ || __NetBSD__ || __APPLE__
#if __FreeBSD__ || __OpenBSD__ || __NetBSD__
#define PLATFORM_BSD 1
#if __FreeBSD__
#define PLATFORM_FREEBSD 1
#endif
#if __OpenBSD__
#define PLATFORM_OPENBSD 1
#endif
#if __NetBSD__
#define PLATFORM_NETBSD 1
#endif
#elif __sun
#define PLATFORM_SOLARIS 1
#else
#error Unknown OS
#endif
#endif
#endif
#if __x86_64
#define CPU_LE 1
#define CPU_LITTLE_ENDIAN 1
#define CPU_UNALIGNED 1
#define CPU_X86 1
#define CPU_64 1
#define CPU_AMD64 1
#define CPU_SSE2 1
#define CPU_IA64 1
#elif __i386 || __i386__ || i386
#define CPU_LE 1
#define CPU_LITTLE_ENDIAN 1
#define CPU_UNALIGNED 1
#define CPU_X86 1
#define CPU_32 1
#define CPU_IA32 1
#ifdef flagSSE2
#define CPU_SSE2 1
#endif
#elif __sparc // ToDo!
#define CPU_32 1
#define CPU_SPARC 1
#define CPU_BE 1
#define CPU_BIG_ENDIAN 1
#define CPU_ALIGNED 1
#elif __arm // ToDo!
#define CPU_32 1
#define CPU_ARM 1
#define CPU_LE 1
#define CPU_LITTLE_ENDIAN 1 // is it really?
#define CPU_ALIGNED 1
#elif __bfin
#define CPU_32 1
#define CPU_BLACKFIN
#define CPU_LE 1
#define CPU_LITTLE_ENDIAN 1
#define CPU_ALIGNED 1
#define _HAVE_NO_STDWSTRING 1
//BF toolchain has no support for __thread (TLS), so U++ Heap not possible
#define flagUSEMALLOC
#else
#error Unknown CPU architecture
#endif
#endif
#ifdef _MSC_VER
#define COMPILER_MSC 1
#ifndef _CPPRTTI
#error RTTI must be enabled !!!
#endif //_CPPRTTI
#if _MSC_VER <= 1300
#error MSC 6.0 not supported anymore
#endif
#pragma warning(disable: 4786)
#define _CRT_SECURE_NO_DEPRECATE 1 // we really need strcpy etc. to work with MSC 8.0
#define PLATFORM_WIN32 1
#define CPU_LE 1
#define CPU_LITTLE_ENDIAN 1
#define CPU_UNALIGNED 1
#define CPU_X86 1
#ifdef _WIN64
#define PLATFORM_WIN64 1
#define CPU_64 1
#define CPU_AMD64 1
#define CPU_SSE2 1
#define CPU_IA64 1
#else
#define CPU_32 1
#define CPU_IA32 1
#ifdef flagSSE2
#define CPU_SSE2 1
#endif
#endif
#endif

View file

@ -1,390 +1,398 @@
#include "Draw.h"
#define LLOG(x)
NAMESPACE_UPP
CommonFontInfo GetFontInfoSys(Font font);
GlyphInfo GetGlyphInfoSys(Font font, int chr);
void GetStdFontSys(String& name, int& height);
Vector<FaceInfo> GetAllFacesSys();
bool Replace(Font fnt, int chr, Font& rfnt);
void Std(Font& font)
{
if(IsNull(font))
font = StdFont();
if(font.GetFace() == 0)
font.Face(GetStdFont().GetFace());
if(font.GetHeight() == 0)
font.Height(GetStdFont().GetHeight());
}
Size Font::StdFontSize;
Font Font::AStdFont;
INITBLOCK {
RichValue<Font>::Register();
}
const Vector<FaceInfo>& Font::List()
{
static Vector<FaceInfo> *q;
ONCELOCK {
static Vector<FaceInfo> x;
x = GetAllFacesSys();
q = &x;
}
return *q;
}
void sInitFonts()
{
Font::List();
GetStdFont();
}
INITBLOCK {
sInitFonts();
}
int Font::GetFaceCount()
{
return List().GetCount();
}
String Font::GetFaceName(int index)
{
if(index == 0)
return "STDFONT";
const Vector<FaceInfo>& l = List();
if(index >= 0 && index < l.GetCount())
return l[index].name;
return Null;
}
dword Font::GetFaceInfo(int index)
{
const Vector<FaceInfo>& l = List();
if(index >= 0 && index < l.GetCount())
return l[index].info;
return 0;
}
int FontFilter(int c)
{
return c >= 'a' && c <= 'z' || c >= '0' && c <= '9' ? c : c >= 'A' && c <= 'Z' ? ToLower(c) : 0;
}
int Font::FindFaceNameIndex(const String& name) {
if(name == "STDFONT")
return 0;
for(int i = 1; i < GetFaceCount(); i++)
if(GetFaceName(i) == name)
return i;
String n = Filter(name, FontFilter);
for(int i = 1; i < GetFaceCount(); i++)
if(Filter(GetFaceName(i), FontFilter) == n)
return i;
return 0;
}
void Font::SyncStdFont()
{
DrawLock __;
StdFontSize = Size(AStdFont.GetAveWidth(), AStdFont().Bold().GetCy());
}
void Font::SetStdFont(Font font)
{
DrawLock __;
InitStdFont();
AStdFont = font;
SyncStdFont();
}
void Font::InitStdFont()
{
ONCELOCK {
DrawLock __;
List();
AStdFont = Arial(12);
String name;
int height = 0;
GetStdFontSys(name, height);
#ifdef PLATFORM_WIN32
#ifdef flagWINGL
AStdFont = Font(FindFaceNameIndex("Tahoma"), 12);
#else
int q = FindFaceNameIndex(name);
if(q <= 0)
q = FindFaceNameIndex("Tahoma");
if(q <= 0)
q = FindFaceNameIndex("Microsoft Sans Serif");
if(q <= 0)
q = FindFaceNameIndex("MS Sans Serif");
if(q > 0)
AStdFont = Font(q, max(height, 1));
#endif
SyncStdFont();
#endif
}
}
Font Font::GetStdFont()
{
InitStdFont();
return AStdFont;
}
Size Font::GetStdFontSize()
{
InitStdFont();
return StdFontSize;
}
Font StdFont()
{
return Font(0, -32000);
}
int Font::GetHeight() const
{
return v.height == -32000 ? GetStdFont().GetHeight() : v.height;
}
String Font::GetFaceName() const {
if(IsNull()) return String();
if(GetFace() == 0)
return "STDFONT";
return GetFaceName(GetFace());
}
dword Font::GetFaceInfo() const {
if(IsNull()) return 0;
return GetFaceInfo(GetFace());
}
Font& Font::FaceName(const String& name) {
int n = FindFaceNameIndex(name);
Face(n < 0 ? 0xffff : n);
return *this;
}
void Font::Serialize(Stream& s) {
int version = 1;
s / version;
if(version >= 1) {
enum {
OLD_STDFONT, OLD_SCREEN_SERIF, OLD_SCREEN_SANS, OLD_SCREEN_FIXED,
OLD_ROMAN,
OLD_ARIAL,
OLD_COURIER,
};
int f = GetFace();
if(f > COURIER)
f = -1;
s / f;
String name;
if(f == OLD_ROMAN)
f = ROMAN;
if(f == OLD_ARIAL)
f = ARIAL;
if(f == OLD_COURIER)
f = COURIER;
if(f < 0) {
name = GetFaceName();
s % name;
}
if(s.IsLoading())
if(f >= 0)
Face(f);
else
FaceName(name);
}
else {
String name = GetFaceName();
s % name;
if(s.IsLoading()) {
FaceName(name);
if(IsNull())
Face(COURIER);
}
}
s % v.flags % v.height % v.width;
}
template<>
String AsString(const Font& f) {
if(IsNull(f)) return "<null>";
String s = "<" + f.GetFaceName() + Format(":%d", f.GetHeight());
if(f.IsBold())
s += " Bold";
if(f.IsItalic())
s += " Italic";
if(f.IsUnderline())
s += " Underline";
if(f.IsStrikeout())
s += " Strikeout";
return s + '>';
}
struct CharEntry {
int64 font;
GlyphInfo info;
word chr;
};
CharEntry fc_cache_global[4093];
bool IsNormal(Font font, int chr)
{
DrawLock __;
CharEntry& e = fc_cache_global[CombineHash(font.GetHashValue(), chr) % 4093];
if(e.font == font.AsInt64() || e.chr == chr)
return e.info.IsNormal();
return GetGlyphInfoSys(font, chr).IsNormal();
}
CharEntry GetGlyphEntry(Font font, int chr, unsigned hash)
{
DrawLock __;
CharEntry& e = fc_cache_global[hash % 4093];
if(e.font != font.AsInt64() || e.chr != chr) {
e.font = font.AsInt64();
e.chr = chr;
e.info = GetGlyphInfoSys(font, chr);
if(!e.info.IsNormal()) {
ComposedGlyph cg;
Font rfnt;
if(Compose(font, chr, cg)) {
e.info.lspc = -1;
e.info.rspc = cg.basic_char;
}
else
if(Replace(font, chr, rfnt)) {
e.info.lspc = rfnt.GetFace();
e.info.rspc = rfnt.GetHeight();
}
else
e.info.lspc = -2;
}
}
return e;
}
thread__ CharEntry fc_cache[512];
GlyphInfo GetGlyphInfo(Font font, int chr)
{
Std(font);
unsigned hash = CombineHash(font.GetHashValue(), chr);
CharEntry& e = fc_cache[hash & 511];
if(e.font != font.AsInt64() || e.chr != chr)
e = GetGlyphEntry(font, chr, hash);
return e.info;
}
bool Font::IsNormal(int ch) const
{
return GetGlyphInfo(*this, ch).IsNormal();
}
bool Font::IsComposed(int ch) const
{
return GetGlyphInfo(*this, ch).IsComposed();
}
bool Font::IsReplaced(int ch) const
{
return GetGlyphInfo(*this, ch).IsReplaced();
}
bool Font::IsMissing(int ch) const
{
return GetGlyphInfo(*this, ch).IsMissing();
}
int Font::HasChar(int ch) const
{
return !GetGlyphInfo(*this, ch).IsMissing();
}
void GlyphMetrics(GlyphInfo& f, Font font, int chr)
{
if(f.IsReplaced())
f = GetGlyphInfo(font().Face(f.lspc).Height(f.rspc), chr);
if(f.IsComposed()) {
f = GetGlyphInfo(font, f.rspc);
if(f.IsComposedLM())
f.rspc += f.width / 2;
}
}
GlyphInfo GetGlyphMetrics(Font font, int chr)
{
GlyphInfo f = GetGlyphInfo(font, chr);
if(f.IsMissing())
f = GetGlyphInfo(font, '?');
GlyphMetrics(f, font, chr);
return f;
}
struct FontEntry {
CommonFontInfo info;
int64 font;
};
thread__ FontEntry fi_cache[64];
const CommonFontInfo& GetFontInfo(Font font)
{
Std(font);
unsigned hash = font.GetHashValue() & 63;
FontEntry& e = fi_cache[hash];
if(e.font != font.AsInt64()) {
DrawLock __;
e.font = font.AsInt64();
e.info = GetFontInfoSys(font);
}
return e.info;
}
int Font::GetWidth(int c) const {
return GetGlyphMetrics(*this, c).width;
}
int Font::GetLeftSpace(int c) const {
return GetGlyphMetrics(*this, c).lspc;
}
int Font::GetRightSpace(int c) const {
return GetGlyphMetrics(*this, c).rspc;
}
thread__ int64 lastFiFont = INT_MIN;
thread__ CommonFontInfo lastFontInfo;
thread__ int64 lastStdFont = INT_MIN;
const CommonFontInfo& Font::Fi() const
{
if(lastStdFont != AStdFont.AsInt64()) {
lastFiFont = INT_MIN;
lastStdFont = AStdFont.AsInt64();
}
if(AsInt64() == lastFiFont)
return lastFontInfo;
lastFontInfo = GetFontInfo(*this);
lastFiFont = AsInt64();
return lastFontInfo;
}
FontInfo Font::Info() const
{
FontInfo h;
h.font = *this;
return h;
}
END_UPP_NAMESPACE
#include "Draw.h"
#define LLOG(x)
NAMESPACE_UPP
CommonFontInfo GetFontInfoSys(Font font);
GlyphInfo GetGlyphInfoSys(Font font, int chr);
void GetStdFontSys(String& name, int& height);
Vector<FaceInfo> GetAllFacesSys();
bool Replace(Font fnt, int chr, Font& rfnt);
void Std(Font& font)
{
if(IsNull(font))
font = StdFont();
if(font.GetFace() == 0)
font.Face(GetStdFont().GetFace());
if(font.GetHeight() == 0)
font.Height(GetStdFont().GetHeight());
}
Size Font::StdFontSize;
Font Font::AStdFont;
INITBLOCK {
RichValue<Font>::Register();
}
const Vector<FaceInfo>& Font::List()
{
static Vector<FaceInfo> *q;
ONCELOCK {
static Vector<FaceInfo> x;
x = GetAllFacesSys();
q = &x;
}
return *q;
}
void sInitFonts()
{
Font::List();
GetStdFont();
}
INITBLOCK {
sInitFonts();
}
int Font::GetFaceCount()
{
return List().GetCount();
}
String Font::GetFaceName(int index)
{
if(index == 0)
return "STDFONT";
const Vector<FaceInfo>& l = List();
if(index >= 0 && index < l.GetCount())
return l[index].name;
return Null;
}
dword Font::GetFaceInfo(int index)
{
const Vector<FaceInfo>& l = List();
if(index >= 0 && index < l.GetCount())
return l[index].info;
return 0;
}
int FontFilter(int c)
{
return c >= 'a' && c <= 'z' || c >= '0' && c <= '9' ? c : c >= 'A' && c <= 'Z' ? ToLower(c) : 0;
}
int Font::FindFaceNameIndex(const String& name) {
if(name == "STDFONT")
return 0;
for(int i = 1; i < GetFaceCount(); i++)
if(GetFaceName(i) == name)
return i;
String n = Filter(name, FontFilter);
for(int i = 1; i < GetFaceCount(); i++)
if(Filter(GetFaceName(i), FontFilter) == n)
return i;
return 0;
}
void Font::SyncStdFont()
{
DrawLock __;
StdFontSize = Size(AStdFont.GetAveWidth(), AStdFont().Bold().GetCy());
}
void Font::SetStdFont(Font font)
{
DrawLock __;
InitStdFont();
AStdFont = font;
SyncStdFont();
}
void Font::InitStdFont()
{
ONCELOCK {
DrawLock __;
List();
AStdFont = Arial(12);
String name;
int height = 0;
GetStdFontSys(name, height);
#ifdef PLATFORM_WIN32
#ifdef flagWINGL
AStdFont = Font(FindFaceNameIndex("Tahoma"), 12);
#else
int q = FindFaceNameIndex(name);
if(q <= 0)
q = FindFaceNameIndex("Tahoma");
if(q <= 0)
q = FindFaceNameIndex("Microsoft Sans Serif");
if(q <= 0)
q = FindFaceNameIndex("MS Sans Serif");
if(q > 0)
AStdFont = Font(q, max(height, 1));
#endif
SyncStdFont();
#endif
}
}
Font Font::GetStdFont()
{
InitStdFont();
return AStdFont;
}
Size Font::GetStdFontSize()
{
InitStdFont();
return StdFontSize;
}
Font StdFont()
{
return Font(0, -32000);
}
int Font::GetHeight() const
{
return v.height == -32000 ? GetStdFont().GetHeight() : v.height;
}
String Font::GetFaceName() const {
if(IsNull()) return String();
if(GetFace() == 0)
return "STDFONT";
return GetFaceName(GetFace());
}
dword Font::GetFaceInfo() const {
if(IsNull()) return 0;
return GetFaceInfo(GetFace());
}
Font& Font::FaceName(const String& name) {
int n = FindFaceNameIndex(name);
Face(n < 0 ? 0xffff : n);
return *this;
}
void Font::Serialize(Stream& s) {
int version = 1;
s / version;
if(version >= 1) {
enum {
OLD_STDFONT, OLD_SCREEN_SERIF, OLD_SCREEN_SANS, OLD_SCREEN_FIXED,
OLD_ROMAN,
OLD_ARIAL,
OLD_COURIER,
};
int f = GetFace();
if(f > COURIER)
f = -1;
s / f;
String name;
if(f == OLD_ROMAN)
f = ROMAN;
if(f == OLD_ARIAL)
f = ARIAL;
if(f == OLD_COURIER)
f = COURIER;
if(f < 0) {
name = GetFaceName();
s % name;
}
if(s.IsLoading())
if(f >= 0)
Face(f);
else
FaceName(name);
}
else {
String name = GetFaceName();
s % name;
if(s.IsLoading()) {
FaceName(name);
if(IsNull())
Face(COURIER);
}
}
s % v.flags % v.height % v.width;
}
template<>
String AsString(const Font& f) {
if(IsNull(f)) return "<null>";
String s = "<" + f.GetFaceName() + Format(":%d", f.GetHeight());
if(f.IsBold())
s += " Bold";
if(f.IsItalic())
s += " Italic";
if(f.IsUnderline())
s += " Underline";
if(f.IsStrikeout())
s += " Strikeout";
return s + '>';
}
struct CharEntry {
int64 font;
GlyphInfo info;
word chr;
};
CharEntry fc_cache_global[4093];
bool IsNormal(Font font, int chr)
{
DrawLock __;
CharEntry& e = fc_cache_global[CombineHash(font.GetHashValue(), chr) % 4093];
if(e.font == font.AsInt64() || e.chr == chr)
return e.info.IsNormal();
return GetGlyphInfoSys(font, chr).IsNormal();
}
CharEntry GetGlyphEntry(Font font, int chr, unsigned hash)
{
DrawLock __;
CharEntry& e = fc_cache_global[hash % 4093];
if(e.font != font.AsInt64() || e.chr != chr) {
e.font = font.AsInt64();
e.chr = chr;
e.info = GetGlyphInfoSys(font, chr);
if(!e.info.IsNormal()) {
ComposedGlyph cg;
Font rfnt;
if(Compose(font, chr, cg)) {
e.info.lspc = -1;
e.info.rspc = cg.basic_char;
}
else
if(Replace(font, chr, rfnt)) {
e.info.lspc = rfnt.GetFace();
e.info.rspc = rfnt.GetHeight();
}
else
e.info.lspc = -2;
}
}
return e;
}
thread__ CharEntry fc_cache[512];
GlyphInfo GetGlyphInfo(Font font, int chr)
{
Std(font);
unsigned hash = CombineHash(font.GetHashValue(), chr);
CharEntry& e = fc_cache[hash & 511];
if(e.font != font.AsInt64() || e.chr != chr)
e = GetGlyphEntry(font, chr, hash);
return e.info;
}
bool Font::IsNormal(int ch) const
{
return GetGlyphInfo(*this, ch).IsNormal();
}
bool Font::IsComposed(int ch) const
{
return GetGlyphInfo(*this, ch).IsComposed();
}
bool Font::IsReplaced(int ch) const
{
return GetGlyphInfo(*this, ch).IsReplaced();
}
bool Font::IsMissing(int ch) const
{
return GetGlyphInfo(*this, ch).IsMissing();
}
int Font::HasChar(int ch) const
{
return !GetGlyphInfo(*this, ch).IsMissing();
}
void GlyphMetrics(GlyphInfo& f, Font font, int chr)
{
if(f.IsReplaced())
f = GetGlyphInfo(font().Face(f.lspc).Height(f.rspc), chr);
if(f.IsComposed()) {
f = GetGlyphInfo(font, f.rspc);
if(f.IsComposedLM())
f.rspc += f.width / 2;
}
}
GlyphInfo GetGlyphMetrics(Font font, int chr)
{
GlyphInfo f = GetGlyphInfo(font, chr);
if(f.IsMissing())
f = GetGlyphInfo(font, '?');
GlyphMetrics(f, font, chr);
return f;
}
struct FontEntry {
CommonFontInfo info;
int64 font;
};
thread__ FontEntry fi_cache[64];
const CommonFontInfo& GetFontInfo(Font font)
{
Std(font);
unsigned hash = font.GetHashValue() & 63;
FontEntry& e = fi_cache[hash];
if(e.font != font.AsInt64()) {
DrawLock __;
e.font = font.AsInt64();
e.info = GetFontInfoSys(font);
}
return e.info;
}
int Font::GetWidth(int c) const {
return GetGlyphMetrics(*this, c).width;
}
int Font::GetLeftSpace(int c) const {
return GetGlyphMetrics(*this, c).lspc;
}
int Font::GetRightSpace(int c) const {
return GetGlyphMetrics(*this, c).rspc;
}
thread__ int64 lastFiFont = INT_MIN;
thread__ CommonFontInfo lastFontInfo;
thread__ int64 lastStdFont = INT_MIN;
const CommonFontInfo& Font::Fi() const
{
#ifdef PLATFORM_OSX11
// known leak on MacOSX here: getAllCarbonLazyValues2000 calls Core.h op new()
// should not call UPP op new()
// from GetFontInfo() ... XftFontOpenPattern() ... getAllCarbonLazyValues2000() -> new()
MemoryIgnoreLeaksBlock __;
#endif
if(lastStdFont != AStdFont.AsInt64()) {
lastFiFont = INT_MIN;
lastStdFont = AStdFont.AsInt64();
}
if(AsInt64() == lastFiFont)
return lastFontInfo;
lastFontInfo = GetFontInfo(*this);
lastFiFont = AsInt64();
return lastFontInfo;
}
FontInfo Font::Info() const
{
FontInfo h;
h.font = *this;
return h;
}
END_UPP_NAMESPACE

View file

@ -1,241 +1,242 @@
#include "Draw.h"
#ifdef PLATFORM_POSIX
#include <fontconfig/fontconfig.h>
#include <fontconfig/fcfreetype.h>
#endif
NAMESPACE_UPP
#ifdef PLATFORM_POSIX
#define LLOG(x) // LOG(x)
#define LTIMING(x) // TIMING(x)
void GetStdFontSys(String& name, int& height)
{
name = "xxxx";
}
static FT_Library sFTlib;
bool sInitFt(void)
{
if(sFTlib)
return true;
return FT_Init_FreeType(&sFTlib) == 0;
}
FcPattern *CreateFcPattern(Font font)
{
LTIMING("CreateXftFont");
double sina, cosa;
int hg = abs(font.GetHeight());
if(hg == 0) hg = 10;
String face = font.GetFaceName();
FcPattern *p = FcPatternCreate();
FcPatternAddString(p, FC_FAMILY, (FcChar8*)~face);
FcPatternAddInteger(p, FC_SLANT, font.IsItalic() ? 110 : 0);
FcPatternAddInteger(p, FC_PIXEL_SIZE, hg);
FcPatternAddInteger(p, FC_WEIGHT, font.IsBold() ? 200 : 100);
FcPatternAddBool(p, FC_MINSPACE, 1);
FcConfigSubstitute(0, p, FcMatchPattern);
FcDefaultSubstitute(p);
FcResult result;
FcPattern *m = FcFontMatch(0, p, &result);
FcPatternDestroy(p);
return m;
}
FT_Face CreateFTFace(const FcPattern *pattern, String *rpath) {
FT_Face face = NULL;
int id;
double dsize;
double aspect;
FcChar8 *filename;
if(!sInitFt())
return NULL;
if(FcPatternGetString(pattern, FC_FILE, 0, &filename) != FcResultMatch)
return NULL;
if(rpath)
*rpath = (const char *)filename;
if(FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &dsize) != FcResultMatch)
dsize = 16;
if (FcPatternGetDouble(pattern, FC_ASPECT, 0, &aspect) != FcResultMatch)
aspect = 1.0;
FT_F26Dot6 ysize = (FT_F26Dot6) (dsize * 64.0);
FT_F26Dot6 xsize = (FT_F26Dot6) (dsize * aspect * 64.0);
if(FT_New_Face(sFTlib, (const char *)filename, 0, &face))
return NULL;
FT_Set_Char_Size(face, xsize, ysize, 0, 0);
return face;
}
#define FONTCACHE 37
struct FtFaceEntry {
Font font;
FT_Face face;
String path;
};
static FtFaceEntry ft_cache[FONTCACHE];
void ClearFtFaceCache()
{
for(int i = 0; i < FONTCACHE; i++)
ft_cache[i].font.Height(-30000);
}
FT_Face (*FTFaceXft)(Font fnt, String *rpath);
FT_Face FTFace(Font fnt, String *rpath = NULL)
{
LTIMING("FTFace");
if(FTFaceXft)
return (*FTFaceXft)(fnt, rpath);
ONCELOCK {
ClearFtFaceCache();
}
FtFaceEntry be;
be = ft_cache[0];
for(int i = 0; i < FONTCACHE; i++) {
FtFaceEntry e = ft_cache[i];
if(i)
ft_cache[i] = be;
if(e.font == fnt) {
if(rpath)
*rpath = e.path;
if(i)
ft_cache[0] = e;
return e.face;
}
be = e;
}
LTIMING("FTFace2");
if(be.face) {
LLOG("Removing " << be.font << " - " << (void *)be.face);
FT_Done_Face(be.face);
}
be.font = fnt;
FcPattern *p = CreateFcPattern(fnt);
be.face = CreateFTFace(p, &be.path);
FcPatternDestroy(p);
ft_cache[0] = be;
if(rpath)
*rpath = be.path;
return be.face;
}
CommonFontInfo (*GetFontInfoSysXft)(Font font);
CommonFontInfo GetFontInfoSys(Font font)
{
if(GetFontInfoSysXft)
return (*GetFontInfoSysXft)(font);
CommonFontInfo fi;
String path;
FT_Face face = FTFace(font, &path);
if(face) {
fi.ascent = face->size->metrics.ascender >> 6;
fi.descent = -(face->size->metrics.descender >> 6);
fi.height = fi.ascent + fi.descent;
fi.lineheight = face->size->metrics.height >> 6;
fi.external = 0;
fi.internal = 0;
fi.overhang = 0;
fi.maxwidth = face->size->metrics.max_advance >> 6;
fi.avewidth = fi.maxwidth;
fi.default_char = '?';
fi.fixedpitch = font.GetFaceInfo() & Font::FIXEDPITCH;
if(path.GetCount() < 250)
strcpy(fi.path, ~path);
else
*fi.path = 0;
}
return fi;
}
#define FLOOR(x) ((x) & -64)
#define CEIL(x) (((x)+63) & -64)
#define TRUNC(x) ((x) >> 6)
#define ROUND(x) (((x)+32) & -64)
GlyphInfo (*GetGlyphInfoSysXft)(Font font, int chr);
GlyphInfo GetGlyphInfoSys(Font font, int chr)
{
LTIMING("GetGlyphInfoSys");
GlyphInfo gi;
FT_Face face = FTFace(font, NULL);
gi.lspc = gi.rspc = 0;
gi.width = 0x8000;
if(face) {
LTIMING("GetGlyphInfoSys 2");
int glyph_index = FT_Get_Char_Index(face, chr);
if(glyph_index) {
if(GetGlyphInfoSysXft)
return (*GetGlyphInfoSysXft)(font, chr);
if(FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT|FT_LOAD_NO_BITMAP) == 0 ||
FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT) == 0) {
FT_Glyph_Metrics& m = face->glyph->metrics;
int left = FLOOR(m.horiBearingX);
int width = TRUNC(CEIL(m.horiBearingX + m.width) - left);
gi.width = TRUNC(ROUND(face->glyph->advance.x));
gi.lspc = TRUNC(left);
gi.rspc = gi.width - width - gi.lspc;
}
}
}
return gi;
}
Vector<FaceInfo> GetAllFacesSys()
{
static const char *basic_fonts[] = {
"sans-serif",
"serif",
"sans-serif",
"monospace",
};
Vector<FaceInfo> list;
for(int i = 0; i < __countof(basic_fonts); i++) {
FaceInfo& fi = list.Add();
fi.name = basic_fonts[i];
fi.info = (i == 3) ? Font::SCALEABLE|Font::FIXEDPITCH : Font::SCALEABLE;
}
FcPattern *p = FcPatternCreate();
FcObjectSet *os = FcObjectSetBuild(FC_FAMILY, FC_SPACING, FC_SCALABLE, (void *)0);
FcFontSet *fs = FcFontList(NULL, p, os);
FcPatternDestroy(p);
FcObjectSetDestroy(os);
for(int i = 0; i < fs->nfont; i++) {
FcChar8 *family = NULL;
if(FcPatternGetString(fs->fonts[i], FC_FAMILY, 0, &family) == 0 && family) {
FaceInfo& fi = list.Add();
fi.name = (const char *)family;
fi.info = 0;
int iv;
if(FcPatternGetInteger(fs->fonts[i], FC_SPACING, 0, &iv) == 0 && iv == FC_MONO)
fi.info |= Font::FIXEDPITCH;
FcBool bv;
if(FcPatternGetBool(fs->fonts[i], FC_SCALABLE, 0, &bv) == 0 && bv)
fi.info |= Font::SCALEABLE;
}
}
FcFontSetDestroy(fs);
return list;
}
#endif
END_UPP_NAMESPACE
#include "Draw.h"
#ifdef PLATFORM_POSIX
#include <fontconfig/fontconfig.h>
#include <fontconfig/fcfreetype.h>
#endif
NAMESPACE_UPP
#ifdef PLATFORM_POSIX
#define LLOG(x) // LOG(x)
#define LTIMING(x) // TIMING(x)
void GetStdFontSys(String& name, int& height)
{
name = "xxxx";
}
static FT_Library sFTlib;
bool sInitFt(void)
{
if(sFTlib)
return true;
return FT_Init_FreeType(&sFTlib) == 0;
}
FcPattern *CreateFcPattern(Font font)
{
LTIMING("CreateXftFont");
double sina, cosa;
int hg = abs(font.GetHeight());
if(hg == 0) hg = 10;
String face = font.GetFaceName();
FcPattern *p = FcPatternCreate();
FcPatternAddString(p, FC_FAMILY, (FcChar8*)~face);
FcPatternAddInteger(p, FC_SLANT, font.IsItalic() ? 110 : 0);
FcPatternAddInteger(p, FC_PIXEL_SIZE, hg);
FcPatternAddInteger(p, FC_WEIGHT, font.IsBold() ? 200 : 100);
FcPatternAddBool(p, FC_MINSPACE, 1);
FcConfigSubstitute(0, p, FcMatchPattern);
FcDefaultSubstitute(p);
FcResult result;
FcPattern *m = FcFontMatch(0, p, &result);
FcPatternDestroy(p);
return m;
}
FT_Face CreateFTFace(const FcPattern *pattern, String *rpath) {
FT_Face face = NULL;
int id;
double dsize;
double aspect;
FcChar8 *filename;
if(!sInitFt())
return NULL;
if(FcPatternGetString(pattern, FC_FILE, 0, &filename) != FcResultMatch)
return NULL;
if(rpath)
*rpath = (const char *)filename;
if(FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &dsize) != FcResultMatch)
dsize = 16;
if (FcPatternGetDouble(pattern, FC_ASPECT, 0, &aspect) != FcResultMatch)
aspect = 1.0;
FT_F26Dot6 ysize = (FT_F26Dot6) (dsize * 64.0);
FT_F26Dot6 xsize = (FT_F26Dot6) (dsize * aspect * 64.0);
if(FT_New_Face(sFTlib, (const char *)filename, 0, &face))
return NULL;
FT_Set_Char_Size(face, xsize, ysize, 0, 0);
return face;
}
#define FONTCACHE 37
struct FtFaceEntry {
Font font;
FT_Face face;
String path;
};
static FtFaceEntry ft_cache[FONTCACHE];
void ClearFtFaceCache()
{
for(int i = 0; i < FONTCACHE; i++)
ft_cache[i].font.Height(-30000);
}
FT_Face (*FTFaceXft)(Font fnt, String *rpath);
FT_Face FTFace(Font fnt, String *rpath = NULL)
{
LTIMING("FTFace");
if(FTFaceXft)
return (*FTFaceXft)(fnt, rpath);
ONCELOCK {
ClearFtFaceCache();
}
FtFaceEntry be;
be = ft_cache[0];
for(int i = 0; i < FONTCACHE; i++) {
FtFaceEntry e = ft_cache[i];
if(i)
ft_cache[i] = be;
if(e.font == fnt) {
if(rpath)
*rpath = e.path;
if(i)
ft_cache[0] = e;
return e.face;
}
be = e;
}
LTIMING("FTFace2");
if(be.face) {
LLOG("Removing " << be.font << " - " << (void *)be.face);
FT_Done_Face(be.face);
}
be.font = fnt;
FcPattern *p = CreateFcPattern(fnt);
be.face = CreateFTFace(p, &be.path);
FcPatternDestroy(p);
ft_cache[0] = be;
if(rpath)
*rpath = be.path;
return be.face;
}
CommonFontInfo (*GetFontInfoSysXft)(Font font);
CommonFontInfo GetFontInfoSys(Font font)
{
sInitFt();
if(GetFontInfoSysXft)
return (*GetFontInfoSysXft)(font);
CommonFontInfo fi;
String path;
FT_Face face = FTFace(font, &path);
if(face) {
fi.ascent = face->size->metrics.ascender >> 6;
fi.descent = -(face->size->metrics.descender >> 6);
fi.height = fi.ascent + fi.descent;
fi.lineheight = face->size->metrics.height >> 6;
fi.external = 0;
fi.internal = 0;
fi.overhang = 0;
fi.maxwidth = face->size->metrics.max_advance >> 6;
fi.avewidth = fi.maxwidth;
fi.default_char = '?';
fi.fixedpitch = font.GetFaceInfo() & Font::FIXEDPITCH;
if(path.GetCount() < 250)
strcpy(fi.path, ~path);
else
*fi.path = 0;
}
return fi;
}
#define FLOOR(x) ((x) & -64)
#define CEIL(x) (((x)+63) & -64)
#define TRUNC(x) ((x) >> 6)
#define ROUND(x) (((x)+32) & -64)
GlyphInfo (*GetGlyphInfoSysXft)(Font font, int chr);
GlyphInfo GetGlyphInfoSys(Font font, int chr)
{
LTIMING("GetGlyphInfoSys");
GlyphInfo gi;
FT_Face face = FTFace(font, NULL);
gi.lspc = gi.rspc = 0;
gi.width = 0x8000;
if(face) {
LTIMING("GetGlyphInfoSys 2");
int glyph_index = FT_Get_Char_Index(face, chr);
if(glyph_index) {
if(GetGlyphInfoSysXft)
return (*GetGlyphInfoSysXft)(font, chr);
if(FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT|FT_LOAD_NO_BITMAP) == 0 ||
FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT) == 0) {
FT_Glyph_Metrics& m = face->glyph->metrics;
int left = FLOOR(m.horiBearingX);
int width = TRUNC(CEIL(m.horiBearingX + m.width) - left);
gi.width = TRUNC(ROUND(face->glyph->advance.x));
gi.lspc = TRUNC(left);
gi.rspc = gi.width - width - gi.lspc;
}
}
}
return gi;
}
Vector<FaceInfo> GetAllFacesSys()
{
static const char *basic_fonts[] = {
"sans-serif",
"serif",
"sans-serif",
"monospace",
};
Vector<FaceInfo> list;
for(int i = 0; i < __countof(basic_fonts); i++) {
FaceInfo& fi = list.Add();
fi.name = basic_fonts[i];
fi.info = (i == 3) ? Font::SCALEABLE|Font::FIXEDPITCH : Font::SCALEABLE;
}
FcPattern *p = FcPatternCreate();
FcObjectSet *os = FcObjectSetBuild(FC_FAMILY, FC_SPACING, FC_SCALABLE, (void *)0);
FcFontSet *fs = FcFontList(NULL, p, os);
FcPatternDestroy(p);
FcObjectSetDestroy(os);
for(int i = 0; i < fs->nfont; i++) {
FcChar8 *family = NULL;
if(FcPatternGetString(fs->fonts[i], FC_FAMILY, 0, &family) == 0 && family) {
FaceInfo& fi = list.Add();
fi.name = (const char *)family;
fi.info = 0;
int iv;
if(FcPatternGetInteger(fs->fonts[i], FC_SPACING, 0, &iv) == 0 && iv == FC_MONO)
fi.info |= Font::FIXEDPITCH;
FcBool bv;
if(FcPatternGetBool(fs->fonts[i], FC_SCALABLE, 0, &bv) == 0 && bv)
fi.info |= Font::SCALEABLE;
}
}
FcFontSetDestroy(fs);
return list;
}
#endif
END_UPP_NAMESPACE