PageRenderTime 34ms CodeModel.GetById 10ms app.highlight 20ms RepoModel.GetById 1ms app.codeStats 0ms

/jEdit/tags/jedit-4-0-pre3/org/gjt/sp/jedit/textarea/TextRenderer.java

#
Java | 264 lines | 181 code | 47 blank | 36 comment | 23 complexity | eec30bee2a46b00ec859fd7b5dcd1a16 MD5 | raw file
  1/*
  2 * TextRenderer.java - Draws text
  3 * :tabSize=8:indentSize=8:noTabs=false:
  4 * :folding=explicit:collapseFolds=1:
  5 *
  6 * Copyright (C) 2001 Slava Pestov
  7 *
  8 * This program is free software; you can redistribute it and/or
  9 * modify it under the terms of the GNU General Public License
 10 * as published by the Free Software Foundation; either version 2
 11 * of the License, or any later version.
 12 *
 13 * This program is distributed in the hope that it will be useful,
 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 16 * GNU General Public License for more details.
 17 *
 18 * You should have received a copy of the GNU General Public License
 19 * along with this program; if not, write to the Free Software
 20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 21 */
 22
 23package org.gjt.sp.jedit.textarea;
 24
 25//{{{ Imports
 26import javax.swing.text.TabExpander;
 27import java.awt.font.*;
 28import java.awt.geom.*;
 29import java.awt.*;
 30import java.util.Hashtable;
 31import org.gjt.sp.util.Log;
 32//}}}
 33
 34public class TextRenderer
 35{
 36	//{{{ setupGraphics() method
 37	public void setupGraphics(Graphics g)
 38	{
 39		((Graphics2D)g).setRenderingHints(renderingHints);
 40	} //}}}
 41
 42	//{{{ configure() method
 43	public void configure(boolean antiAlias, boolean fracFontMetrics)
 44	{
 45		Hashtable hints = new Hashtable();
 46
 47		if(antiAlias)
 48		{
 49			hints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
 50			hints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
 51			hints.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
 52			hints.put(RenderingHints.KEY_FRACTIONALMETRICS,
 53				fracFontMetrics ?
 54					RenderingHints.VALUE_FRACTIONALMETRICS_ON
 55					: RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
 56		}
 57		else
 58			hints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
 59
 60		renderingHints = new RenderingHints(hints);
 61		fontRenderContext = new FontRenderContext(null,antiAlias,
 62			fracFontMetrics);
 63	} //}}}
 64
 65	//{{{ drawChars() method
 66	public float drawChars(char[] text, int off, int len, Graphics _g,
 67		float x, float y, TabExpander e, Color foreground,
 68		Color tokenBackground, Color componentBackground)
 69	{
 70		Graphics2D g = (Graphics2D)_g;
 71
 72		//{{{ this probably should be moved elsewhere
 73		if(tokenBackground != null)
 74		{
 75			float width = charsWidth(text,off,len,g.getFont(),x,e);
 76
 77			FontMetrics fm = g.getFontMetrics();
 78			float height = fm.getHeight();
 79			float descent = fm.getDescent();
 80			float leading = fm.getLeading();
 81
 82			g.setXORMode(componentBackground);
 83			g.setColor(tokenBackground);
 84			g.fillRect((int)x,(int)(y - height + descent + leading),
 85				(int)width,(int)height);
 86
 87			g.setPaintMode();
 88		} //}}}
 89
 90		g.setColor(foreground);
 91
 92		int flushLen = 0;
 93		int flushIndex = off;
 94
 95		int end = off + len;
 96
 97		for(int i = off; i < end; i++)
 98		{
 99			if(text[i] == '\t')
100			{
101				if(flushLen > 0)
102				{
103					x += _drawChars(text,flushIndex,
104						flushLen,g,x,y);
105					flushLen = 0;
106				}
107
108				flushIndex = i + 1;
109
110				x = e.nextTabStop(x,i - off);
111			}
112			else
113				flushLen++;
114		}
115
116		if(flushLen > 0)
117			x += _drawChars(text,flushIndex,flushLen,g,x,y);
118
119		return x;
120	} //}}}
121
122	//{{{ charsWidth() method
123	public float charsWidth(char[] text, int off, int len, Font font, float x,
124		TabExpander e)
125	{
126		float newX = x;
127
128		int flushLen = 0;
129		int flushIndex = off;
130
131		int end = off + len;
132
133		for(int i = off; i < end; i++)
134		{
135			if(text[i] == '\t')
136			{
137				if(flushLen > 0)
138				{
139					newX += _getWidth(text,flushIndex,flushLen,font);
140					flushLen = 0;
141				}
142
143				flushIndex = i + 1;
144
145				newX = e.nextTabStop(newX,i - off);
146			}
147			else
148				flushLen++;
149		}
150
151		if(flushLen > 0)
152			newX += _getWidth(text,flushIndex,flushLen,font);
153
154		return newX - x;
155	} //}}}
156
157	//{{{ xToOffset() method
158	public int xToOffset(char[] text, int off, int len, Font font, float x,
159		TabExpander e, boolean round, float[] widthArray)
160	{
161		int flushLen = 0;
162		int flushIndex = off;
163
164		int end = off + len;
165
166		float width = widthArray[0];
167
168		for(int i = off; i < end; i++)
169		{
170			if(text[i] == '\t')
171			{
172				if(flushLen > 0)
173				{
174					float newWidth = _getWidth(text,flushIndex,
175						flushLen,font);
176					if(x <= width + newWidth)
177					{
178						return _xToOffset(text,flushIndex,
179							flushLen,font,x - width,
180							round) + flushIndex;
181					}
182					else
183						width += newWidth;
184
185					flushLen = 0;
186				}
187
188				flushIndex = i + 1;
189
190				float newWidth = e.nextTabStop(width,i - off) - width;
191				if(x <= width + newWidth)
192				{
193					if(round && (x - width) < (width + newWidth - x))
194						return i;
195					else
196						return i + 1;
197				}
198				else
199					width += newWidth;
200			}
201			else
202				flushLen++;
203		}
204
205		if(flushLen > 0)
206		{
207			float newWidth = _getWidth(text,flushIndex,flushLen,font);
208			if(x <= width + newWidth)
209			{
210				return _xToOffset(text,flushIndex,flushLen,font,
211					x - width,round) + flushIndex;
212			}
213			else
214				width += newWidth;
215		}
216
217		widthArray[0] = width;
218		return -1;
219	} //}}}
220
221	//{{{ Private members
222	private RenderingHints renderingHints;
223	private FontRenderContext fontRenderContext;
224
225	//{{{ _drawChars() method
226	private float _drawChars(char[] text, int start, int len, Graphics2D g,
227		float x, float y)
228	{
229		Font font = g.getFont();
230
231		// update it just in case
232		fontRenderContext = g.getFontRenderContext();
233
234		GlyphVector glyphs = font.createGlyphVector(fontRenderContext,
235			new String(text,start,len));
236
237		g.drawGlyphVector(glyphs,x,y);
238
239		return (float)glyphs.getLogicalBounds().getWidth();
240	} //}}}
241
242	//{{{ _getWidth() method
243	private float _getWidth(char[] text, int start, int len, Font font)
244	{
245		GlyphVector glyphs = font.createGlyphVector(fontRenderContext,
246			new String(text,start,len));
247
248		return (float)glyphs.getLogicalBounds().getWidth();
249	} //}}}
250
251	//{{{ _xToOffset() method
252	private int _xToOffset(char[] text, int start, int len, Font font,
253		float x, boolean round)
254	{
255		// this is slow!
256		TextLayout layout = new TextLayout(new String(text,start,len),font,
257			fontRenderContext);
258
259		TextHitInfo info = layout.hitTestChar(x,0);
260		return (round ? info.getInsertionIndex() : info.getCharIndex());
261	} //}}}
262
263	//}}}
264}