⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 platgtk.cxx.svn-base

📁 Notepad++ is a generic source code editor (it tries to be anyway) and Notepad replacement written in
💻 SVN-BASE
📖 第 1 页 / 共 4 页
字号:
}

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;
	len = strlen(utfForm);
	return utfForm;
}

static size_t UTF8CharLength(const char *s) {
	const unsigned char *us = reinterpret_cast<const unsigned char *>(s);
	unsigned char ch = *us;
	if (ch < 0x80) {
		return 1;
	} else if (ch < 0x80 + 0x40 + 0x20) {
		return 2;
	} else {
		return 3;
	}
}

#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) {
		int x = rc.left;
#ifdef USE_PANGO
		if (PFont(font_)->pfd) {
			char *utfForm = 0;
			bool useGFree = false;
			if (et == UTF8) {
				pango_layout_set_text(layout, s, len);
			} else {
				if (!utfForm) {
					SetConverter(PFont(font_)->characterSet);
					utfForm = UTF8FromIconv(conv, s, len);
				}
				if (!utfForm) {	// iconv failed so try DBCS if DBCS mode
					if (et == dbcs) {
						// Convert to utf8
						utfForm = UTF8FromDBCS(s, len);
					}
				}
				if (!utfForm) {	// iconv and DBCS failed so treat as Latin1
					utfForm = UTF8FromLatin1(s, len);
				}
				pango_layout_set_text(layout, utfForm, len);
			}
			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);
			if (useGFree) {
				g_free(utfForm);
			} else {
				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 (et != singleByte) {
			GdkWChar wctext[maxLengthTextRun];
			if (len >= maxLengthTextRun)
				len = maxLengthTextRun-1;
			int wclen;
			if (et == UTF8) {
				wclen = UCS2FromUTF8(s, len,
					static_cast<wchar_t *>(static_cast<void *>(wctext)), maxLengthTextRun - 1);
			} else {	// dbcs, so convert using current locale
				char sMeasure[maxLengthTextRun];
				memcpy(sMeasure, s, len);
				sMeasure[len] = '\0';
				wclen = gdk_mbstowcs(
					wctext, sMeasure, maxLengthTextRun - 1);
			}
			if (wclen > 0) {
				draw8bit = false;
				wctext[wclen] = L'\0';
				GdkWChar *wcp = wctext;
				while ((wclen > 0) && (x < maxCoordinate)) {
					int lenDraw = Platform::Minimum(wclen, segmentLength);
					gdk_draw_text_wc(drawable, PFont(font_)->pfont, gc,
							 x, ybase, wcp, lenDraw);
					wclen -= lenDraw;
					if (wclen > 0) {	// Avoid next calculation if possible as may be expensive
						x += gdk_text_width_wc(PFont(font_)->pfont,
								       wcp, lenDraw);
					}
					wcp += lenDraw;
				}
			}
		}
		if (draw8bit) {
			while ((len > 0) && (x < maxCoordinate)) {
				int lenDraw = Platform::Minimum(len, segmentLength);
				gdk_draw_text(drawable, PFont(font_)->pfont, gc,
				              x, ybase, s, lenDraw);
				len -= lenDraw;
				if (len > 0) {	// Avoid next calculation if possible as may be expensive
					x += gdk_text_width(PFont(font_)->pfont, s, lenDraw);
				}
				s += lenDraw;
			}
		}
	}
}

void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len,
                                 ColourAllocated fore, ColourAllocated back) {
	FillRectangle(rc, back);
	DrawTextBase(rc, font_, ybase, s, len, fore);
}

// On GTK+, exactly same as DrawTextNoClip
void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len,
                                  ColourAllocated fore, ColourAllocated back) {
	FillRectangle(rc, back);
	DrawTextBase(rc, font_, ybase, s, len, fore);
}

void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len,
                                  ColourAllocated fore) {
	// Avoid drawing spaces in transparent mode
	for (int i=0;i<len;i++) {
		if (s[i] != ' ') {
			DrawTextBase(rc, font_, ybase, s, len, fore);
			return;
		}
	}
}

void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positions) {
	if (font_.GetID()) {
		int totalWidth = 0;
#ifdef USE_PANGO
		const int lenPositions = len;
		if (PFont(font_)->pfd) {
			if (len == 1) {
				int width = PFont(font_)->CharWidth(*s, et);
				if (width) {
					positions[0] = width;
					return;
				}
			}
			PangoRectangle pos;
			pango_layout_set_font_description(layout, PFont(font_)->pfd);
			if (et == UTF8) {
				// Simple and direct as UTF-8 is native Pango encoding
				pango_layout_set_text(layout, s, len);
				PangoLayoutIter *iter = pango_layout_get_iter(layout);
				pango_layout_iter_get_cluster_extents(iter, NULL, &pos);
				int i = 0;
				while (pango_layout_iter_next_cluster(iter)) {
					pango_layout_iter_get_cluster_extents(iter, NULL, &pos);
					int position = PANGO_PIXELS(pos.x);
					int curIndex = pango_layout_iter_get_index(iter);
					while (i < curIndex) {
						positions[i++] = position;
					}
				}
				while (i < lenPositions)
					positions[i++] = PANGO_PIXELS(pos.x + pos.width);
				pango_layout_iter_free(iter);
				PLATFORM_ASSERT(i == lenPositions);
			} else {
				int positionsCalculated = 0;
				if (et == dbcs) {
					SetConverter(PFont(font_)->characterSet);
					char *utfForm = UTF8FromIconv(conv, s, len);
					if (utfForm) {
						// 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.
						Converter convMeasure("UCS-2", CharacterSetID(characterSet), false);
						pango_layout_set_text(layout, utfForm, strlen(utfForm));
						int i = 0;
						int utfIndex = 0;
						PangoLayoutIter *iter = pango_layout_get_iter(layout);
						pango_layout_iter_get_cluster_extents(iter, NULL, &pos);
						while (pango_layout_iter_next_cluster(iter)) {
							pango_layout_iter_get_cluster_extents (iter, NULL, &pos);
							int position = PANGO_PIXELS(pos.x);
							int utfIndexNext = pango_layout_iter_get_index(iter);
							while (utfIndex < utfIndexNext) {
								size_t lenChar = MultiByteLenFromIconv(convMeasure, s+i, len-i);
								//size_t lenChar = mblen(s+i, MB_CUR_MAX);
								while (lenChar--) {
									positions[i++] = position;
									positionsCalculated++;
								}
								utfIndex += UTF8CharLength(utfForm+utfIndex);
							}
						}
						while (i < lenPositions)
							positions[i++] = PANGO_PIXELS(pos.x + pos.width);
						pango_layout_iter_free(iter);
						delete []utfForm;
						PLATFORM_ASSERT(i == lenPositions);
					}
				}
				if (positionsCalculated < 1 ) {
					// Either Latin1 or DBCS conversion failed so treat as Latin1.
					bool useGFree = false;
					SetConverter(PFont(font_)->characterSet);
					char *utfForm = UTF8FromIconv(conv, s, len);
					if (!utfForm) {
						utfForm = UTF8FromLatin1(s, len);
					}
					pango_layout_set_text(layout, utfForm, len);
					int i = 0;
					PangoLayoutIter *iter = pango_layout_get_iter(layout);
					pango_layout_iter_get_cluster_extents(iter, NULL, &pos);
					while (pango_layout_iter_next_cluster(iter)) {
						pango_layout_iter_get_cluster_extents(iter, NULL, &pos);
						positions[i++] = PANGO_PIXELS(pos.x);
					}
					while (i < lenPositions)
						positions[i++] = PANGO_PIXELS(pos.x + pos.width);
					pango_layout_iter_free(iter);
					if (useGFree) {
						g_free(utfForm);
					} else {
						delete []utfForm;
					}
					PLATFORM_ASSERT(i == lenPositions);
				}
			}
			if (len == 1) {
				PFont(font_)->SetCharWidth(*s, positions[0], et);
			}
			return;
		}
#endif
		GdkFont *gf = PFont(font_)->pfont;
		bool measure8bit = true;
		if (et != singleByte) {
			GdkWChar wctext[maxLengthTextRun];
			if (len >= maxLengthTextRun)
				len = maxLengthTextRun-1;
			int wclen;
			if (et == UTF8) {
				wclen = UCS2FromUTF8(s, len,
					static_cast<wchar_t *>(static_cast<void *>(wctext)), maxLengthTextRun - 1);
			} else {	// dbcsMode, so convert using current locale
				char sDraw[maxLengthTextRun];
				memcpy(sDraw, s, len);
				sDraw[len] = '\0';
				wclen = gdk_mbstowcs(
					wctext, sDraw, maxLengthTextRun - 1);
			}
			if (wclen > 0) {
				measure8bit = false;
				wctext[wclen] = L'\0';
				// 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;
					int lenChar;
					if (et == UTF8) {
						lenChar = UTF8Len(s[i]);
					} else {
						lenChar = mblen(s+i, MB_CUR_MAX);
						if (lenChar < 0)
							lenChar = 1;
					}
					while (lenChar--) {
						positions[i++] = totalWidth;
					}
				}
				while (i < len) {	// In case of problems with lengths
					positions[i++] = totalWidth;
				}
			}
		}
		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;
				positions[i] = totalWidth;
			}
		}
	} else {
		// No font so return an ascending range of values
		for (int i = 0; i < len; i++) {
			positions[i] = i + 1;
		}
	}
}

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;
			bool useGFree = false;
			if (et == UTF8) {
				pango_layout_set_text(layout, s, len);
			} else {
				if (et == dbcs) {
					// Convert to utf8
					utfForm = UTF8FromDBCS(s, len);
				}
				if (!utfForm) {	// DBCS failed so treat as iconv
					SetConverter(PFont(font_)->characterSet);
					utfForm = UTF8FromIconv(conv, s, len);
				}
				if (!utfForm) {	// g_locale_to_utf8 failed so treat as Latin1
					utfForm = UTF8FromLatin1(s, len);
				}
				pango_layout_set_text(layout, utfForm, len);
			}
			PangoLayoutLine *pangoLine = pango_layout_get_line(layout, 0);
			pango_layout_line_get_extents(pangoLine, NULL, &pos);
			if (useGFree) {
				g_free(utfForm);
			} else {
				delete []utfForm;
			}
			return PANGO_PIXELS(pos.width);
		}
#endif
		if (et == UTF8) {
			GdkWChar wctext[maxLengthTextRun];
			size_t wclen = UCS2FromUTF8(s, len, static_cast<wchar_t *>(static_cast<void *>(wctext)),
				sizeof(wctext) / sizeof(GdkWChar) - 1);
			wctext[wclen] = L'\0';
			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()) {
#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:
// 1) Call gdk_string_extents with string containing all letters, numbers and punctuation.
// 2) Use the ascent and descent fields of GdkFont.
// 3) Call gdk_string_extents with string as 1 but also including accented capitals.
// Smallest values given by 1 and largest by 3 with 2 in between.
// Techniques 1 and 2 sometimes chop off extreme portions of ascenders and
// descenders but are mostly OK except for accented characters like 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -