aboutsummaryrefslogtreecommitdiffhomepage
path: root/gtk
diff options
context:
space:
mode:
Diffstat (limited to 'gtk')
-rw-r--r--gtk/PlatGTK.cxx551
-rw-r--r--gtk/ScintillaGTK.cxx10
2 files changed, 390 insertions, 171 deletions
diff --git a/gtk/PlatGTK.cxx b/gtk/PlatGTK.cxx
index 0a84f46a1..073e51faa 100644
--- a/gtk/PlatGTK.cxx
+++ b/gtk/PlatGTK.cxx
@@ -7,6 +7,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
+#define assert(c) ((c) ? (void)(0) : Platform::Assert(#c, __FILE__, __LINE__))
#include <glib.h>
#include <gdk/gdk.h>
@@ -34,11 +35,50 @@
#define snprintf _snprintf
#endif
+#if GTK_MAJOR_VERSION >= 2
+#define USE_PANGO 1
+#endif
+
#ifdef _MSC_VER
// Ignore unreferenced local functions in GTK+ headers
#pragma warning(disable: 4505)
#endif
+// On GTK+ 1.x holds a GdkFont* but on GTK+ 2.x can hold a GdkFont* or a
+// PangoFontDescription*.
+class FontHandle {
+public:
+ int ascent;
+ GdkFont *pfont;
+#ifdef USE_PANGO
+ PangoFontDescription *pfd;
+#endif
+ FontHandle(GdkFont *pfont_) {
+ ascent = 0;
+ pfont = pfont_;
+#ifdef USE_PANGO
+ pfd = 0;
+#endif
+ }
+#ifdef USE_PANGO
+ FontHandle(PangoFontDescription *pfd_) {
+ ascent = 0;
+ pfont = 0;
+ pfd = pfd_;
+ }
+#endif
+ ~FontHandle() {
+ if (pfont)
+ gdk_font_unref(pfont);
+ pfont = 0;
+#ifdef USE_PANGO
+ if (pfd)
+ pango_font_description_free(pfd);
+ pfd = 0;
+#endif
+ }
+};
+
struct LOGFONT {
int size;
bool bold;
@@ -94,8 +134,8 @@ static void FontMutexUnlock() {
// X has a 16 bit coordinate space, so stop drawing here to avoid wrapping
static const int maxCoordinate = 32000;
-static GdkFont *PFont(Font &f) {
- return reinterpret_cast<GdkFont *>(f.GetID());
+static FontHandle *PFont(Font &f) {
+ return reinterpret_cast<FontHandle *>(f.GetID());
}
static GtkWidget *PWidget(WindowID id) {
@@ -350,7 +390,7 @@ bool FontCached::SameAs(const char *faceName_, int characterSet_, int size_, boo
void FontCached::Release() {
if (id)
- gdk_font_unref(PFont(*this));
+ delete PFont(*this);
id = 0;
}
@@ -396,7 +436,7 @@ void FontCached::ReleaseId(FontID id_) {
FontMutexUnlock();
}
-static FontID LoadFontOrSet(const char *fontspec, int characterSet) {
+static GdkFont *LoadFontOrSet(const char *fontspec, int characterSet) {
if (IsDBCSCharacterSet(characterSet)) {
return gdk_fontset_load(fontspec);
} else {
@@ -416,8 +456,21 @@ FontID FontCached::CreateNewFont(const char *fontName, int characterSet,
foundary[0] = '\0';
faceName[0] = '\0';
charset[0] = '\0';
- FontID newid = 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);
+ }
+ }
+#endif
+
+ GdkFont *newid = 0;
// If name of the font begins with a '-', assume, that it is
// a full fontspec.
if (fontName[0] == '-') {
@@ -432,7 +485,7 @@ FontID FontCached::CreateNewFont(const char *fontName, int characterSet,
newid = LoadFontOrSet("-*-*-*-*-*-*-*-*-*-*-*-*-iso8859-*",
characterSet);
}
- return newid;
+ return new FontHandle(newid);
}
// it's not a full fontspec, build one.
@@ -501,7 +554,7 @@ FontID FontCached::CreateNewFont(const char *fontName, int characterSet,
newid = gdk_fontset_load(fontset);
if (newid)
- return newid;
+ return new FontHandle(newid);
// if fontset load failed, fall through, we'll use
// the last font entry and continue to try and
@@ -550,7 +603,7 @@ FontID FontCached::CreateNewFont(const char *fontName, int characterSet,
newid = LoadFontOrSet("-*-*-*-*-*-*-*-*-*-*-*-*-iso8859-*",
characterSet);
}
- return newid;
+ return new FontHandle(newid);
}
Font::Font() : id(0) {}
@@ -578,13 +631,17 @@ class SurfaceImpl : public Surface {
int y;
bool inited;
bool createdGC;
+#ifdef USE_PANGO
+ PangoContext *pcontext;
+ PangoLayout *layout;
+#endif
public:
SurfaceImpl();
virtual ~SurfaceImpl();
- void Init();
- void Init(SurfaceID sid);
- void InitPixMap(int width, int height, Surface *surface_);
+ void Init(WindowID wid);
+ void Init(SurfaceID sid, WindowID wid);
+ void InitPixMap(int width, int height, Surface *surface_, WindowID wid);
void Release();
bool Initialised();
@@ -624,7 +681,11 @@ public:
};
SurfaceImpl::SurfaceImpl() : unicodeMode(false), dbcsMode(false), drawable(0), gc(0), ppixmap(0),
-x(0), y(0), inited(false), createdGC(false) {
+x(0), y(0), inited(false), createdGC(false)
+#ifdef USE_PANGO
+, pcontext(0), layout(0)
+#endif
+{
}
SurfaceImpl::~SurfaceImpl() {
@@ -641,6 +702,14 @@ void SurfaceImpl::Release() {
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;
+#endif
x = 0;
y = 0;
inited = false;
@@ -651,30 +720,56 @@ bool SurfaceImpl::Initialised() {
return inited;
}
-void SurfaceImpl::Init() {
+// 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) {
+ PLATFORM_ASSERT(wid);
Release();
+#ifdef USE_PANGO
+ 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) {
+void SurfaceImpl::Init(SurfaceID sid, WindowID WID_NAME) {
+ PLATFORM_ASSERT(wid);
+ PLATFORM_ASSERT(sid);
GdkDrawable *drawable_ = reinterpret_cast<GdkDrawable *>(sid);
Release();
+#ifdef USE_PANGO
+ pcontext = gtk_widget_create_pango_context(PWidget(wid));
+ layout = pango_layout_new(pcontext);
+#endif
drawable = drawable_;
gc = gdk_gc_new(drawable_);
- //gdk_gc_set_line_attributes(gc, 1,
- // GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_BEVEL);
createdGC = true;
inited = true;
}
-void SurfaceImpl::InitPixMap(int width, int height, Surface *surface_) {
+void SurfaceImpl::InitPixMap(int width, int height, Surface *surface_, WindowID WID_NAME) {
+ PLATFORM_ASSERT(wid);
+ PLATFORM_ASSERT(surface_);
Release();
+ SurfaceImpl *surfImpl = static_cast<SurfaceImpl *>(surface_);
+ PLATFORM_ASSERT(surfImpl->drawable);
+#ifdef USE_PANGO
+ 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(static_cast<SurfaceImpl *>(surface_)->drawable, width, height, -1);
+ ppixmap = gdk_pixmap_new(surfImpl->drawable, width, height, -1);
drawable = ppixmap;
- gc = gdk_gc_new(static_cast<SurfaceImpl *>(surface_)->drawable);
- //gdk_gc_set_line_attributes(gc, 1,
- // GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_BEVEL);
+ gc = gdk_gc_new(surfImpl->drawable);
createdGC = true;
inited = true;
}
@@ -821,77 +916,142 @@ void SurfaceImpl::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
}
}
-#define MAX_US_LEN 5000
+static size_t UTF8Len(char ch) {
+ unsigned char uch = static_cast<unsigned char>(ch);
+ if (uch < 0x80)
+ return 1;
+ else if (uch < (0x80 + 0x40 + 0x20))
+ return 2;
+ else
+ return 3;
+}
+
+#ifdef USE_PANGO
+
+static char *UTF8FromLatin1(const char *s, int len) {
+ char *utfForm = new char[len*2+1];
+ size_t lenU = 0;
+ for (int i=0;i<len;i++) {
+ unsigned int uch = static_cast<unsigned char>(s[i]);
+ if (uch < 0x80) {
+ utfForm[lenU++] = uch;
+ } else {
+ utfForm[lenU++] = static_cast<char>(0xC0 | (uch >> 6));
+ utfForm[lenU++] = static_cast<char>(0x80 | (uch & 0x3f));
+ }
+ }
+ utfForm[lenU] = '\0';
+ return utfForm;
+}
+
+static char *UTF8FromGdkWChar(GdkWChar *wctext, int wclen) {
+ char *utfForm = new char[wclen*3+1]; // Maximum of 3 UTF-8 bytes per character
+ size_t lenU = 0;
+ for (int i = 0; i < wclen && wctext[i]; i++) {
+ unsigned int uch = wctext[i];
+ if (uch < 0x80) {
+ utfForm[lenU++] = static_cast<char>(uch);
+ } else if (uch < 0x800) {
+ utfForm[lenU++] = static_cast<char>(0xC0 | (uch >> 6));
+ utfForm[lenU++] = static_cast<char>(0x80 | (uch & 0x3f));
+ } else {
+ utfForm[lenU++] = static_cast<char>(0xE0 | (uch >> 12));
+ utfForm[lenU++] = static_cast<char>(0x80 | ((uch >> 6) & 0x3f));
+ utfForm[lenU++] = static_cast<char>(0x80 | (uch & 0x3f));
+ }
+ }
+ utfForm[lenU] = '\0';
+ return utfForm;
+}
+
+static char *UTF8FromDBCS(const char *s, int len) {
+ GdkWChar *wctext = new GdkWChar[len + 1];
+ GdkWChar *wcp = wctext;
+ int wclen = gdk_mbstowcs(wcp, s, len);
+ if (wclen < 1) {
+ // In the annoying case when non-locale chars in the line.
+ // e.g. latin1 chars in Japanese locale.
+ delete []wctext;
+ return 0;
+ }
+
+ char *utfForm = UTF8FromGdkWChar(wctext, wclen);
+ delete []wctext;
+ return utfForm;
+}
+
+#endif
+
+// On GTK+, wchar_t is 4 bytes
+
+const int maxLengthTextRun = 10000;
void SurfaceImpl::DrawTextBase(PRectangle rc, Font &font_, int ybase, const char *s, int len,
ColourAllocated fore) {
PenColour(fore);
if (gc && drawable) {
- // Draw text as a series of segments to avoid limitations in X servers
- const int segmentLength = 1000;
int x = rc.left;
- if (unicodeMode) {
- GdkWChar wctext[MAX_US_LEN];
- GdkWChar *wcp = (GdkWChar *) & wctext;
- size_t wclen = UCS2FromUTF8(s, len, (wchar_t *)wctext,
- sizeof(wctext) / sizeof(GdkWChar) - 1);
- wctext[wclen] = L'\0';
- int lenDraw;
- while ((wclen > 0) && (x < maxCoordinate)) {
- lenDraw = Platform::Minimum(wclen, segmentLength);
- gdk_draw_text_wc(drawable, PFont(font_), gc,
- x, ybase, wcp, lenDraw);
- wclen -= lenDraw;
- if (wclen > 0) {
- x += gdk_text_width_wc(PFont(font_),
- wcp, lenDraw);
+#ifdef USE_PANGO
+ if (PFont(font_)->pfd) {
+ char *utfForm = 0;
+ if (unicodeMode) {
+ pango_layout_set_text(layout, s, len);
+ } else {
+ if (dbcsMode) {
+ // Convert to utf8
+ utfForm = UTF8FromDBCS(s, len);
}
- wcp += lenDraw;
+ if (!utfForm) // Latin1 or DBCS failed so treat as Latin1
+ utfForm = UTF8FromLatin1(s, len);
+ pango_layout_set_text(layout, utfForm, strlen(utfForm));
}
- } else if (dbcsMode) {
- GdkWChar wctext[MAX_US_LEN];
- GdkWChar *wcp = (GdkWChar *) & wctext;
- int wclen = gdk_mbstowcs(wcp, s, MAX_US_LEN);
-
- /* In the annoying case when non-locale chars
- * in the line.
- * e.g. latin1 chars in Japanese locale */
- if (wclen < 1) {
- while ((len > 0) && (x < maxCoordinate)) {
- int lenDraw = Platform::Minimum(len, segmentLength);
- gdk_draw_text(drawable, PFont(font_), gc,
- x, ybase, s, lenDraw);
- len -= lenDraw;
- if (len > 0) {
- x += gdk_text_width(PFont(font_), s, lenDraw);
- }
- s += lenDraw;
- }
- } else {
+ pango_layout_set_font_description(layout, PFont(font_)->pfd);
+ PangoLayoutLine *pll = pango_layout_get_line(layout,0);
+ gdk_draw_layout_line(drawable, gc, x, ybase, pll);
+ delete []utfForm;
+ return;
+ }
+#endif
+ // Draw text as a series of segments to avoid limitations in X servers
+ const int segmentLength = 1000;
+ bool draw8bit = true;
+ if (unicodeMode || dbcsMode) {
+ GdkWChar wctext[maxLengthTextRun];
+ int wclen;
+ if (unicodeMode) {
+ wclen = UCS2FromUTF8(s, len,
+ reinterpret_cast<wchar_t *>(wctext), maxLengthTextRun - 1);
+ } else { // dbcsMode, so convert using current locale
+ wclen = gdk_mbstowcs(
+ wctext, s, maxLengthTextRun - 1);
+ }
+ if (wclen > 0) {
+ draw8bit = false;
wctext[wclen] = L'\0';
- int lenDraw;
+ GdkWChar *wcp = wctext;
while ((wclen > 0) && (x < maxCoordinate)) {
- lenDraw = Platform::Minimum(wclen, segmentLength);
- gdk_draw_text_wc(drawable, PFont(font_), gc,
- x, ybase, wcp, lenDraw);
+ int lenDraw = Platform::Minimum(wclen, segmentLength);
+ gdk_draw_text_wc(drawable, PFont(font_)->pfont, gc,
+ x, ybase, wcp, lenDraw);
wclen -= lenDraw;
- if (wclen > 0) {
- x += gdk_text_width_wc(PFont(font_),
- wcp, lenDraw);
- }
wcp += lenDraw;
- }
+ if (wclen > 0) { // Avoid next calculation if possible as may be expensive
+ x += gdk_text_width_wc(PFont(font_)->pfont,
+ wcp, lenDraw);
+ }
+ }
}
- } else {
+ }
+ if (draw8bit) {
while ((len > 0) && (x < maxCoordinate)) {
int lenDraw = Platform::Minimum(len, segmentLength);
- gdk_draw_text(drawable, PFont(font_), gc,
+ gdk_draw_text(drawable, PFont(font_)->pfont, gc,
x, ybase, s, lenDraw);
len -= lenDraw;
- if (len > 0) {
- x += gdk_text_width(PFont(font_), s, lenDraw);
- }
s += lenDraw;
+ if (len > 0) { // Avoid next calculation if possible as may be expensive
+ x += gdk_text_width(PFont(font_)->pfont, s, lenDraw);
+ }
}
}
}
@@ -919,86 +1079,98 @@ void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, int ybase, con
void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positions) {
if (font_.GetID()) {
int totalWidth = 0;
- GdkFont *gf = PFont(font_);
- if (unicodeMode) {
- GdkWChar wctext[MAX_US_LEN];
- size_t wclen = UCS2FromUTF8(s, len, (wchar_t *)wctext, sizeof(wctext) / sizeof(GdkWChar) - 1);
- wctext[wclen] = L'\0';
- int poses[MAX_US_LEN];
- size_t i;
- for (i = 0; i < wclen; i++) {
- int width = gdk_char_width_wc(gf, wctext[i]);
- totalWidth += width;
- poses[i] = totalWidth;
- }
- // map widths back to utf-8 input string
- size_t ui = 0;
- i = 0;
- const unsigned char *us = reinterpret_cast<const unsigned char *>(s);
- unsigned char uch;
- while (ui < wclen) {
- uch = us[i];
- positions[i++] = poses[ui];
- if (uch >= 0x80) {
- if (uch < (0x80 + 0x40 + 0x20)) {
- positions[i++] = poses[ui];
- } else {
- positions[i++] = poses[ui];
- positions[i++] = poses[ui];
+#ifdef USE_PANGO
+ if (PFont(font_)->pfd) {
+ PangoRectangle pos;
+ pango_layout_set_font_description(layout, PFont(font_)->pfd);
+ if (unicodeMode) {
+ // Simple and direct as UTF-8 is native Pango encoding
+ pango_layout_set_text(layout, s, len);
+ int i = 0;
+ while (i < len) {
+ pango_layout_index_to_pos(layout, i+1, &pos);
+ positions[i++] = PANGO_PIXELS(pos.x);
+ }
+ } else {
+ int wclen = 0;
+ if (dbcsMode) {
+ GdkWChar *wctext = new GdkWChar[len + 1];
+ GdkWChar *wcp = wctext;
+ wclen = gdk_mbstowcs(wcp, s, len);
+ if (wclen >= 1 ) {
+ // Convert to UTF-8 so can ask Pango for widths, then
+ // Loop through UTF-8 and DBCS forms, taking account of different
+ // character byte lengths.
+ char *utfForm = UTF8FromGdkWChar(wctext, wclen);
+ pango_layout_set_text(layout, utfForm, strlen(utfForm));
+ int i = 0;
+ int iU = 0;
+ while (i < len) {
+ pango_layout_index_to_pos(layout, iU+1, &pos);
+ iU += UTF8Len(utfForm[iU]);
+ size_t lenChar = mblen(s+i, MB_CUR_MAX);
+ while (lenChar--) {
+ positions[i++] = PANGO_PIXELS(pos.x);
+ }
+ }
+ delete []utfForm;
}
+ delete []wctext;
+ }
+ if (wclen < 1 ) {
+ // Either Latin1 or DBCS conversion failed so treat as Latin1.
+ char *utfForm = UTF8FromLatin1(s, len);
+ pango_layout_set_text(layout, utfForm, strlen(utfForm));
+ int i = 0;
+ int iU = 0;
+ while (i < len) {
+ pango_layout_index_to_pos(layout, iU+1, &pos);
+ iU += UTF8Len(s[i]);
+ positions[i++] = PANGO_PIXELS(pos.x);
+ }
+ delete []utfForm;
}
- ui++;
}
- int lastPos = 0;
- if (i > 0)
- lastPos = positions[i - 1];
- while (i < static_cast<size_t>(len)) {
- positions[i++] = lastPos;
+ return;
+ }
+#endif
+ GdkFont *gf = PFont(font_)->pfont;
+ bool measure8bit = true;
+ if (unicodeMode || dbcsMode) {
+ GdkWChar wctext[maxLengthTextRun];
+ int wclen;
+ if (unicodeMode) {
+ wclen = UCS2FromUTF8(s, len,
+ reinterpret_cast<wchar_t *>(wctext), maxLengthTextRun - 1);
+ } else { // dbcsMode, so convert using current locale
+ wclen = gdk_mbstowcs(
+ wctext, s, maxLengthTextRun - 1);
}
- } else if (dbcsMode) {
- GdkWChar wctext[MAX_US_LEN];
- size_t wclen = (size_t)gdk_mbstowcs(wctext, s, MAX_US_LEN);
- /* In the annoying case when non-locale chars
- * in the line.
- * e.g. latin1 chars in Japanese locale */
- if( (int)wclen < 1 ) {
- for (int i = 0; i < len; i++) {
- int width = gdk_char_width(gf, s[i]);
- totalWidth += width;
- positions[i] = totalWidth;
- }
- } else {
+ if (wclen > 0) {
+ measure8bit = false;
wctext[wclen] = L'\0';
- int poses[MAX_US_LEN];
- size_t i;
- for (i = 0; i < wclen; i++) {
- int width = gdk_char_width_wc(gf, wctext[i]);
+ // Map widths back to utf-8 or DBCS input string
+ int i = 0;
+ for (int iU = 0; iU < wclen; iU++) {
+ int width = gdk_char_width_wc(gf, wctext[iU]);
totalWidth += width;
- poses[i] = totalWidth;
- }
- size_t ui = 0;
- i = 0;
- for (ui = 0; ui< wclen; ui++) {
- GdkWChar wch[2];
- wch[0] = wctext[ui];
- wch[1] = L'\0';
- gchar* mbstr = gdk_wcstombs(wch);
- if (mbstr == NULL || *mbstr == '\0')
- g_error("mbs broken\n");
- for(int j=0; j<(int)strlen(mbstr); j++) {
- positions[i++] = poses[ui];
+ size_t lenChar;
+ if (unicodeMode) {
+ lenChar = UTF8Len(s[i]);
+ } else {
+ lenChar = mblen(s+i, MB_CUR_MAX);
+ }
+ while (lenChar--) {
+ positions[i++] = totalWidth;
}
- if( mbstr != NULL )
- g_free(mbstr);
}
- int lastPos = 0;
- if (i > 0)
- lastPos = positions[i - 1];
- while (i < static_cast<size_t>(len)) {
- positions[i++] = lastPos;
+ while (i < len) { // In case of problems with lengths
+ positions[i++] = totalWidth;
}
}
- } else {
+ }
+ if (measure8bit) {
+ // Either Latin1 or conversion failed so treat as Latin1.
for (int i = 0; i < len; i++) {
int width = gdk_char_width(gf, s[i]);
totalWidth += width;
@@ -1006,6 +1178,7 @@ void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positi
}
}
} else {
+ // No font so return an ascending range of values
for (int i = 0; i < len; i++) {
positions[i] = i + 1;
}
@@ -1014,24 +1187,52 @@ void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positi
int SurfaceImpl::WidthText(Font &font_, const char *s, int len) {
if (font_.GetID()) {
+#ifdef USE_PANGO
+ if (PFont(font_)->pfd) {
+ char *utfForm = 0;
+ pango_layout_set_font_description(layout, PFont(font_)->pfd);
+ PangoRectangle pos;
+ if (unicodeMode) {
+ pango_layout_set_text(layout, s, len);
+ } else {
+ if (dbcsMode) {
+ // Convert to utf8
+ utfForm = UTF8FromDBCS(s, len);
+ }
+ if (!utfForm) // Latin1 or DBCS failed so treat as Latin1
+ utfForm = UTF8FromLatin1(s, len);
+ pango_layout_set_text(layout, utfForm, strlen(utfForm));
+ }
+ pango_layout_index_to_pos(layout, len, &pos);
+ int width = PANGO_PIXELS(pos.x);
+ delete []utfForm;
+ return width;
+ }
+#endif
if (unicodeMode) {
- GdkWChar wctext[MAX_US_LEN];
+ GdkWChar wctext[maxLengthTextRun];
size_t wclen = UCS2FromUTF8(s, len, (wchar_t *)wctext, sizeof(wctext) / sizeof(GdkWChar) - 1);
wctext[wclen] = L'\0';
- int width = gdk_text_width_wc(PFont(font_), wctext, wclen);
- return width;
- } else
- return gdk_text_width(PFont(font_), s, len);
+ return gdk_text_width_wc(PFont(font_)->pfont, wctext, wclen);
+ } else {
+ return gdk_text_width(PFont(font_)->pfont, s, len);
+ }
} else {
return 1;
}
}
int SurfaceImpl::WidthChar(Font &font_, char ch) {
- if (font_.GetID())
- return gdk_char_width(PFont(font_), ch);
- else
+ if (font_.GetID()) {
+#ifdef USE_PANGO
+ if (PFont(font_)->pfd) {
+ return WidthText(font_, &ch, 1);
+ }
+#endif
+ return gdk_char_width(PFont(font_)->pfont, ch);
+ } else {
return 1;
+ }
}
// Three possible strategies for determining ascent and descent of font:
@@ -1050,11 +1251,23 @@ const char sizeString[] = "`~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890"
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
int SurfaceImpl::Ascent(Font &font_) {
- if (!font_.GetID())
+ if (!(font_.GetID()))
return 1;
#ifdef FAST_WAY
+ if (PFont(font_)->ascent > 0)
+ return PFont(font_)->ascent;
+#ifdef USE_PANGO
+ if (PFont(font_)->pfd) {
+ PangoFontMetrics *metrics = pango_context_get_metrics(pcontext,
+ PFont(font_)->pfd, pango_context_get_language(pcontext));
+ PFont(font_)->ascent =
+ PANGO_PIXELS(pango_font_metrics_get_ascent(metrics));
+ pango_font_metrics_unref(metrics);
+ return PFont(font_)->ascent;
+ }
+#endif
- return PFont(font_)->ascent;
+ return PFont(font_)->pfont->ascent;
#else
gint lbearing;
@@ -1063,18 +1276,27 @@ int SurfaceImpl::Ascent(Font &font_) {
gint ascent;
gint descent;
- gdk_string_extents(PFont(font_), sizeString,
+ gdk_string_extents(PFont(font_)->pfont, sizeString,
&lbearing, &rbearing, &width, &ascent, &descent);
return ascent;
#endif
}
int SurfaceImpl::Descent(Font &font_) {
- if (!font_.GetID())
+ if (!(font_.GetID()))
return 1;
#ifdef FAST_WAY
- return PFont(font_)->descent;
+#ifdef USE_PANGO
+ if (PFont(font_)->pfd) {
+ PangoFontMetrics *metrics = pango_context_get_metrics(pcontext,
+ PFont(font_)->pfd, pango_context_get_language(pcontext));
+ int descent = PANGO_PIXELS(pango_font_metrics_get_descent(metrics));
+ pango_font_metrics_unref(metrics);
+ return descent;
+ }
+#endif
+ return PFont(font_)->pfont->descent;
#else
gint lbearing;
@@ -1083,7 +1305,7 @@ int SurfaceImpl::Descent(Font &font_) {
gint ascent;
gint descent;
- gdk_string_extents(PFont(font_), sizeString,
+ gdk_string_extents(PFont(font_)->pfont, sizeString,
&lbearing, &rbearing, &width, &ascent, &descent);
return descent;
#endif
@@ -1102,10 +1324,7 @@ int SurfaceImpl::Height(Font &font_) {
}
int SurfaceImpl::AverageCharWidth(Font &font_) {
- if (font_.GetID())
- return gdk_char_width(PFont(font_), 'n');
- else
- return 1;
+ return WidthChar(font_, 'n');
}
int SurfaceImpl::SetPalette(Palette *, bool) {
@@ -1381,10 +1600,10 @@ void ListBoxX::Create(Window &, int, int, bool) {
void ListBoxX::SetFont(Font &scint_font) {
#if GTK_MAJOR_VERSION < 2
GtkStyle *style = gtk_widget_get_style(GTK_WIDGET(PWidget(list)));
- if (!gdk_font_equal(style->font, PFont(scint_font))) {
+ if (!gdk_font_equal(style->font, PFont(scint_font)->pfont)) {
style = gtk_style_copy(style);
gdk_font_unref(style->font);
- style->font = PFont(scint_font);
+ style->font = PFont(scint_font)->pfont;
gdk_font_ref(style->font);
gtk_widget_set_style(GTK_WIDGET(PWidget(list)), style);
gtk_style_unref(style);
@@ -1392,9 +1611,9 @@ void ListBoxX::SetFont(Font &scint_font) {
#else
GtkStyle *styleCurrent = gtk_widget_get_style(GTK_WIDGET(PWidget(list)));
GdkFont *fontCurrent = gtk_style_get_font(styleCurrent);
- if (!gdk_font_equal(fontCurrent, PFont(scint_font))) {
+ if (!gdk_font_equal(fontCurrent, PFont(scint_font)->pfont)) {
GtkStyle *styleNew = gtk_style_copy(styleCurrent);
- gtk_style_set_font(styleNew, PFont(scint_font));
+ gtk_style_set_font(styleNew, PFont(scint_font)->pfont);
gtk_widget_set_style(GTK_WIDGET(PWidget(list)), styleNew);
gtk_style_unref(styleCurrent);
}
diff --git a/gtk/ScintillaGTK.cxx b/gtk/ScintillaGTK.cxx
index 7a2bfa458..e0fd95a99 100644
--- a/gtk/ScintillaGTK.cxx
+++ b/gtk/ScintillaGTK.cxx
@@ -93,7 +93,7 @@ class ScintillaGTK : public ScintillaBase {
gint wheelMouseIntensity;
// Private so ScintillaGTK objects can not be copied
-ScintillaGTK(const ScintillaGTK &) : ScintillaBase() {}
+ ScintillaGTK(const ScintillaGTK &) : ScintillaBase() {}
ScintillaGTK &operator=(const ScintillaGTK &) { return * this; }
public:
@@ -654,7 +654,7 @@ void ScintillaGTK::FullPaint() {
if ((PWidget(wMain))->window) {
Surface *sw = Surface::Allocate();
if (sw) {
- sw->Init((PWidget(wMain))->window);
+ sw->Init(PWidget(wMain)->window, PWidget(wMain));
Paint(sw, rcPaint);
sw->Release();
delete sw;
@@ -691,7 +691,7 @@ void ScintillaGTK::SyncPaint(PRectangle rc) {
if ((PWidget(wMain))->window) {
Surface *sw = Surface::Allocate();
if (sw) {
- sw->Init((PWidget(wMain))->window);
+ sw->Init(PWidget(wMain)->window, PWidget(wMain));
Paint(sw, rc);
sw->Release();
delete sw;
@@ -1520,7 +1520,7 @@ gint ScintillaGTK::Expose(GtkWidget *, GdkEventExpose *ose) {
paintingAllText = rcPaint.Contains(rcClient);
Surface *surfaceWindow = Surface::Allocate();
if (surfaceWindow) {
- surfaceWindow->Init((PWidget(wMain))->window);
+ surfaceWindow->Init(PWidget(wMain)->window, PWidget(wMain));
// Fill the corner between the scrollbars
PRectangle rcCorner = wMain.GetClientPosition();
if (verticalScrollBarVisible)
@@ -1668,7 +1668,7 @@ void ScintillaGTK::PopUpCB(ScintillaGTK *sciThis, guint action, GtkWidget *) {
gint ScintillaGTK::ExposeCT(GtkWidget *widget, GdkEventExpose * /*ose*/, CallTip *ctip) {
Surface *surfaceWindow = Surface::Allocate();
if (surfaceWindow) {
- surfaceWindow->Init(widget->window);
+ surfaceWindow->Init(widget->window, widget);
ctip->PaintCT(surfaceWindow);
surfaceWindow->Release();
delete surfaceWindow;