/* WCEGlyphVector.java
   Copyright (C) 2006 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package gnu.java.awt.peer.wce.font;

import java.awt.Font;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphJustificationInfo;
import java.awt.font.GlyphMetrics;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.peer.FontPeer;
import java.text.StringCharacterIterator;

/**
 * GlyphVectorのWindows CE実装
 */
public class WCEGlyphVector extends GlyphVector {
	
	private final Font font;
	private FontRenderContext fontRenderContext;

	/**
	 * Windows CEにはフォントのアウトラインを取得するAPIが存在しないため、
	 * 文字列を保持しておく必要がある
	 */
	private final String text;
	
	public WCEGlyphVector(Font font,
						  String text,
						  FontRenderContext frc,
						  int flags) {
		this.font = font;
		this.fontRenderContext = frc;
		this.text = text;
	}
	
	public Font getFont() {
		return this.font;
	}
	
	public FontRenderContext getFontRenderContext() {
		return this.fontRenderContext;
	}
	
	public void performDefaultLayout() {
		// ToDo:実装する
	}
	
	public int getNumGlyphs() {
		// ToDo: 実装する
		return text.length();
	}
	
	public int getGlyphCode(int glyphIndex) {
		// ToDo: 実装する
		return (int) text.charAt(glyphIndex);
	}
	
	public int[] getGlyphCodes(int beginGlyphIndex,
                               int numEntries,
                               int[] codeReturn) {
		if (numEntries < 0) {
			throw new IllegalArgumentException("numEntries < 0");
		}
		
		int[] result = codeReturn;
		if (result == null || result.length < numEntries) {
			result = new int[numEntries];
		}
		
		// ToDo: 実装する
		for (int i = 0; i < numEntries; ++i) {
			result[i] = this.text.charAt(beginGlyphIndex + i);
		}
		return result;
	}
	
	/**
	 * 論理境界線を返す
	 *
	 * @return	論理境界線
	 */
	@SuppressWarnings("deprecation")
	public Rectangle2D getLogicalBounds() {
		// ToDo: 実装する
		FontPeer peer = font.getPeer();
		if (peer instanceof WCEFontPeer) {
			return ((WCEFontPeer) peer).getStringBounds(this.font,
														new StringCharacterIterator(this.text),
														0,
														this.text.length(),
														this.fontRenderContext);
		} else {
			throw new UnsupportedOperationException();
		}
	}
	
	public Rectangle2D getVisualBounds() {
		// ToDo: 実装する
		return getLogicalBounds();
	}
	
	public Shape getOutline() {
		// ToDo: 実装する
		return getLogicalBounds();
	}
	
	public Shape getOutline(float x, float y) {
		Rectangle2D rect = (Rectangle2D) getOutline();
		return new Rectangle((int) x, (int) y, (int) rect.getWidth(), (int) rect.getHeight());
	}
	
	public Shape getGlyphOutline(int glyphIndex) {
		// ToDo: 実装する
		throw new UnsupportedOperationException();
	}

	public Shape getGlyphOutline(int glyphIndex,
                             float x,
                             float y) {
		// ToDo: 実装する
		throw new UnsupportedOperationException();
	}
	
	public Point2D getGlyphPosition(int glyphIndex) {
		// ToDo: 実装する
		throw new UnsupportedOperationException();
	}

	public void setGlyphPosition(int glyphIndex, Point2D newPos) {
		// ToDo: 実装する
		throw new UnsupportedOperationException();
	}
	
	public AffineTransform getGlyphTransform(int glyphIndex) {
		// ToDo: 実装する
		throw new UnsupportedOperationException();
	}

	public void setGlyphTransform(int glyphIndex, AffineTransform newTX) {
		// ToDo: 実装する
		throw new UnsupportedOperationException();
	}

	public float[] getGlyphPositions(int beginGlyphIndex,
                                          int numEntries,
                                          float[] positionReturn) {
		throw new UnsupportedOperationException();
	}
	
	/**
	 * 指定されたインデックス位置にあるグリフの論理境界線を返す。
	 *
	 * @param	glyphIndex	グリフインデックス
	 * @return	論理境界線
	 * @throws	IndexOutOfBoundsException	glyphIndex < 0 または グリフ数と等しい場合
	 */
	@SuppressWarnings("deprecation")
	public Shape getGlyphLogicalBounds(int glyphIndex) {
		final int length = this.text.length();
		if (glyphIndex < 0 || glyphIndex >= length) {
			throw new ArrayIndexOutOfBoundsException(glyphIndex);
		}
		
		// フォントピアを得る
		WCEFontPeer peer = (WCEFontPeer) this.font.getPeer();
		
		// まず、指定された位置にある文字だけを含む境界線を得る
		char[] target = new char[1];
		this.text.getChars(glyphIndex, glyphIndex + 1, target, 0);
		Rectangle2D r1 = peer.getNativeStringBounds(peer.getFontHandle(), target);
		if (glyphIndex == 0) {
			return r1;
		}
		
		// 次に、指定された位置にある文字より１つ手前までの境界線を得る
		target = new char[glyphIndex];
		this.text.getChars(0, glyphIndex, target, 0);
		Rectangle2D r2 = peer.getNativeStringBounds(peer.getFontHandle(), target);
		// X座標だけをずらしたRectangleを返す
		return new Rectangle((int) r2.getWidth(),
							 (int) r1.getY(),
							 (int) r1.getWidth(),
							 (int) r1.getHeight());
	}
	
	public Shape getGlyphVisualBounds(int glyphIndex) {
		throw new UnsupportedOperationException();
	}
	
	public Rectangle getGlyphPixelBounds(int index,
                                     FontRenderContext renderFRC,
                                     float x,
                                     float y) {
		throw new UnsupportedOperationException();
	}
	
	public GlyphMetrics getGlyphMetrics(int glyphIndex) {
		throw new UnsupportedOperationException();
	}
	
	public GlyphJustificationInfo getGlyphJustificationInfo(int glyphIndex) {
		throw new UnsupportedOperationException();
	}
	
	public int hashCode() {
		return this.font.hashCode()
				+ this.fontRenderContext.hashCode()
				+ this.text.hashCode();
	}
	
	public boolean equals(GlyphVector set) {
		if (set instanceof WCEGlyphVector) {
			WCEGlyphVector gv = (WCEGlyphVector) set;
			return (this.font.equals(gv.font)
					&& this.fontRenderContext.equals(gv.fontRenderContext)
					&& this.text.equals(gv.text));
		}
		return false;
	}

	/**
	 * 設定されているテキストを返す
	 */
	public String getText() {
		return this.text;
	}
}

