📄 platgtk.cxx
字号:
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) {
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;
iconv_t iconvh;
int characterSet;
void SetIconv(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 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);
};
#ifdef USE_PANGO
const char *CharacterSetID(int characterSet) {
switch (characterSet) {
case SC_CHARSET_ANSI:
return "";
case SC_CHARSET_DEFAULT:
return "LATIN1";
case SC_CHARSET_BALTIC:
return "BALTIC";
case SC_CHARSET_CHINESEBIG5:
return "BIG-5";
case SC_CHARSET_EASTEUROPE:
return "ISO8859-2";
case SC_CHARSET_GB2312:
return "GB2312";
case SC_CHARSET_GREEK:
return "ISO8859-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_SHIFTJIS:
return "SHIFT-JIS";
case SC_CHARSET_SYMBOL:
return "";
case SC_CHARSET_TURKISH:
return "ISO8859-9";
case SC_CHARSET_JOHAB:
return "JOHAB";
case SC_CHARSET_HEBREW:
return "ISO8859-8";
case SC_CHARSET_ARABIC:
return "ISO8859-6";
case SC_CHARSET_VIETNAMESE:
return "";
case SC_CHARSET_THAI:
return "ISO8859-1";
default:
return "";
}
}
void SurfaceImpl::SetIconv(int characterSet_) {
if (characterSet != characterSet_) {
if (iconvh != iconvhBad)
iconv_close(iconvh);
iconvh = iconvhBad;
characterSet = characterSet_;
const char *source = CharacterSetID(characterSet);
if (*source) {
iconvh = iconv_open("UTF8", source);
}
}
}
#endif
SurfaceImpl::SurfaceImpl() : et(singleByte), drawable(0), gc(0), ppixmap(0),
x(0), y(0), inited(false), createdGC(false)
#ifdef USE_PANGO
, pcontext(0), layout(0), iconvh(iconvhBad), characterSet(-1)
#endif
{
}
SurfaceImpl::~SurfaceImpl() {
Release();
}
void SurfaceImpl::Release() {
et = singleByte;
drawable = 0;
if (createdGC) {
createdGC = false;
gdk_gc_unref(gc);
}
gc = 0;
if (ppixmap)
gdk_pixmap_unref(ppixmap);
ppixmap = 0;
#ifdef USE_PANGO
if (layout)
g_object_unref(layout);
layout = 0;
if (pcontext)
g_object_unref(pcontext);
pcontext = 0;
if (iconvh != iconvhBad)
iconv_close(iconvh);
iconvh = iconvhBad;
characterSet = -1;
#endif
x = 0;
y = 0;
inited = false;
createdGC = false;
}
bool SurfaceImpl::Initialised() {
return inited;
}
// The WindowID argument is only used for Pango builds
#ifdef USE_PANGO
#define WID_NAME wid
#else
#define WID_NAME
#endif
void SurfaceImpl::Init(WindowID WID_NAME) {
Release();
#ifdef USE_PANGO
PLATFORM_ASSERT(wid);
pcontext = gtk_widget_create_pango_context(PWidget(wid));
PLATFORM_ASSERT(pcontext);
layout = pango_layout_new(pcontext);
PLATFORM_ASSERT(layout);
#endif
inited = true;
}
void SurfaceImpl::Init(SurfaceID sid, WindowID WID_NAME) {
PLATFORM_ASSERT(sid);
GdkDrawable *drawable_ = reinterpret_cast<GdkDrawable *>(sid);
Release();
#ifdef USE_PANGO
PLATFORM_ASSERT(wid);
pcontext = gtk_widget_create_pango_context(PWidget(wid));
layout = pango_layout_new(pcontext);
#endif
drawable = drawable_;
gc = gdk_gc_new(drawable_);
createdGC = true;
inited = true;
}
void SurfaceImpl::InitPixMap(int width, int height, Surface *surface_, WindowID WID_NAME) {
PLATFORM_ASSERT(surface_);
Release();
SurfaceImpl *surfImpl = static_cast<SurfaceImpl *>(surface_);
PLATFORM_ASSERT(surfImpl->drawable);
#ifdef USE_PANGO
PLATFORM_ASSERT(wid);
pcontext = gtk_widget_create_pango_context(PWidget(wid));
PLATFORM_ASSERT(pcontext);
layout = pango_layout_new(pcontext);
PLATFORM_ASSERT(layout);
#endif
if (height > 0 && width > 0)
ppixmap = gdk_pixmap_new(surfImpl->drawable, width, height, -1);
drawable = ppixmap;
gc = gdk_gc_new(surfImpl->drawable);
createdGC = true;
inited = true;
}
void SurfaceImpl::PenColour(ColourAllocated fore) {
if (gc) {
GdkColor co;
co.pixel = fore.AsLong();
gdk_gc_set_foreground(gc, &co);
}
}
int SurfaceImpl::LogPixelsY() {
return 72;
}
int SurfaceImpl::DeviceHeightFont(int points) {
int logPix = LogPixelsY();
return (points * logPix + logPix / 2) / 72;
}
void SurfaceImpl::MoveTo(int x_, int y_) {
x = x_;
y = y_;
}
void SurfaceImpl::LineTo(int x_, int y_) {
if (drawable && gc) {
gdk_draw_line(drawable, gc,
x, y,
x_, y_);
}
x = x_;
y = y_;
}
void SurfaceImpl::Polygon(Point *pts, int npts, ColourAllocated fore,
ColourAllocated back) {
GdkPoint gpts[20];
if (npts < static_cast<int>((sizeof(gpts) / sizeof(gpts[0])))) {
for (int i = 0;i < npts;i++) {
gpts[i].x = pts[i].x;
gpts[i].y = pts[i].y;
}
PenColour(back);
gdk_draw_polygon(drawable, gc, 1, gpts, npts);
PenColour(fore);
gdk_draw_polygon(drawable, gc, 0, gpts, npts);
}
}
void SurfaceImpl::RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
if (gc && drawable) {
PenColour(back);
gdk_draw_rectangle(drawable, gc, 1,
rc.left + 1, rc.top + 1,
rc.right - rc.left - 2, rc.bottom - rc.top - 2);
PenColour(fore);
// The subtraction of 1 off the width and height here shouldn't be needed but
// otherwise a different rectangle is drawn than would be done if the fill parameter == 1
gdk_draw_rectangle(drawable, gc, 0,
rc.left, rc.top,
rc.right - rc.left - 1, rc.bottom - rc.top - 1);
}
}
void SurfaceImpl::FillRectangle(PRectangle rc, ColourAllocated back) {
PenColour(back);
if (drawable && (rc.left < maxCoordinate)) { // Protect against out of range
gdk_draw_rectangle(drawable, gc, 1,
rc.left, rc.top,
rc.right - rc.left, rc.bottom - rc.top);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -