📄 platgtk.cxx.svn-base
字号:
* If one font is the same as another, its hash will be the same, but if the hash is the
* same then they may still be different.
*/
static int HashFont(const char *faceName, int characterSet, int size, bool bold, bool italic) {
return
size ^
(characterSet << 10) ^
(bold ? 0x10000000 : 0) ^
(italic ? 0x20000000 : 0) ^
faceName[0];
}
class FontCached : Font {
FontCached *next;
int usage;
LOGFONT lf;
int hash;
FontCached(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_);
~FontCached() {}
bool SameAs(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_);
virtual void Release();
static FontID CreateNewFont(const char *fontName, int characterSet,
int size, bool bold, bool italic);
static FontCached *first;
public:
static FontID FindOrCreate(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_);
static void ReleaseId(FontID id_);
};
FontCached *FontCached::first = 0;
FontCached::FontCached(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_) :
next(0), usage(0), hash(0) {
::SetLogFont(lf, faceName_, characterSet_, size_, bold_, italic_);
hash = HashFont(faceName_, characterSet_, size_, bold_, italic_);
id = CreateNewFont(faceName_, characterSet_, size_, bold_, italic_);
usage = 1;
}
bool FontCached::SameAs(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_) {
return
lf.size == size_ &&
lf.bold == bold_ &&
lf.italic == italic_ &&
lf.characterSet == characterSet_ &&
0 == strcmp(lf.faceName, faceName_);
}
void FontCached::Release() {
if (id)
delete PFont(*this);
id = 0;
}
FontID FontCached::FindOrCreate(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_) {
FontID ret = 0;
FontMutexLock();
int hashFind = HashFont(faceName_, characterSet_, size_, bold_, italic_);
for (FontCached *cur = first; cur; cur = cur->next) {
if ((cur->hash == hashFind) &&
cur->SameAs(faceName_, characterSet_, size_, bold_, italic_)) {
cur->usage++;
ret = cur->id;
}
}
if (ret == 0) {
FontCached *fc = new FontCached(faceName_, characterSet_, size_, bold_, italic_);
if (fc) {
fc->next = first;
first = fc;
ret = fc->id;
}
}
FontMutexUnlock();
return ret;
}
void FontCached::ReleaseId(FontID id_) {
FontMutexLock();
FontCached **pcur = &first;
for (FontCached *cur = first; cur; cur = cur->next) {
if (cur->id == id_) {
cur->usage--;
if (cur->usage == 0) {
*pcur = cur->next;
cur->Release();
cur->next = 0;
delete cur;
}
break;
}
pcur = &cur->next;
}
FontMutexUnlock();
}
static GdkFont *LoadFontOrSet(const char *fontspec, int characterSet) {
if (IsDBCSCharacterSet(characterSet)) {
return gdk_fontset_load(fontspec);
} else {
return gdk_font_load(fontspec);
}
}
FontID FontCached::CreateNewFont(const char *fontName, int characterSet,
int size, bool bold, bool italic) {
char fontset[1024];
char fontspec[300];
char foundary[50];
char faceName[100];
char charset[50];
fontset[0] = '\0';
fontspec[0] = '\0';
foundary[0] = '\0';
faceName[0] = '\0';
charset[0] = '\0';
#ifdef USE_PANGO
if (fontName[0] == '!') {
PangoFontDescription *pfd = pango_font_description_new();
if (pfd) {
pango_font_description_set_family(pfd, fontName+1);
pango_font_description_set_size(pfd, size * PANGO_SCALE);
pango_font_description_set_weight(pfd, bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL);
pango_font_description_set_style(pfd, italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL);
return new FontHandle(pfd, characterSet);
}
}
#endif
GdkFont *newid = 0;
// If name of the font begins with a '-', assume, that it is
// a full fontspec.
if (fontName[0] == '-') {
if (strchr(fontName, ',') || IsDBCSCharacterSet(characterSet)) {
newid = gdk_fontset_load(fontName);
} else {
newid = gdk_font_load(fontName);
}
if (!newid) {
// Font not available so substitute a reasonable code font
// iso8859 appears to only allow western characters.
newid = LoadFontOrSet("-*-*-*-*-*-*-*-*-*-*-*-*-iso8859-*",
characterSet);
}
return new FontHandle(newid);
}
// it's not a full fontspec, build one.
// This supports creating a FONT_SET
// in a method that allows us to also set size, slant and
// weight for the fontset. The expected input is multiple
// partial fontspecs seperated by comma
// eg. adobe-courier-iso10646-1,*-courier-iso10646-1,*-*-*-*
if (strchr(fontName, ',')) {
// build a fontspec and use gdk_fontset_load
int remaining = sizeof(fontset);
char fontNameCopy[1024];
strncpy(fontNameCopy, fontName, sizeof(fontNameCopy) - 1);
char *fn = fontNameCopy;
char *fp = strchr(fn, ',');
for (;;) {
const char *spec = "%s%s%s%s-*-*-*-%0d-*-*-*-*-%s";
if (fontset[0] != '\0') {
// if this is not the first font in the list,
// append a comma seperator
spec = ",%s%s%s%s-*-*-*-%0d-*-*-*-*-%s";
}
if (fp)
*fp = '\0'; // nullify the comma
GenerateFontSpecStrings(fn, characterSet,
foundary, sizeof(foundary),
faceName, sizeof(faceName),
charset, sizeof(charset));
snprintf(fontspec,
sizeof(fontspec) - 1,
spec,
foundary, faceName,
bold ? "-bold" : "-medium",
italic ? "-i" : "-r",
size * 10,
charset);
// if this is the first font in the list, and
// we are doing italic, add an oblique font
// to the list
if (italic && fontset[0] == '\0') {
strncat(fontset, fontspec, remaining - 1);
remaining -= strlen(fontset);
snprintf(fontspec,
sizeof(fontspec) - 1,
",%s%s%s-o-*-*-*-%0d-*-*-*-*-%s",
foundary, faceName,
bold ? "-bold" : "-medium",
size * 10,
charset);
}
strncat(fontset, fontspec, remaining - 1);
remaining -= strlen(fontset);
if (!fp)
break;
fn = fp + 1;
fp = strchr(fn, ',');
}
newid = gdk_fontset_load(fontset);
if (newid)
return new FontHandle(newid);
// if fontset load failed, fall through, we'll use
// the last font entry and continue to try and
// get something that matches
}
// single fontspec support
GenerateFontSpecStrings(fontName, characterSet,
foundary, sizeof(foundary),
faceName, sizeof(faceName),
charset, sizeof(charset));
snprintf(fontspec,
sizeof(fontspec) - 1,
"%s%s%s%s-*-*-*-%0d-*-*-*-*-%s",
foundary, faceName,
bold ? "-bold" : "-medium",
italic ? "-i" : "-r",
size * 10,
charset);
newid = LoadFontOrSet(fontspec, characterSet);
if (!newid) {
// some fonts have oblique, not italic
snprintf(fontspec,
sizeof(fontspec) - 1,
"%s%s%s%s-*-*-*-%0d-*-*-*-*-%s",
foundary, faceName,
bold ? "-bold" : "-medium",
italic ? "-o" : "-r",
size * 10,
charset);
newid = LoadFontOrSet(fontspec, characterSet);
}
if (!newid) {
snprintf(fontspec,
sizeof(fontspec) - 1,
"-*-*-*-*-*-*-*-%0d-*-*-*-*-%s",
size * 10,
charset);
newid = gdk_font_load(fontspec);
}
if (!newid) {
// Font not available so substitute a reasonable code font
// iso8859 appears to only allow western characters.
newid = LoadFontOrSet("-*-*-*-*-*-*-*-*-*-*-*-*-iso8859-*",
characterSet);
}
return new FontHandle(newid);
}
Font::Font() : id(0) {}
Font::~Font() {}
void Font::Create(const char *faceName, int characterSet, int size,
bool bold, bool italic, bool) {
Release();
id = FontCached::FindOrCreate(faceName, characterSet, size, bold, italic);
}
void Font::Release() {
if (id)
FontCached::ReleaseId(id);
id = 0;
}
class SurfaceImpl : public Surface {
encodingType et;
GdkDrawable *drawable;
GdkGC *gc;
GdkPixmap *ppixmap;
int x;
int y;
bool inited;
bool createdGC;
#ifdef USE_PANGO
PangoContext *pcontext;
PangoLayout *layout;
Converter conv;
int characterSet;
void SetConverter(int characterSet_);
#endif
public:
SurfaceImpl();
virtual ~SurfaceImpl();
void Init(WindowID wid);
void Init(SurfaceID sid, WindowID wid);
void InitPixMap(int width, int height, Surface *surface_, WindowID wid);
void Release();
bool Initialised();
void PenColour(ColourAllocated fore);
int LogPixelsY();
int DeviceHeightFont(int points);
void MoveTo(int x_, int y_);
void LineTo(int x_, int y_);
void Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back);
void RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back);
void FillRectangle(PRectangle rc, ColourAllocated back);
void FillRectangle(PRectangle rc, Surface &surfacePattern);
void RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back);
void AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill,
ColourAllocated outline, int alphaOutline, int flags);
void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back);
void Copy(PRectangle rc, Point from, Surface &surfaceSource);
void DrawTextBase(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore);
void DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
void DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
void DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore);
void MeasureWidths(Font &font_, const char *s, int len, int *positions);
int WidthText(Font &font_, const char *s, int len);
int WidthChar(Font &font_, char ch);
int Ascent(Font &font_);
int Descent(Font &font_);
int InternalLeading(Font &font_);
int ExternalLeading(Font &font_);
int Height(Font &font_);
int AverageCharWidth(Font &font_);
int SetPalette(Palette *pal, bool inBackGround);
void SetClip(PRectangle rc);
void FlushCachedState();
void SetUnicodeMode(bool unicodeMode_);
void SetDBCSMode(int codePage);
};
const char *CharacterSetID(int characterSet) {
switch (characterSet) {
case SC_CHARSET_ANSI:
return "";
case SC_CHARSET_DEFAULT:
return "ISO-8859-1";
case SC_CHARSET_BALTIC:
return "ISO-8859-13";
case SC_CHARSET_CHINESEBIG5:
return "BIG-5";
case SC_CHARSET_EASTEUROPE:
return "ISO-8859-2";
case SC_CHARSET_GB2312:
return "GB2312";
case SC_CHARSET_GREEK:
return "ISO-8859-7";
case SC_CHARSET_HANGUL:
return "";
case SC_CHARSET_MAC:
return "MACINTOSH";
case SC_CHARSET_OEM:
return "ASCII";
case SC_CHARSET_RUSSIAN:
return "KOI8-R";
case SC_CHARSET_CYRILLIC:
return "CP1251";
case SC_CHARSET_SHIFTJIS:
return "SHIFT-JIS";
case SC_CHARSET_SYMBOL:
return "";
case SC_CHARSET_TURKISH:
return "ISO-8859-9";
case SC_CHARSET_JOHAB:
return "JOHAB";
case SC_CHARSET_HEBREW:
return "ISO-8859-8";
case SC_CHARSET_ARABIC:
return "ISO-8859-6";
case SC_CHARSET_VIETNAMESE:
return "";
case SC_CHARSET_THAI:
return "ISO-8859-11";
case SC_CHARSET_8859_15:
return "ISO-8859-15";
default:
return "";
}
}
#ifdef USE_PANGO
void SurfaceImpl::SetConverter(int characterSet_) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -