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

📄 platgtk.cxx

📁 一个可以提供语法高亮显示的编辑器
💻 CXX
📖 第 1 页 / 共 3 页
字号:
}

void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) {
	if (static_cast<SurfaceImpl &>(surfacePattern).drawable) {
		// Tile pattern over rectangle
		// Currently assumes 8x8 pattern
		int widthPat = 8;
		int heightPat = 8;
		for (int xTile = rc.left; xTile < rc.right; xTile += widthPat) {
			int widthx = (xTile + widthPat > rc.right) ? rc.right - xTile : widthPat;
			for (int yTile = rc.top; yTile < rc.bottom; yTile += heightPat) {
				int heighty = (yTile + heightPat > rc.bottom) ? rc.bottom - yTile : heightPat;
				gdk_draw_pixmap(drawable,
				                gc,
				                static_cast<SurfaceImpl &>(surfacePattern).drawable,
				                0, 0,
				                xTile, yTile,
				                widthx, heighty);
			}
		}
	} else {
		// Something is wrong so try to show anyway
		// Shows up black because colour not allocated
		FillRectangle(rc, ColourAllocated(0));
	}
}

void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
	if (((rc.right - rc.left) > 4) && ((rc.bottom - rc.top) > 4)) {
		// Approximate a round rect with some cut off corners
		Point pts[] = {
		                  Point(rc.left + 2, rc.top),
		                  Point(rc.right - 2, rc.top),
		                  Point(rc.right, rc.top + 2),
		                  Point(rc.right, rc.bottom - 2),
		                  Point(rc.right - 2, rc.bottom),
		                  Point(rc.left + 2, rc.bottom),
		                  Point(rc.left, rc.bottom - 2),
		                  Point(rc.left, rc.top + 2),
		              };
		Polygon(pts, sizeof(pts) / sizeof(pts[0]), fore, back);
	} else {
		RectangleDraw(rc, fore, back);
	}
}

void SurfaceImpl::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
	PenColour(back);
	gdk_draw_arc(drawable, gc, 1,
	             rc.left + 1, rc.top + 1,
	             rc.right - rc.left - 2, rc.bottom - rc.top - 2,
	             0, 32767);

	// The subtraction of 1 here is similar to the case for RectangleDraw
	PenColour(fore);
	gdk_draw_arc(drawable, gc, 0,
	             rc.left, rc.top,
	             rc.right - rc.left - 1, rc.bottom - rc.top - 1,
	             0, 32767);
}

void SurfaceImpl::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
	if (static_cast<SurfaceImpl &>(surfaceSource).drawable) {
		gdk_draw_pixmap(drawable,
		                gc,
		                static_cast<SurfaceImpl &>(surfaceSource).drawable,
		                from.x, from.y,
		                rc.left, rc.top,
		                rc.right - rc.left, rc.bottom - rc.top);
	}
}

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 *UTF8FromIconv(iconv_t iconvh, const char *s, int len) {
	if (iconvh != ((iconv_t)(-1))) {
		char *utfForm = new char[len*3+1];
		char *pin = const_cast<char *>(s);
		size_t inLeft = len;
		char *pout = utfForm;
		size_t outLeft = len*3+1;
		size_t conversions = iconv(iconvh, &pin, &inLeft, &pout, &outLeft);
		if (conversions != ((size_t)(-1))) {
			*pout = '\0';
			return utfForm;
		}
		delete []utfForm;
	}
	return 0;
}

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) {
		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 (et == dbcs) {
					// Convert to utf8
					utfForm = UTF8FromDBCS(s, len);
				}
				if (!utfForm) {	// DBCS failed so treat as iconv
					SetIconv(PFont(font_)->characterSet);
					utfForm = UTF8FromIconv(iconvh, s, len);
				}
				//~ if (!utfForm) {	// DBCS failed so treat as locale
					//~ gsize w; // stub
					//~ utfForm = g_locale_to_utf8(s, len, NULL, &w, NULL);
					//~ useGFree = static_cast<bool>(utfForm);
				//~ };
				if (!utfForm) {	// g_locale_to_utf8 failed so treat as Latin1
					utfForm = UTF8FromLatin1(s, len);
				}
				pango_layout_set_text(layout, utfForm, strlen(utfForm));
			}
			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];
			int wclen;
			if (et == UTF8) {
				wclen = UCS2FromUTF8(s, len,
					reinterpret_cast<wchar_t *>(wctext), maxLengthTextRun - 1);
			} else {	// dbcs, so convert using current locale
				wclen = gdk_mbstowcs(
					wctext, s, 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;
					wcp += lenDraw;
					if (wclen > 0) {	// Avoid next calculation if possible as may be expensive
						x += gdk_text_width_wc(PFont(font_)->pfont,
								       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;
				s += lenDraw;
				if (len > 0) {	// Avoid next calculation if possible as may be expensive
					x += gdk_text_width(PFont(font_)->pfont, 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
		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);
				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 (et == dbcs) {
					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) {
							iU += UTF8Len(utfForm[iU]);
							pango_layout_index_to_pos(layout, iU, &pos);
							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.
					bool useGFree = false;
					SetIconv(PFont(font_)->characterSet);
					char *utfForm = UTF8FromIconv(iconvh, s, len);
					//~ if (!utfForm) {	// iconv failed so treat as locale
						//~ gsize w; // stub
						//~ utfForm = g_locale_to_utf8(s, len, NULL, &w, NULL);
						//~ useGFree = static_cast<bool>(utfForm);
					//~ }
					if (!utfForm) {
						utfForm = UTF8FromLatin1(s, len);
					}
					pango_layout_set_text(layout, utfForm, strlen(utfForm));
					int i = 0;
					int iU = 0;
					while (i < len) {
						iU += UTF8Len(utfForm[iU]);
						pango_layout_index_to_pos(layout, iU, &pos);
						positions[i++] = PANGO_PIXELS(pos.x);
					}
					if (useGFree) {
						g_free(utfForm);
					} else {
						delete []utfForm;
					}
				}
			}
			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];
			int wclen;
			if (et == UTF8) {
				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) {
				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;
					size_t lenChar;
					if (et == UTF8) {
						lenChar = UTF8Len(s[i]);
					} else {
						lenChar = mblen(s+i, MB_CUR_MAX);
					}
					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
					SetIconv(PFont(font_)->characterSet);
					utfForm = UTF8FromIconv(iconvh, s, len);
				}
				//~ if (!utfForm) {	// iconv failed so treat as locale
					//~ gsize w;
					//~ utfForm = g_locale_to_utf8(s, len, NULL, &w, NULL);
					//~ useGFree = static_cast<bool>(utfForm);
				//~ };
				if (!utfForm) {	// g_locale_to_utf8 failed so treat as Latin1
					utfForm = UTF8FromLatin1(s, len);
				}
				pango_layout_set_text(layout, utfForm, strlen(utfForm));
				len = strlen(utfForm);
			}
			pango_layout_index_to_pos(layout, len, &pos);
			int width = PANGO_PIXELS(pos.x);
			if (useGFree) {
				g_free(utfForm);
			} else {
				delete []utfForm;
			}
			return width;
		}
#endif
		if (et == UTF8) {
			GdkWChar wctext[maxLengthTextRun];
			size_t wclen = UCS2FromUTF8(s, len, (wchar_t *)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 + -