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

📄 textlayout.java

📁 源码为Eclipse开源开发平台桌面开发工具SWT的源代码,
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
/******************************************************************************* * Copyright (c) 2000, 2004 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html *  * Contributors: *     IBM Corporation - initial API and implementation *******************************************************************************/package org.eclipse.swt.graphics;import org.eclipse.swt.internal.*;import org.eclipse.swt.internal.win32.*;import org.eclipse.swt.*;/** * <code>TextLayout</code> is a graphic object that represents * styled text. *<p> * Instances of this class provide support for drawing, cursor * navigation, hit testing, text wrapping, alignment, tab expansion * line breaking, etc.  These are aspects required for rendering internationalized text. * </p> *  * <p> * Application code must explicitly invoke the <code>TextLayout#dispose()</code>  * method to release the operating system resources managed by each instance * when those instances are no longer required. * </p> *  *  @since 3.0 */public final class TextLayout {	Device device;	Font font;	String text, segmentsText;	int lineSpacing;	int ascent, descent;	int alignment;	int wrapWidth;	int orientation;	int[] tabs;	int[] segments;	StyleItem[] styles;	StyleItem[] allRuns;	StyleItem[][] runs;	int[] lineOffset, lineY, lineWidth;		static final char LTR_MARK = '\u200E', RTL_MARK = '\u200F';		static final int SCRIPT_VISATTR_SIZEOF = 2;	static final int GOFFSET_SIZEOF = 8;		static class StyleItem {		TextStyle style;		int start, length;		boolean lineBreak, softBreak, tab;					/*Script cache and analysis */		SCRIPT_ANALYSIS analysis;		int psc = 0;				/*Shape info (malloc when the run is shaped) */		int glyphs;		int glyphCount;		int clusters;		int visAttrs;				/*Place info (malloc when the run is placed) */		int advances;		int goffsets;		int width;		int ascent;		int descent;		/* ScriptBreak */		int psla;		int fallbackFont;		void free() {		int hHeap = OS.GetProcessHeap();		if (psc != 0) {			OS.ScriptFreeCache (psc);			OS.HeapFree(hHeap, 0, psc);			psc = 0;		}		if (glyphs != 0) {			OS.HeapFree(hHeap, 0, glyphs);			glyphs = 0;			glyphCount = 0;		}		if (clusters != 0) {			OS.HeapFree(hHeap, 0, clusters);			clusters = 0;		}		if (visAttrs != 0) {			OS.HeapFree(hHeap, 0, visAttrs);			visAttrs = 0;		}		if (advances != 0) {			OS.HeapFree(hHeap, 0, advances);			advances = 0;		}				if (goffsets != 0) {			OS.HeapFree(hHeap, 0, goffsets);			goffsets = 0;		}		if (psla != 0) {			OS.HeapFree(hHeap, 0, psla);			psla = 0;		}		if (fallbackFont != 0) {			OS.DeleteObject(fallbackFont);			fallbackFont = 0;		}		width = ascent = descent = 0;		lineBreak = softBreak = false;			}	}/**	  * Constructs a new instance of this class on the given device. * <p> * You must dispose the text layout when it is no longer required.  * </p> *  * @param device the device on which to allocate the text layout *  * @exception IllegalArgumentException <ul> *    <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li> * </ul> *  * @see #dispose() */public TextLayout (Device device) {	if (device == null) device = Device.getDevice();	if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);	this.device = device;	wrapWidth = ascent = descent = -1;	lineSpacing = 0;	orientation = SWT.LEFT_TO_RIGHT;	styles = new StyleItem[2];	styles[0] = new StyleItem();	styles[1] = new StyleItem();	text = ""; //$NON-NLS-1$	if (device.tracking) device.new_Object(this);}void breakRun(StyleItem run) {	if (run.psla != 0) return;	char[] chars = new char[run.length];	segmentsText.getChars(run.start, run.start + run.length, chars, 0);	int hHeap = OS.GetProcessHeap();	run.psla = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, SCRIPT_LOGATTR.sizeof * chars.length); 	OS.ScriptBreak(chars, chars.length, run.analysis, run.psla);}void checkLayout () {	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);}/* *  Compute the runs: itemize, shape, place, and reorder the runs.* 	Break paragraphs into lines, wraps the text, and initialize caches.*/void computeRuns (GC gc) {	if (runs != null) return;	int hDC = gc != null ? gc.handle : device.internal_new_GC(null);	int srcHdc = OS.CreateCompatibleDC(hDC);	allRuns = itemize();	for (int i=0; i<allRuns.length - 1; i++) {		StyleItem run = allRuns[i];		OS.SelectObject(srcHdc, getItemFont(run));		shape(srcHdc, run);	}	SCRIPT_LOGATTR logAttr = new SCRIPT_LOGATTR();	SCRIPT_PROPERTIES properties = new SCRIPT_PROPERTIES();	int lineWidth = 0, lineStart = 0, lineCount = 1;	for (int i=0; i<allRuns.length - 1; i++) {		StyleItem run = allRuns[i];		if (run.length == 1) {			char ch = segmentsText.charAt(run.start);			switch (ch) {				case '\t': {					run.tab = true;					if (tabs == null) break;					int tabsLength = tabs.length, j;					for (j = 0; j < tabsLength; j++) {						if (tabs[j] > lineWidth) {							run.width = tabs[j] - lineWidth;							break;						}					}					if (j == tabsLength) {						int tabX = tabs[tabsLength-1];						int lastTabWidth = tabsLength > 1 ? tabs[tabsLength-1] - tabs[tabsLength-2] : tabs[0];						if (lastTabWidth > 0) {							while (tabX <= lineWidth) tabX += lastTabWidth;							run.width = tabX - lineWidth;						}					}					break;				}				case '\n': {					run.lineBreak = true;					break;				}				case '\r': {					run.lineBreak = true;					StyleItem next = allRuns[i + 1];					if (next.length != 0 && segmentsText.charAt(next.start) == '\n') {						run.length += 1;						next.free();						i++;					}					break;				}			}		} 		if (wrapWidth != -1 && lineWidth + run.width > wrapWidth && !run.tab) {			int start = 0;			int[] piDx = new int[run.length];			OS.ScriptGetLogicalWidths(run.analysis, run.length, run.glyphCount, run.advances, run.clusters, run.visAttrs, piDx);			int width = 0, maxWidth = wrapWidth - lineWidth;			while (width + piDx[start] < maxWidth) {				width += piDx[start++];			}			int firstStart = start;			int firstIndice = i;			while (i >= lineStart) {				breakRun(run);				while (start >= 0) {					OS.MoveMemory(logAttr, run.psla + (start * SCRIPT_LOGATTR.sizeof), SCRIPT_LOGATTR.sizeof); 					if (logAttr.fSoftBreak || logAttr.fWhiteSpace) break;					start--;				}								/*				*  Bug in Windows. For some reason Uniscribe sets the fSoftBreak flag for the first letter				*  after a letter with an accent. This cause a break line to be set in the middle of a word.				*  The fix is to detect the case and ignore fSoftBreak forcing the algorithm keep searching.				*/				if (start == 0 && i != lineStart && !run.tab) {					if (logAttr.fSoftBreak && !logAttr.fWhiteSpace) {						OS.MoveMemory(properties, device.scripts[run.analysis.eScript], SCRIPT_PROPERTIES.sizeof);						int langID = properties.langid;						StyleItem pRun = allRuns[i - 1];						OS.MoveMemory(properties, device.scripts[pRun.analysis.eScript], SCRIPT_PROPERTIES.sizeof);						if (properties.langid == langID || langID == OS.LANG_NEUTRAL || properties.langid == OS.LANG_NEUTRAL) {							breakRun(pRun);							OS.MoveMemory(logAttr, pRun.psla + ((pRun.length - 1) * SCRIPT_LOGATTR.sizeof), SCRIPT_LOGATTR.sizeof); 							if (!logAttr.fWhiteSpace) start = -1;						}					}				}						if (start >= 0 || i == lineStart) break;				run = allRuns[--i];				start = run.length - 1;			}			if (start == 0 && i != lineStart && !run.tab) {				run = allRuns[--i];			} else 	if (start <= 0 && i == lineStart) {				i = firstIndice;				run = allRuns[i];				start = Math.max(1, firstStart);			}			breakRun(run);			while (start < run.length) {				OS.MoveMemory(logAttr, run.psla + (start * SCRIPT_LOGATTR.sizeof), SCRIPT_LOGATTR.sizeof); 				if (!logAttr.fWhiteSpace) break;				start++;			}			if (0 < start && start < run.length) {				StyleItem newRun = new StyleItem();				newRun.start = run.start + start;				newRun.length = run.length - start;				newRun.style = run.style;				newRun.analysis = run.analysis;				run.free();				run.length = start;				OS.SelectObject(srcHdc, getItemFont(run));				shape (srcHdc, run);				shape (srcHdc, newRun);				StyleItem[] newAllRuns = new StyleItem[allRuns.length + 1];				System.arraycopy(allRuns, 0, newAllRuns, 0, i + 1);				System.arraycopy(allRuns, i + 1, newAllRuns, i + 2, allRuns.length - i - 1);				allRuns = newAllRuns;				allRuns[i + 1] = newRun;			}			if (i != allRuns.length - 2) {				run.softBreak = run.lineBreak = true;			}		}		lineWidth += run.width;		if (run.lineBreak) {			lineStart = i + 1;			lineWidth = 0;			lineCount++;		}	}	lineWidth = 0;	runs = new StyleItem[lineCount][];	lineOffset = new int[lineCount + 1];	lineY = new int[lineCount + 1];	this.lineWidth = new int[lineCount];	int lineRunCount = 0, line = 0;	int ascent = Math.max(0, this.ascent);	int descent = Math.max(0, this.descent);	StyleItem[] lineRuns = new StyleItem[allRuns.length];	for (int i=0; i<allRuns.length; i++) {		StyleItem run = allRuns[i];		lineRuns[lineRunCount++] = run;		lineWidth += run.width;		ascent = Math.max(ascent, run.ascent);		descent = Math.max(descent, run.descent);		if (run.lineBreak || i == allRuns.length - 1) {			/* Update the run metrics if the last run is a hard break. */			if (lineRunCount == 1 && i == allRuns.length - 1) {				TEXTMETRIC lptm = OS.IsUnicode ? (TEXTMETRIC)new TEXTMETRICW() : new TEXTMETRICA();				OS.SelectObject(srcHdc, getItemFont(run));				OS.GetTextMetrics(srcHdc, lptm);				run.ascent = lptm.tmAscent;				run.descent = lptm.tmDescent;				ascent = Math.max(ascent, run.ascent);				descent = Math.max(descent, run.descent);			}			runs[line] = new StyleItem[lineRunCount];			System.arraycopy(lineRuns, 0, runs[line], 0, lineRunCount);			StyleItem lastRun = runs[line][lineRunCount - 1];			runs[line] = reorder(runs[line]);			this.lineWidth[line] = lineWidth;			line++;			lineY[line] = lineY[line - 1] + ascent + descent + lineSpacing;			lineOffset[line] = lastRun.start + lastRun.length;			lineRunCount = lineWidth = 0;			ascent = Math.max(0, this.ascent);			descent = Math.max(0, this.descent);		}	}	if (srcHdc != 0) OS.DeleteDC(srcHdc);	if (gc == null) device.internal_dispose_GC(hDC, null);	}/** * Disposes of the operating system resources associated with * the text layout. Applications must dispose of all allocated text layouts. */public void dispose () {	if (device == null) return;	freeRuns();	font = null;		text = null;	segmentsText = null;	tabs = null;	styles = null;	runs = null;	lineOffset = null;	lineY = null;	lineWidth = null;	if (device.tracking) device.dispose_Object(this);	device = null;}/** * Draws the receiver's text using the specified GC at the specified * point. *  * @param gc the GC to draw * @param x the x coordinate of the top left corner of the rectangular area where the text is to be drawn * @param y the y coordinate of the top left corner of the rectangular area where the text is to be drawn * * @exception SWTException <ul> *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li> * </ul> */public void draw (GC gc, int x, int y) {	draw(gc, x, y, -1, -1, null, null);}/** * Draws the receiver's text using the specified GC at the specified * point. *  * @param gc the GC to draw * @param x the x coordinate of the top left corner of the rectangular area where the text is to be drawn * @param y the y coordinate of the top left corner of the rectangular area where the text is to be drawn * @param selectionStart the offset where the selections starts, or -1 indicating no selection * @param selectionEnd the offset where the selections ends, or -1 indicating no selection * @param selectionForeground selection foreground, or NULL to use the system default color * @param selectionBackground selection background, or NULL to use the system default color * * @exception SWTException <ul>

⌨️ 快捷键说明

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