diff -ruN javie-0.3.2-src/ch.kuramo.javie.api/META-INF/MANIFEST.MF javie-0.3.3-src/ch.kuramo.javie.api/META-INF/MANIFEST.MF
--- javie-0.3.2-src/ch.kuramo.javie.api/META-INF/MANIFEST.MF	2010-02-06 19:53:15.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.api/META-INF/MANIFEST.MF	2010-02-16 03:30:21.000000000 +0900
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: Javie API
 Bundle-SymbolicName: ch.kuramo.javie.api;singleton:=true
-Bundle-Version: 0.3.2.qualifier
+Bundle-Version: 0.3.3.qualifier
 Bundle-Vendor: rakusan
 Export-Package: ch.kuramo.javie.api,
  ch.kuramo.javie.api.annotations,
diff -ruN javie-0.3.2-src/ch.kuramo.javie.api/src/main/java/ch/kuramo/javie/api/RenderResolution.java javie-0.3.3-src/ch.kuramo.javie.api/src/main/java/ch/kuramo/javie/api/RenderResolution.java
--- javie-0.3.2-src/ch.kuramo.javie.api/src/main/java/ch/kuramo/javie/api/RenderResolution.java	2009-12-21 03:54:17.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.api/src/main/java/ch/kuramo/javie/api/RenderResolution.java	2010-02-14 01:08:11.000000000 +0900
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Yoshikazu Kuramochi
+ * Copyright (c) 2009,2010 Yoshikazu Kuramochi
  * All rights reserved.
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -59,6 +59,22 @@
 		return (scale == 1) ? vec : new Vec3d(vec.x * scale, vec.y * scale, vec.z * scale);
 	}
 
+	public void scale(double[] array) {
+		if (scale != 1) {
+			for (int i = 0; i < array.length; ++i) {
+				array[i] *= scale;
+			}
+		}
+	}
+
+	public void scale(float[] array) {
+		if (scale != 1) {
+			for (int i = 0; i < array.length; ++i) {
+				array[i] *= scale;
+			}
+		}
+	}
+
 	@Override
 	public int hashCode() {
 		final int prime = 31;
diff -ruN javie-0.3.2-src/ch.kuramo.javie.app/META-INF/MANIFEST.MF javie-0.3.3-src/ch.kuramo.javie.app/META-INF/MANIFEST.MF
--- javie-0.3.2-src/ch.kuramo.javie.app/META-INF/MANIFEST.MF	2010-02-06 19:53:15.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.app/META-INF/MANIFEST.MF	2010-02-16 03:30:21.000000000 +0900
@@ -2,15 +2,15 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: Javie Application Plug-in
 Bundle-SymbolicName: ch.kuramo.javie.app; singleton:=true
-Bundle-Version: 0.3.2.qualifier
+Bundle-Version: 0.3.3.qualifier
 Bundle-Activator: ch.kuramo.javie.app.Activator
 Bundle-Vendor: rakusan
 Require-Bundle: org.eclipse.ui,
  org.eclipse.ui.console,
  org.eclipse.core.runtime,
- ch.kuramo.javie.api;bundle-version="0.3.2",
- ch.kuramo.javie.core;bundle-version="0.3.2",
- ch.kuramo.javie.effects;bundle-version="0.3.2",
+ ch.kuramo.javie.api;bundle-version="0.3.3",
+ ch.kuramo.javie.core;bundle-version="0.3.3",
+ ch.kuramo.javie.effects;bundle-version="0.3.3",
  com.google.code.guice;bundle-version="2.0.0",
  javassist;bundle-version="3.11.0",
  org.scannotation;bundle-version="1.0.2",
diff -ruN javie-0.3.2-src/ch.kuramo.javie.app/app.product javie-0.3.3-src/ch.kuramo.javie.app/app.product
--- javie-0.3.2-src/ch.kuramo.javie.app/app.product	2010-02-06 19:53:15.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.app/app.product	2010-02-16 03:30:21.000000000 +0900
@@ -1,11 +1,11 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?pde version="3.5"?>
 
-<product name="Javie" id="ch.kuramo.javie.app.product" application="ch.kuramo.javie.app.application" version="0.3.2.qualifier" useFeatures="false" includeLaunchers="true">
+<product name="Javie" id="ch.kuramo.javie.app.product" application="ch.kuramo.javie.app.application" version="0.3.3.qualifier" useFeatures="false" includeLaunchers="true">
 
    <aboutInfo>
       <text>
-         Javie 0.3.2
+         Javie 0.3.3
 Copyright (c) 2009,2010 Yoshikazu Kuramochi
 All rights reserved.
 
@@ -43,6 +43,7 @@
       </win>
    </launcher>
 
+
    <vm>
    </vm>
 
diff -ruN javie-0.3.2-src/ch.kuramo.javie.app/plugin.xml javie-0.3.3-src/ch.kuramo.javie.app/plugin.xml
--- javie-0.3.2-src/ch.kuramo.javie.app/plugin.xml	2010-02-06 19:53:15.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.app/plugin.xml	2010-02-16 03:30:21.000000000 +0900
@@ -13,7 +13,7 @@
          </property>
          <property
                name="aboutText"
-               value="Javie 0.3.2&#x0A;Copyright (c) 2009,2010 Yoshikazu Kuramochi&#x0A;All rights reserved.&#x0A;&#x0A;This product include third party software:&#x0A;  Eclipse RCP: http://www.eclipse.org/&#x0A;  FreeType2: http://www.freetype.org/&#x0A;  FTGL: http://sourceforge.net/projects/ftgl/&#x0A;  Guice: http://code.google.com/p/google-guice/&#x0A;  Vecmath: https://vecmath.dev.java.net/&#x0A;  Javassist: http://www.csg.is.titech.ac.jp/~chiba/javassist/&#x0A;  JOGL: http://kenai.com/projects/jogl/&#x0A;  JSONIC: http://jsonic.sourceforge.jp/&#x0A;  JNA: https://jna.dev.java.net/&#x0A;  Scannotation: http://sourceforge.net/projects/scannotation/&#x0A;  SLF4J: http://www.slf4j.org/&#x0A;  Rhino: http://www.mozilla.org/rhino/&#x0A;  Tritonus: http://www.tritonus.org/">
+               value="Javie 0.3.3&#x0A;Copyright (c) 2009,2010 Yoshikazu Kuramochi&#x0A;All rights reserved.&#x0A;&#x0A;This product include third party software:&#x0A;  Eclipse RCP: http://www.eclipse.org/&#x0A;  FreeType2: http://www.freetype.org/&#x0A;  FTGL: http://sourceforge.net/projects/ftgl/&#x0A;  Guice: http://code.google.com/p/google-guice/&#x0A;  Vecmath: https://vecmath.dev.java.net/&#x0A;  Javassist: http://www.csg.is.titech.ac.jp/~chiba/javassist/&#x0A;  JOGL: http://kenai.com/projects/jogl/&#x0A;  JSONIC: http://jsonic.sourceforge.jp/&#x0A;  JNA: https://jna.dev.java.net/&#x0A;  Scannotation: http://sourceforge.net/projects/scannotation/&#x0A;  SLF4J: http://www.slf4j.org/&#x0A;  Rhino: http://www.mozilla.org/rhino/&#x0A;  Tritonus: http://www.tritonus.org/">
          </property>
       </product>
    </extension>
diff -ruN javie-0.3.2-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/Activator.java javie-0.3.3-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/Activator.java
--- javie-0.3.2-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/Activator.java	2010-01-18 11:37:49.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/Activator.java	2010-02-14 11:49:20.000000000 +0900
@@ -98,6 +98,7 @@
 		JsonicBugFix.patch();
 		DragSourceEnhancement.patch();
 		DropTargetEnhancement.patch();
+		TreeViewerEditorEnhancement.patch();
 		ColorDialogBugFix.patch();
 
 		createDefaultConsole();
diff -ruN javie-0.3.2-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/DragSourceEnhancement.java javie-0.3.3-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/DragSourceEnhancement.java
--- javie-0.3.2-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/DragSourceEnhancement.java	2009-12-21 19:46:42.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/DragSourceEnhancement.java	2010-02-14 11:46:41.000000000 +0900
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Yoshikazu Kuramochi
+ * Copyright (c) 2009,2010 Yoshikazu Kuramochi
  * All rights reserved.
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -70,7 +70,7 @@
 							 + "		});"
 							 + "org.eclipse.swt.graphics.ImageData imageData = new org.eclipse.swt.graphics.ImageData(1, 1, 1, palette, 1, new byte[1]);"
 							 + "imageData.transparentPixel = 0;"
-							 + "emptyImage = new org.eclipse.swt.graphics.Image($0.getDisplay(), imageData);";
+							 + "emptyImage = new org.eclipse.swt.graphics.Image(getDisplay(), imageData);";
 
 					cstr.insertAfter(src);
 				}
diff -ruN javie-0.3.2-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/TreeViewerEditorEnhancement.java javie-0.3.3-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/TreeViewerEditorEnhancement.java
--- javie-0.3.2-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/TreeViewerEditorEnhancement.java	1970-01-01 09:00:00.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/TreeViewerEditorEnhancement.java	2010-02-14 11:49:20.000000000 +0900
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2010 Yoshikazu Kuramochi
+ * All rights reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package ch.kuramo.javie.app;
+
+import javassist.CannotCompileException;
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.CtMethod;
+import javassist.LoaderClassPath;
+import javassist.NotFoundException;
+
+import org.eclipse.jface.viewers.CellEditor;
+
+import ch.kuramo.javie.core.JavieRuntimeException;
+
+public class TreeViewerEditorEnhancement {
+
+	public static void patch() {
+		try {
+			ClassLoader loader = CellEditor.class.getClassLoader();
+
+			ClassPool pool = new ClassPool();
+			pool.appendClassPath(new LoaderClassPath(loader));
+
+			CtClass targetClass = pool.get("org.eclipse.jface.viewers.TreeViewerEditor");
+			CtMethod targetMethod = targetClass.getDeclaredMethod("setLayoutData");
+
+			String src
+					= "if ($1.minimumHeight == org.eclipse.swt.SWT.DEFAULT) {"
+					+ "		treeEditor.minimumHeight = 0;"
+					+ "}";
+
+			targetMethod.insertAfter(src);
+
+			targetClass.toClass(loader, null);
+
+		} catch (NotFoundException e) {
+			throw new JavieRuntimeException(e);
+		} catch (CannotCompileException e) {
+			throw new JavieRuntimeException(e);
+		}
+	}
+
+}
diff -ruN javie-0.3.2-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/actions/SequenceOutputAction.java javie-0.3.3-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/actions/SequenceOutputAction.java
--- javie-0.3.2-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/actions/SequenceOutputAction.java	2010-01-12 04:36:27.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/actions/SequenceOutputAction.java	2010-02-13 11:50:59.000000000 +0900
@@ -199,8 +199,7 @@
 
 			vrContext.activate();
 			try {
-				// TODO これはループの外で良いんだっけ？　良いはずだが自信無し。要確認
-				comp.prepareExpression(vrContext.createInitialExpressionScope());
+				comp.prepareExpression(vrContext.createInitialExpressionScope(comp));
 
 				for (long i = 0; i < numFrames; ++i) {
 					if (monitor.isCanceled()) {
diff -ruN javie-0.3.2-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/actions/WaveOutputAction.java javie-0.3.3-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/actions/WaveOutputAction.java
--- javie-0.3.2-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/actions/WaveOutputAction.java	2010-01-29 18:34:04.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/actions/WaveOutputAction.java	2010-02-13 11:50:59.000000000 +0900
@@ -206,8 +206,7 @@
 
 			arContext.activate();
 			try {
-				// TODO これはループの外で良いんだっけ？　良いはずだが自信無し。要確認
-				comp.prepareExpression(arContext.createInitialExpressionScope());
+				comp.prepareExpression(arContext.createInitialExpressionScope(comp));
 
 				long videoFrameNumber = 0;
 				for (long i = 0; i < totalFrames; ) {
diff -ruN javie-0.3.2-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/player/AudioThread.java javie-0.3.3-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/player/AudioThread.java
--- javie-0.3.2-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/player/AudioThread.java	2010-01-29 18:32:43.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/player/AudioThread.java	2010-02-13 11:50:59.000000000 +0900
@@ -167,7 +167,7 @@
 						try {
 							// TODO prepareExpressionはプロジェクトに構造的な変更があった場合のみ行えばよい。
 							Composition comp = ((CompositionItem) _mediaItem).getComposition();
-							comp.prepareExpression(_arContext.createInitialExpressionScope());
+							comp.prepareExpression(_arContext.createInitialExpressionScope(comp));
 
 							ab = input.getAudioChunk();
 						} catch (Exception e) {
diff -ruN javie-0.3.2-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/player/MediaPlayer.java javie-0.3.3-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/player/MediaPlayer.java
--- javie-0.3.2-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/player/MediaPlayer.java	2010-01-18 11:47:49.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/player/MediaPlayer.java	2010-02-15 23:56:30.000000000 +0900
@@ -90,6 +90,8 @@
 
 	private Time _frameDuration;
 
+	private volatile boolean _hidden = true;
+
 	private volatile boolean _dirty;
 
 
@@ -417,6 +419,21 @@
 		}
 	}
 
+	public void setHidden(boolean hidden) {
+		if (_hidden != hidden) {
+			_hidden = hidden;
+
+			if (hidden && !_timeKeeper.isPaused()) {
+				pause();
+			} else if (!hidden && _dirty) {
+				_dirty = false;
+				if (_videoCanvas != null) {
+					_videoCanvas.forceRender();
+				}
+			}
+		}
+	}
+
 
 	private final ListenerList _playerLinkListeners = new ListenerList();
 
@@ -439,21 +456,17 @@
 		Time time = event.time;
 
 		_timeKeeper.setTime(time);
-		if (_audioThread != null && !_timeKeeper.isPaused()) {
-			_audioThread.setTime(time);
-		}
-		if (_videoCanvas != null && _timeKeeper.isPaused()) {
-			_videoCanvas.forceRender();
+		if (_hidden) {
+			_dirty = true;
+			notifyPlayerTime(time);
+		} else {
+			if (_audioThread != null && !_timeKeeper.isPaused()) {
+				_audioThread.setTime(time);
+			}
+			if (_videoCanvas != null && _timeKeeper.isPaused()) {
+				_videoCanvas.forceRender();
+			}
 		}
-
-		// オーディオのみの場合は次の処理が必要になるはずだが、
-		// プレーヤーをリンクするのはコンポジションの場合だけなので、
-		// オーディオのみということは無いはず。
-		//
-		//if (_videoCanvas == null && _timeKeeper.isPaused()) {
-		//	updateScale();
-		//	firePlayerTime();
-		//}
 	}
 
 	public void handleProjectEvent(ProjectEvent event) {
@@ -478,7 +491,7 @@
 
 			case SHADOW_OPERATION_EXECUTION:
 				// このイベントは ShadowOperationRunner のスレッド上で送信される。
-				if (isSameProject(event.getProjectManager().getShadow()) && _dirty) {
+				if (isSameProject(event.getProjectManager().getShadow()) && !_hidden && _dirty) {
 					_dirty = false;
 					if (_videoCanvas != null && _timeKeeper.isPaused()) {
 						_videoCanvas.forceRender();
diff -ruN javie-0.3.2-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/player/VideoCanvas.java javie-0.3.3-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/player/VideoCanvas.java
--- javie-0.3.2-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/player/VideoCanvas.java	2010-01-19 09:20:05.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/player/VideoCanvas.java	2010-02-13 11:50:59.000000000 +0900
@@ -655,7 +655,7 @@
 					try {
 						// TODO prepareExpressionはプロジェクトに構造的な変更があった場合のみ行えばよい。
 						Composition comp = ((CompositionItem) _mediaItem).getComposition();
-						comp.prepareExpression(_vrContext.createInitialExpressionScope());
+						comp.prepareExpression(_vrContext.createInitialExpressionScope(comp));
 
 						vb = _mediaInput.getVideoFrameImage();
 					} catch (Exception e) {
diff -ruN javie-0.3.2-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/project/NewTextLayerOperation.java javie-0.3.3-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/project/NewTextLayerOperation.java
--- javie-0.3.2-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/project/NewTextLayerOperation.java	2009-12-21 19:46:42.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/project/NewTextLayerOperation.java	2010-02-12 00:42:21.000000000 +0900
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Yoshikazu Kuramochi
+ * Copyright (c) 2009,2010 Yoshikazu Kuramochi
  * All rights reserved.
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -25,14 +25,24 @@
 
 import ch.kuramo.javie.api.Size2i;
 import ch.kuramo.javie.api.Vec3d;
+import ch.kuramo.javie.app.InjectorHolder;
 import ch.kuramo.javie.core.LayerComposition;
 import ch.kuramo.javie.core.TextLayer;
+import ch.kuramo.javie.core.services.Font;
+import ch.kuramo.javie.core.services.FontList;
 import ch.kuramo.javie.core.services.ProjectElementFactory;
 
+import com.google.inject.Inject;
+
 public class NewTextLayerOperation extends AbstractNewLayerOperation<TextLayer> {
 
+	@Inject
+	private FontList _fontList;
+
+
 	public NewTextLayerOperation(ProjectManager projectManager, LayerComposition comp) {
 		super(projectManager, comp, "新規テキスト");
+		InjectorHolder.getInjector().injectMembers(this);
 	}
 
 	@Override
@@ -42,6 +52,11 @@
 		TextLayer layer = factory.newTextLayer();
 		layer.setName(projectManager.getUnusedLayerName(comp, "テキスト"));
 
+		Font font = _fontList.defaultFont();
+		if (font != null) {
+			layer.getFont().clearKeyframes(font.psName);
+		}
+
 		Size2i compSize = comp.getSize();
 		Vec3d compCenter = new Vec3d(compSize.width/2d, compSize.height/2d);
 		layer.getPosition().clearKeyframes(compCenter);
diff -ruN javie-0.3.2-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/views/LayerCompositionView.java javie-0.3.3-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/views/LayerCompositionView.java
--- javie-0.3.2-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/views/LayerCompositionView.java	2010-01-29 23:42:51.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/views/LayerCompositionView.java	2010-02-13 11:50:59.000000000 +0900
@@ -1286,7 +1286,7 @@
 		_collector.setTime(time);
 
 		// TODO prepareExpressionはプロジェクトに構造的な変更があった場合のみ行えばよい。
-		_composition.prepareExpression(_collector.createInitialExpressionScope());
+		_composition.prepareExpression(_collector.createInitialExpressionScope(_composition));
 
 		_treeViewer.setData(ANIMATABLE_VALUES, _collector.collect());
 		updateProperties();
diff -ruN javie-0.3.2-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/views/MediaPlayerView.java javie-0.3.3-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/views/MediaPlayerView.java
--- javie-0.3.2-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/views/MediaPlayerView.java	2010-01-19 20:01:14.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/views/MediaPlayerView.java	2010-02-15 23:56:30.000000000 +0900
@@ -28,8 +28,8 @@
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.ui.IActionBars;
-import org.eclipse.ui.IPartListener;
-import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IPartListener2;
+import org.eclipse.ui.IWorkbenchPartReference;
 import org.eclipse.ui.part.ViewPart;
 
 import ch.kuramo.javie.app.player.MediaPlayer;
@@ -42,7 +42,7 @@
 import ch.kuramo.javie.core.CompositionItem;
 import ch.kuramo.javie.core.MediaItem;
 
-public class MediaPlayerView extends ViewPart implements IPartListener {
+public class MediaPlayerView extends ViewPart implements IPartListener2 {
 
 	public static final String ID = "ch.kuramo.javie.app.views.mediaPlayerView";
 
@@ -132,25 +132,41 @@
 		return _pinAction.isChecked();
 	}
 
-	public void partClosed(IWorkbenchPart part) {
-		if (part == this) {
+	public void partOpened(IWorkbenchPartReference partRef) {
+		// nothing to do
+	}
+
+	public void partClosed(IWorkbenchPartReference partRef) {
+		if (partRef.getPart(false) == this) {
 			_mediaPlayer.close();
 		}
 	}
 
-	public void partOpened(IWorkbenchPart part) {
+	public void partVisible(IWorkbenchPartReference partRef) {
+		if (partRef.getPart(false) == this) {
+			_mediaPlayer.setHidden(false);
+		}
+	}
+
+	public void partHidden(IWorkbenchPartReference partRef) {
+		if (partRef.getPart(false) == this) {
+			_mediaPlayer.setHidden(true);
+		}
+	}
+
+	public void partActivated(IWorkbenchPartReference partRef) {
 		// nothing to do
 	}
 
-	public void partActivated(IWorkbenchPart part) {
+	public void partDeactivated(IWorkbenchPartReference partRef) {
 		// nothing to do
 	}
 
-	public void partDeactivated(IWorkbenchPart part) {
+	public void partBroughtToTop(IWorkbenchPartReference partRef) {
 		// nothing to do
 	}
 
-	public void partBroughtToTop(IWorkbenchPart part) {
+	public void partInputChanged(IWorkbenchPartReference partRef) {
 		// nothing to do
 	}
 
diff -ruN javie-0.3.2-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/views/layercomp/LayerElement.java javie-0.3.3-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/views/layercomp/LayerElement.java
--- javie-0.3.2-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/views/layercomp/LayerElement.java	2010-01-21 15:49:00.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/views/layercomp/LayerElement.java	2010-02-12 15:34:32.000000000 +0900
@@ -354,7 +354,9 @@
 					modeEditor.setLabelProvider(new BlendModeLabelProvider());
 					modeEditor.setActivationStyle(ComboBoxViewerCellEditor.DROP_DOWN_ON_PROGRAMMATIC_ACTIVATION);
 
-					((Combo) modeEditor.getControl()).addSelectionListener(new SelectionAdapter() {
+					Combo combo = (Combo) modeEditor.getControl();
+					combo.setVisibleItemCount(35);
+					combo.addSelectionListener(new SelectionAdapter() {
 						public void widgetSelected(SelectionEvent e) {
 							setCellEditorValue(LayerCompositionView.MODE_COL, modeEditor.getValue());
 						}
@@ -413,7 +415,7 @@
 				return (parent != null) ? parent : NO_PARENT;
 
 			default:
-				return true;
+				return null;
 		}
 	}
 
diff -ruN javie-0.3.2-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/views/layercomp/TextElement.java javie-0.3.3-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/views/layercomp/TextElement.java
--- javie-0.3.2-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/views/layercomp/TextElement.java	2009-12-21 19:46:42.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/views/layercomp/TextElement.java	2010-02-15 22:04:41.000000000 +0900
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Yoshikazu Kuramochi
+ * Copyright (c) 2009,2010 Yoshikazu Kuramochi
  * All rights reserved.
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -25,6 +25,7 @@
 
 import ch.kuramo.javie.app.views.LayerCompositionView;
 import ch.kuramo.javie.core.Layer;
+import ch.kuramo.javie.core.TextLayer;
 
 public class TextElement extends Element {
 
@@ -55,9 +56,12 @@
 		if (children == null) {
 			Layer layer = ((LayerElement) parent).layer;
 			children = new Element[] {
-					new LayerAnimatableValueElement(this, layer, "sourceText", "ソーステキスト"),
+					new TextSourceElement(this, (TextLayer) layer),
+					new TextFontElement(this, (TextLayer) layer),
 					new LayerAnimatableValueElement(this, layer, "fontSize", "フォントサイズ", "px"),
-					new LayerAnimatableValueElement(this, layer, "fillColor", "塗りのカラー")
+					new LayerAnimatableValueElement(this, layer, "fillColor", "塗りのカラー"),
+					new LayerAnimatableValueElement(this, layer, "horizontalAlignment", "整列"),
+					new TextLeadingElement(this, (TextLayer) layer)
 			};
 		}
 		return children;
diff -ruN javie-0.3.2-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/views/layercomp/TextFontElement.java javie-0.3.3-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/views/layercomp/TextFontElement.java
--- javie-0.3.2-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/views/layercomp/TextFontElement.java	1970-01-01 09:00:00.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/views/layercomp/TextFontElement.java	2010-02-12 15:34:32.000000000 +0900
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2010 Yoshikazu Kuramochi
+ * All rights reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package ch.kuramo.javie.app.views.layercomp;
+
+import org.eclipse.jface.viewers.ArrayContentProvider;
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.widgets.Combo;
+
+import ch.kuramo.javie.app.InjectorHolder;
+import ch.kuramo.javie.app.PropertyUtil;
+import ch.kuramo.javie.app.views.ComboBoxViewerCellEditor;
+import ch.kuramo.javie.app.views.LayerCompositionView;
+import ch.kuramo.javie.core.AnimatableString;
+import ch.kuramo.javie.core.TextLayer;
+import ch.kuramo.javie.core.services.Font;
+import ch.kuramo.javie.core.services.FontList;
+
+import com.google.inject.Inject;
+
+public class TextFontElement extends LayerAnimatableValueElement {
+
+	public TextFontElement(Element parent, TextLayer layer) {
+		super(parent, layer, "font", "フォント");
+	}
+
+	protected AnimatableValueElementDelegate<?> createDelegate() {
+		AnimatableString avalue = PropertyUtil.getProperty(layer, property);
+		return new TextFontElementDelegate(this, name, avalue);
+	}
+
+}
+
+class TextFontElementDelegate extends AnimatableStringElementDelegate {
+
+	private ComboBoxViewerCellEditor editor;
+
+	@Inject
+	private FontList fontList;
+
+
+	TextFontElementDelegate(
+			AnimatableValueElement element, String name, AnimatableString avalue) {
+
+		super(element, name, avalue);
+		InjectorHolder.getInjector().injectMembers(this);
+	}
+
+	protected void drawValue(GC gc, int x, int y, int height, boolean focused) {
+		Font font = fontList.get(value);
+		drawValue(gc, x, y, height, focused, (font != null) ? font.fullName : "      ");
+	}
+
+	public CellEditor getCellEditor(int columnIndex) {
+		if (columnIndex == LayerCompositionView.VALUE_COL) {
+			if (editor == null) {
+				editor = new ComboBoxViewerCellEditor(element.viewer.getTree(), SWT.READ_ONLY);
+				editor.setContenProvider(ArrayContentProvider.getInstance());
+				editor.setLabelProvider(new FontLabelProvider());
+				editor.setActivationStyle(ComboBoxViewerCellEditor.DROP_DOWN_ON_PROGRAMMATIC_ACTIVATION);
+
+				Combo combo = (Combo) editor.getControl();
+				combo.setVisibleItemCount(35);
+				combo.addSelectionListener(new SelectionAdapter() {
+					public void widgetSelected(SelectionEvent e) {
+						setCellEditorValue(LayerCompositionView.VALUE_COL, editor.getValue());
+					}
+				});
+			}
+			editor.setInput(fontList.list());
+			return editor;
+
+		} else {
+			return super.getCellEditor(columnIndex);
+		}
+	}
+
+	public Object getCellEditorValue(int columnIndex) {
+		if (columnIndex == LayerCompositionView.VALUE_COL) {
+			return fontList.get(value);
+		} else {
+			return super.getCellEditorValue(columnIndex);
+		}
+	}
+
+	public void setCellEditorValue(int columnIndex, Object value) {
+		if (columnIndex == LayerCompositionView.VALUE_COL) {
+			value = (value != null) ? ((Font) value).psName : "";
+		}
+		super.setCellEditorValue(columnIndex, value);
+	}
+
+	private static class FontLabelProvider extends LabelProvider {
+		public String getText(Object element) {
+			return ((Font) element).fullName;
+		}
+	}
+
+}
diff -ruN javie-0.3.2-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/views/layercomp/TextLeadingElement.java javie-0.3.3-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/views/layercomp/TextLeadingElement.java
--- javie-0.3.2-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/views/layercomp/TextLeadingElement.java	1970-01-01 09:00:00.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/views/layercomp/TextLeadingElement.java	2010-02-15 22:09:29.000000000 +0900
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2010 Yoshikazu Kuramochi
+ * All rights reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package ch.kuramo.javie.app.views.layercomp;
+
+import java.util.Map;
+
+import org.eclipse.swt.graphics.GC;
+
+import ch.kuramo.javie.app.PropertyUtil;
+import ch.kuramo.javie.app.views.LayerCompositionView;
+import ch.kuramo.javie.core.AnimatableDouble;
+import ch.kuramo.javie.core.AnimatableInteger;
+import ch.kuramo.javie.core.AnimatableValue;
+import ch.kuramo.javie.core.TextLayer;
+
+public class TextLeadingElement extends LayerAnimatableValueElement {
+
+	public TextLeadingElement(Element parent, TextLayer layer) {
+		super(parent, layer, "leading", "行送り", "px");
+	}
+
+	protected AnimatableValueElementDelegate<?> createDelegate() {
+		AnimatableDouble avalue = PropertyUtil.getProperty(layer, property);
+		return new TextLeadingElementDelegate(this, (TextLayer)layer, name, avalue, unit);
+	}
+
+}
+
+class TextLeadingElementDelegate extends AnimatableDoubleElementDelegate {
+
+	private final AnimatableInteger fontSizeAvalue;
+
+
+	public TextLeadingElementDelegate(
+			AnimatableValueElement element, TextLayer layer,
+			String name, AnimatableDouble avalue, String unit) {
+
+		super(element, name, avalue, unit);
+		fontSizeAvalue = PropertyUtil.getProperty(layer, "fontSize");
+	}
+
+	protected void drawValue(GC gc, int x, int y, int height, boolean focused) {
+		if (value < 0) {
+			drawValue(gc, x, y, height, focused, AUTO);
+		} else {
+			super.drawValue(gc, x, y, height, focused);
+		}
+	}
+
+	protected Double dragGesture(double dx, double dy) {
+		if (value < 0 && originalValue < 0) {
+			originalValue = autoValue();
+		}
+		return Math.max(0, super.dragGesture(dx, dy));
+	}
+
+	public Object getCellEditorValue(int columnIndex) {
+		if (columnIndex == LayerCompositionView.VALUE_COL && value < 0) {
+			return autoValueAsCellEditorValue();
+		} else {
+			return super.getCellEditorValue(columnIndex);
+		}
+	}
+
+	public void setCellEditorValue(int columnIndex, Object value) {
+		if (columnIndex == LayerCompositionView.VALUE_COL) {
+			value = ((String) value).trim();
+			if (value.equals(autoValueAsCellEditorValue()) || value.equals(AUTO)) {
+				value = "-1";
+			}
+			super.setCellEditorValue(columnIndex, value);
+		}
+	}
+
+	private double autoValue() {
+		@SuppressWarnings("unchecked")
+		Map<AnimatableValue<?>, ?> animatableValues = (Map<AnimatableValue<?>, ?>)
+				element.viewer.getData(LayerCompositionView.ANIMATABLE_VALUES);
+
+		int fontSize = (Integer) animatableValues.get(fontSizeAvalue);
+		return fontSize * 1.2;
+	}
+
+	private static final String AUTO = "自動";
+
+	private String autoValueAsCellEditorValue() {
+		return String.format("%s (%s)", AUTO, formatValue(autoValue(), 4));
+	}
+
+}
diff -ruN javie-0.3.2-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/views/layercomp/TextSourceElement.java javie-0.3.3-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/views/layercomp/TextSourceElement.java
--- javie-0.3.2-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/views/layercomp/TextSourceElement.java	1970-01-01 09:00:00.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.app/src/main/java/ch/kuramo/javie/app/views/layercomp/TextSourceElement.java	2010-02-13 16:29:12.000000000 +0900
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2010 Yoshikazu Kuramochi
+ * All rights reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package ch.kuramo.javie.app.views.layercomp;
+
+import java.util.regex.Pattern;
+
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.TextCellEditor;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Text;
+
+import ch.kuramo.javie.app.PropertyUtil;
+import ch.kuramo.javie.app.views.LayerCompositionView;
+import ch.kuramo.javie.core.AnimatableString;
+import ch.kuramo.javie.core.TextLayer;
+
+public class TextSourceElement extends LayerAnimatableValueElement {
+
+	public TextSourceElement(Element parent, TextLayer layer) {
+		super(parent, layer, "sourceText", "ソーステキスト");
+	}
+
+	protected AnimatableValueElementDelegate<?> createDelegate() {
+		AnimatableString avalue = PropertyUtil.getProperty(layer, property);
+		return new TextSourceElementDelegate(this, name, avalue);
+	}
+
+}
+
+class TextSourceElementDelegate extends AnimatableStringElementDelegate {
+
+	private static final String EDITOR_KEY = "TextSourceElementDelegate.TextCellEditor";
+
+
+	public TextSourceElementDelegate(
+			AnimatableValueElement element, String name, AnimatableString avalue) {
+
+		super(element, name, avalue);
+	}
+
+	public CellEditor getCellEditor(int columnIndex) {
+		if (columnIndex == LayerCompositionView.VALUE_COL) {
+			TextCellEditor editor = (TextCellEditor) element.viewer.getData(EDITOR_KEY);
+			if (editor == null) {
+				editor = new TextCellEditor(element.viewer.getTree(), SWT.MULTI | SWT.V_SCROLL | SWT.BORDER) {
+					public LayoutData getLayoutData() {
+						LayoutData data = super.getLayoutData();
+						data.minimumHeight = 80;
+						data.verticalAlignment = SWT.TOP;
+						return data;
+					}
+				};
+				Control control = editor.getControl();
+				control.setBackground(control.getDisplay().getSystemColor(SWT.COLOR_WHITE));
+				element.viewer.setData(EDITOR_KEY, editor);
+			}
+			return editor;
+
+		} else {
+			return super.getCellEditor(columnIndex);
+		}
+	}
+
+	private static final Pattern LF = Pattern.compile("\\n");
+	private static final Pattern CR_OR_CRLF = Pattern.compile("\\r\\n?");
+
+	public Object getCellEditorValue(int columnIndex) {
+		if (columnIndex == LayerCompositionView.VALUE_COL) {
+			return LF.matcher(value).replaceAll(Text.DELIMITER);
+		} else {
+			return super.getCellEditorValue(columnIndex);
+		}
+	}
+
+	public void setCellEditorValue(int columnIndex, Object value) {
+		if (columnIndex == LayerCompositionView.VALUE_COL) {
+			value = CR_OR_CRLF.matcher((String) value).replaceAll("\n");
+		}
+		super.setCellEditorValue(columnIndex, value);
+	}
+
+}
diff -ruN javie-0.3.2-src/ch.kuramo.javie.core/META-INF/MANIFEST.MF javie-0.3.3-src/ch.kuramo.javie.core/META-INF/MANIFEST.MF
--- javie-0.3.2-src/ch.kuramo.javie.core/META-INF/MANIFEST.MF	2010-02-06 19:53:15.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.core/META-INF/MANIFEST.MF	2010-02-16 03:30:21.000000000 +0900
@@ -2,14 +2,14 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: Javie Core Plug-in
 Bundle-SymbolicName: ch.kuramo.javie.core;singleton:=true
-Bundle-Version: 0.3.2.qualifier
+Bundle-Version: 0.3.3.qualifier
 Bundle-Vendor: rakusan
 Export-Package: ch.kuramo.javie.core,
  ch.kuramo.javie.core.misc,
  ch.kuramo.javie.core.output,
  ch.kuramo.javie.core.services
 Bundle-RequiredExecutionEnvironment: J2SE-1.5
-Require-Bundle: ch.kuramo.javie.api;bundle-version="0.3.2",
+Require-Bundle: ch.kuramo.javie.api;bundle-version="0.3.3",
  com.google.code.guice;bundle-version="2.0.0",
  javassist;bundle-version="3.11.0",
  org.scannotation;bundle-version="1.0.2",
diff -ruN javie-0.3.2-src/ch.kuramo.javie.core/src/ftgl/README.txt javie-0.3.3-src/ch.kuramo.javie.core/src/ftgl/README.txt
--- javie-0.3.2-src/ch.kuramo.javie.core/src/ftgl/README.txt	2009-12-28 21:16:57.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.core/src/ftgl/README.txt	2010-02-12 05:12:29.000000000 +0900
@@ -10,7 +10,7 @@
 
 [FTGL]
   * http://sourceforge.net/projects/ftgl/ から ftgl-2.1.3-rc5.tar.gz を入手し展開します
-  * src/FTFont 内のファイルにJavie用パッチ ftgl-javie.patch を適用します
+  * Javie用パッチ ftgl-javie.patch を適用します
   * freetype2をビルドした時のprefixと同じパスを--prefixと--with-ft-prefixに指定し
     configureを実行します
   * make 及び make install を行います
@@ -29,7 +29,7 @@
 
 [FTGL]
   * http://sourceforge.net/projects/ftgl/ から ftgl-2.1.3-rc5.tar.gz を入手し展開します
-  * src/FTFont 内のファイルにJavie用パッチ ftgl-javie.patch を適用します
+  * Javie用パッチ ftgl-javie.patch を適用します
   * msvc/vc8/ftgl.sln を開きます
   * ftgl_dllのプロパティを次のように変更します
     * C/C++ -> コード生成 -> ランタイムライブラリ: MTに変更します（Debug版はMTd）
diff -ruN javie-0.3.2-src/ch.kuramo.javie.core/src/ftgl/ftgl-javie.patch javie-0.3.3-src/ch.kuramo.javie.core/src/ftgl/ftgl-javie.patch
--- javie-0.3.2-src/ch.kuramo.javie.core/src/ftgl/ftgl-javie.patch	2009-12-19 18:48:56.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.core/src/ftgl/ftgl-javie.patch	2010-02-12 13:06:03.000000000 +0900
@@ -1,5 +1,42 @@
---- FTBufferFont.cpp.orig	2008-06-12 18:52:03.000000000 +0900
-+++ FTBufferFont.cpp	2009-11-20 08:32:28.000000000 +0900
+Binary files ftgl-2.1.3~rc5.orig/src/._FTFace.cpp and ftgl-2.1.3~rc5/src/._FTFace.cpp differ
+diff -ruN ftgl-2.1.3~rc5.orig/src/FTFace.cpp ftgl-2.1.3~rc5/src/FTFace.cpp
+--- ftgl-2.1.3~rc5.orig/src/FTFace.cpp	2008-06-09 21:51:48.000000000 +0900
++++ ftgl-2.1.3~rc5/src/FTFace.cpp	2010-02-12 12:57:01.000000000 +0900
+@@ -31,17 +31,29 @@
+ 
+ #include FT_TRUETYPE_TABLES_H
+ 
++#include <errno.h>
++
+ FTFace::FTFace(const char* fontFilePath, bool precomputeKerning)
+ :   numGlyphs(0),
+     fontEncodingList(0),
+     kerningCache(0),
+     err(0)
+ {
+-    const FT_Long DEFAULT_FACE_INDEX = 0;
+     ftFace = new FT_Face;
+ 
++    FT_Long faceIndex;
++    char* endptr;
++
++    errno = 0;
++    faceIndex = strtol(fontFilePath, &endptr, 10);
++    if (errno == 0 && *endptr == ',') {
++        fontFilePath = endptr + 1;
++    } else {
++        faceIndex = 0;
++    }
++
+     err = FT_New_Face(*FTLibrary::Instance().GetLibrary(), fontFilePath,
+-                      DEFAULT_FACE_INDEX, ftFace);
++                      faceIndex, ftFace);
+     if(err)
+     {
+         delete ftFace;
+diff -ruN ftgl-2.1.3~rc5.orig/src/FTFont/FTBufferFont.cpp ftgl-2.1.3~rc5/src/FTFont/FTBufferFont.cpp
+--- ftgl-2.1.3~rc5.orig/src/FTFont/FTBufferFont.cpp	2008-06-12 18:52:03.000000000 +0900
++++ ftgl-2.1.3~rc5/src/FTFont/FTBufferFont.cpp	2010-02-12 12:56:33.000000000 +0900
 @@ -236,9 +236,9 @@
      // Protect glPixelStorei() calls
      glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
@@ -12,8 +49,64 @@
  
      // Search whether the string is already in a texture we uploaded
      for(int n = 0; n < BUFFER_CACHE_SIZE; n++)
---- FTOutlineFont.cpp.orig	2008-06-09 21:52:07.000000000 +0900
-+++ FTOutlineFont.cpp	2009-11-20 08:32:28.000000000 +0900
+diff -ruN ftgl-2.1.3~rc5.orig/src/FTFont/FTFontGlue.cpp ftgl-2.1.3~rc5/src/FTFont/FTFontGlue.cpp
+--- ftgl-2.1.3~rc5.orig/src/FTFont/FTFontGlue.cpp	2008-06-09 21:52:05.000000000 +0900
++++ ftgl-2.1.3~rc5/src/FTFont/FTFontGlue.cpp	2010-02-12 12:56:33.000000000 +0900
+@@ -225,3 +225,51 @@
+ 
+ FTGL_END_C_DECLS
+ 
++
++
++#include <freetype/ftsnames.h>
++
++FTGL_BEGIN_C_DECLS
++
++FTGL_EXPORT FT_Error
++ft_Init_FreeType( FT_Library  *alibrary )
++{
++	return FT_Init_FreeType(alibrary);
++}
++
++FTGL_EXPORT FT_Error
++ft_Done_FreeType( FT_Library  library )
++{
++	return FT_Done_FreeType(library);
++}
++
++FTGL_EXPORT FT_Error
++ft_New_Face( FT_Library   library,
++			 const char*  filepathname,
++			 FT_Long      face_index,
++			 FT_Face     *aface )
++{
++	return FT_New_Face(library, filepathname, face_index, aface);
++}
++
++FTGL_EXPORT FT_Error
++ft_Done_Face( FT_Face  face )
++{
++	return FT_Done_Face(face);
++}
++
++FTGL_EXPORT FT_UInt
++ft_Get_Sfnt_Name_Count( FT_Face  face )
++{
++	return FT_Get_Sfnt_Name_Count(face);
++}
++
++FTGL_EXPORT FT_Error
++ft_Get_Sfnt_Name( FT_Face       face,
++				  FT_UInt       idx,
++				  FT_SfntName  *aname )
++{
++	return FT_Get_Sfnt_Name(face, idx, aname);
++}
++
++FTGL_END_C_DECLS
+diff -ruN ftgl-2.1.3~rc5.orig/src/FTFont/FTOutlineFont.cpp ftgl-2.1.3~rc5/src/FTFont/FTOutlineFont.cpp
+--- ftgl-2.1.3~rc5.orig/src/FTFont/FTOutlineFont.cpp	2008-06-09 21:52:07.000000000 +0900
++++ ftgl-2.1.3~rc5/src/FTFont/FTOutlineFont.cpp	2010-02-12 12:56:33.000000000 +0900
 @@ -100,8 +100,8 @@
      glDisable(GL_TEXTURE_2D);
      glEnable(GL_LINE_SMOOTH);
@@ -25,8 +118,9 @@
  
      FTPoint tmp = FTFontImpl::Render(string, len,
                                       position, spacing, renderMode);
---- FTTextureFont.cpp.orig	2008-06-09 21:52:12.000000000 +0900
-+++ FTTextureFont.cpp	2009-11-20 08:32:28.000000000 +0900
+diff -ruN ftgl-2.1.3~rc5.orig/src/FTFont/FTTextureFont.cpp ftgl-2.1.3~rc5/src/FTFont/FTTextureFont.cpp
+--- ftgl-2.1.3~rc5.orig/src/FTFont/FTTextureFont.cpp	2008-06-09 21:52:12.000000000 +0900
++++ ftgl-2.1.3~rc5/src/FTFont/FTTextureFont.cpp	2010-02-12 12:56:33.000000000 +0900
 @@ -234,8 +234,8 @@
      // Protect GL_TEXTURE_2D, GL_BLEND and blending functions
      glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT);
diff -ruN javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/AnimatableHorizontalAlignment.java javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/AnimatableHorizontalAlignment.java
--- javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/AnimatableHorizontalAlignment.java	1970-01-01 09:00:00.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/AnimatableHorizontalAlignment.java	2010-02-15 14:31:06.000000000 +0900
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2010 Yoshikazu Kuramochi
+ * All rights reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package ch.kuramo.javie.core;
+
+import java.util.Collection;
+
+public class AnimatableHorizontalAlignment
+		extends AbstractAnimatableEnum<HorizontalAlignment> {
+
+	public AnimatableHorizontalAlignment(
+			HorizontalAlignment staticValue,
+			Collection<Keyframe<HorizontalAlignment>> keyframes,
+			String expression) {
+
+		super(HorizontalAlignment.class, staticValue, keyframes, expression);
+	}
+
+	public AnimatableHorizontalAlignment(HorizontalAlignment staticValue) {
+		super(HorizontalAlignment.class, staticValue);
+	}
+
+}
diff -ruN javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/ExpressionScope.java javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/ExpressionScope.java
--- javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/ExpressionScope.java	2009-12-21 21:43:29.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/ExpressionScope.java	2010-02-13 11:47:48.000000000 +0900
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Yoshikazu Kuramochi
+ * Copyright (c) 2009,2010 Yoshikazu Kuramochi
  * All rights reserved.
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -27,7 +27,7 @@
 
 	ExpressionScope clone();
 
-	ExpressionScope createPrecompositionScope();
+	ExpressionScope createPrecompositionScope(Composition preComp);
 
 	void setThis(Expressionee exprnee);
 
diff -ruN javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/HorizontalAlignment.java javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/HorizontalAlignment.java
--- javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/HorizontalAlignment.java	1970-01-01 09:00:00.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/HorizontalAlignment.java	2010-02-15 14:31:06.000000000 +0900
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2010 Yoshikazu Kuramochi
+ * All rights reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package ch.kuramo.javie.core;
+
+public enum HorizontalAlignment {
+
+	LEFT,
+	CENTER,
+	RIGHT
+
+}
diff -ruN javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/RenderContext.java javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/RenderContext.java
--- javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/RenderContext.java	2009-12-21 21:43:29.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/RenderContext.java	2010-02-13 11:47:48.000000000 +0900
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Yoshikazu Kuramochi
+ * Copyright (c) 2009,2010 Yoshikazu Kuramochi
  * All rights reserved.
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -46,7 +46,7 @@
 	void setTime(Time time);
 
 
-	ExpressionScope createInitialExpressionScope();
+	ExpressionScope createInitialExpressionScope(Composition comp);
 
 	<T> T getExpressionElement(Expressionee exprnee);
 
diff -ruN javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/TextLayer.java javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/TextLayer.java
--- javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/TextLayer.java	2009-12-21 21:43:29.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/TextLayer.java	2010-02-15 14:34:00.000000000 +0900
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Yoshikazu Kuramochi
+ * Copyright (c) 2009,2010 Yoshikazu Kuramochi
  * All rights reserved.
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -32,8 +32,14 @@
 
 	AnimatableString getSourceText();
 
+	AnimatableString getFont();
+
 	AnimatableInteger getFontSize();
 
 	AnimatableColor getFillColor();
 
+	AnimatableHorizontalAlignment getHorizontalAlignment();
+
+	AnimatableDouble getLeading();
+
 }
diff -ruN javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/internal/MediaItemLayerImpl.java javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/internal/MediaItemLayerImpl.java
--- javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/internal/MediaItemLayerImpl.java	2010-01-07 09:10:31.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/internal/MediaItemLayerImpl.java	2010-02-13 11:47:48.000000000 +0900
@@ -136,7 +136,10 @@
 
 		LayerComposition preComp = getPrecomposition();
 		if (preComp != null) {
-			preComp.prepareExpression(scope.createPrecompositionScope());
+			ExpressionScope preCompScope = scope.createPrecompositionScope(preComp);
+			if (preCompScope != null) {
+				preComp.prepareExpression(preCompScope);
+			}
 		}
 	}
 
diff -ruN javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/internal/TextLayerImpl.java javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/internal/TextLayerImpl.java
--- javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/internal/TextLayerImpl.java	2010-01-07 09:11:07.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/internal/TextLayerImpl.java	2010-02-15 19:06:25.000000000 +0900
@@ -23,28 +23,30 @@
 
 package ch.kuramo.javie.core.internal;
 
-import java.io.File;
+import java.util.regex.Pattern;
 
 import net.arnx.jsonic.JSONHint;
-
-import org.mozilla.javascript.Scriptable;
-
 import ch.kuramo.javie.api.Color;
+import ch.kuramo.javie.api.RenderResolution;
 import ch.kuramo.javie.api.Time;
 import ch.kuramo.javie.api.VideoBounds;
 import ch.kuramo.javie.core.AnimatableColor;
+import ch.kuramo.javie.core.AnimatableDouble;
+import ch.kuramo.javie.core.AnimatableHorizontalAlignment;
 import ch.kuramo.javie.core.AnimatableInteger;
 import ch.kuramo.javie.core.AnimatableString;
 import ch.kuramo.javie.core.AudioBuffer;
 import ch.kuramo.javie.core.DepthBuffer;
 import ch.kuramo.javie.core.ExpressionScope;
+import ch.kuramo.javie.core.HorizontalAlignment;
 import ch.kuramo.javie.core.MediaInput;
 import ch.kuramo.javie.core.RenderContext;
 import ch.kuramo.javie.core.TextLayer;
 import ch.kuramo.javie.core.VectorMediaInput;
 import ch.kuramo.javie.core.VideoBuffer;
 import ch.kuramo.javie.core.annotations.ProjectElement;
-import ch.kuramo.javie.core.exprelems.StringProperty;
+import ch.kuramo.javie.core.services.Font;
+import ch.kuramo.javie.core.services.FontList;
 import ch.kuramo.javie.core.services.FontManager;
 import ch.kuramo.javie.core.services.VideoRenderContext;
 import ch.kuramo.javie.core.services.VideoRenderSupport;
@@ -63,10 +65,16 @@
 
 	private AnimatableString _sourceText = new AnimatableString("テキスト");
 
+	private AnimatableString _font = new AnimatableString("");
+
 	private AnimatableInteger _fontSize = new AnimatableInteger(36);
 
 	private AnimatableColor _fillColor = new AnimatableColor(new Color(1, 1, 1));
 
+	private AnimatableHorizontalAlignment _horizontalAlignment = new AnimatableHorizontalAlignment(HorizontalAlignment.LEFT);
+
+	private AnimatableDouble _leading = new AnimatableDouble(-1.0);
+
 	@Inject
 	private VideoRenderContext _vrContext;
 
@@ -74,6 +82,9 @@
 	private VideoRenderSupport _vrSupport;
 
 	@Inject
+	private FontList _fontList;
+
+	@Inject
 	private FontManager _fontManager;
 
 
@@ -108,6 +119,14 @@
 		_sourceText = sourceText;
 	}
 
+	public AnimatableString getFont() {
+		return _font;
+	}
+
+	public void setFont(AnimatableString font) {
+		_font = font;
+	}
+
 	public AnimatableInteger getFontSize() {
 		return _fontSize;
 	}
@@ -124,12 +143,32 @@
 		_fillColor = fillColor;
 	}
 
+	public AnimatableHorizontalAlignment getHorizontalAlignment() {
+		return _horizontalAlignment;
+	}
+
+	public void setHorizontalAlignment(
+			AnimatableHorizontalAlignment horizontalAlignment) {
+		_horizontalAlignment = horizontalAlignment;
+	}
+
+	public AnimatableDouble getLeading() {
+		return _leading;
+	}
+
+	public void setLeading(AnimatableDouble leading) {
+		_leading = leading;
+	}
+
 	@Override
 	public void prepareExpression(ExpressionScope scope) {
 		super.prepareExpression(scope);
 		scope.assignTo(_sourceText);
+		scope.assignTo(_font);
 		scope.assignTo(_fontSize);
 		scope.assignTo(_fillColor);
+		scope.assignTo(_horizontalAlignment);
+		scope.assignTo(_leading);
 	}
 
 	@Override
@@ -143,11 +182,17 @@
 			super(renderContext);
 		}
 
-		public StringProperty getSourceText()	{ return elem(_sourceText); }
-		public Scriptable getFontSize()			{ return elem(_fontSize); }
-		public Scriptable[] getFillColor()		{ return elem(_fillColor); }
+		public Object getSourceText()			{ return elem(_sourceText); }
+		public Object getFont()					{ return elem(_font); }
+		public Object getFontSize()				{ return elem(_fontSize); }
+		public Object getFillColor()			{ return elem(_fillColor); }
+		public Object getHorizontalAlignment()	{ return elem(_horizontalAlignment); }
+		public Object getLeading()				{ return elem(_leading); }
 	}
 
+
+	private static final Pattern LF = Pattern.compile("\n");
+
 	private class TextInput implements VectorMediaInput {
 
 		public void dispose() {
@@ -176,32 +221,87 @@
 			}
 
 			String sourceText = _sourceText.value(_vrContext);
+			String psName = _font.value(_vrContext);
+			int fontSize = _fontSize.value(_vrContext);
+			FTGLfont font = getFont(psName, fontSize);
 
 			// TODO サイズ0のVideoBoundsを返すとエラーになるので
 			//      暫定的な対処として (1, 1) を返しているが、もっと適切な方法を考える。
 			//      (プレビュー解像度がFULL以外の場合はこの対処ではエラーになるなど、不完全)
-			if (sourceText.length() == 0) {
+			if (sourceText.length() == 0 || font == null) {
 				return new VideoBounds(1, 1);
 			}
 
+			HorizontalAlignment halign = _horizontalAlignment.value(_vrContext);
+
+			double leading = _leading.value(_vrContext);
+			if (leading < 0) leading = fontSize * 1.2;	// AEは「自動」のときにはフォントサイズの1.2倍になってるっぽい。
+
+			double upper = 0, lower = Double.MAX_VALUE, advanced = 0;
+			String[] texts = LF.split(sourceText);
+
 			// [left, lower, near, right, upper, far]
 			float[] box = new float[6];
-			FTGL.instance.ftglGetFontBBox(getFont(), sourceText, -1, box);
+			for (int i = 0; i < texts.length; ++i) {
+				FTGL.ftglGetFontBBox(font, texts[i], -1, box);
+				upper = Math.max(upper, box[4]);
+				lower = Math.min(lower, box[1]);
+				advanced = Math.max(advanced, FTGL.ftglGetFontAdvance(font, texts[i]));
+			}
+
+			upper = Math.ceil(upper)+1;
+			lower = Math.floor(lower)-1;
+
+			double x;
+			int width;
+
+			switch (halign) {
+				default:
+				case LEFT:
+					x = 0;
+					width = (int)Math.ceil(advanced);
+					break;
+
+				case CENTER:
+					x = -Math.ceil(advanced/2);
+					width = (int)-x*2;
+					break;
+
+				case RIGHT:
+					x = -Math.ceil(advanced);
+					width = (int)-x+1;
+					break;
+			}
 
-			return new VideoBounds(box[0], -box[4],
-					(int) Math.ceil(box[3]-box[0]), (int) Math.ceil(box[4]-box[1]));
+			return new VideoBounds(x, -upper, width, (int)(upper + Math.ceil(leading*(texts.length-1)) - lower));
 		}
 
 		public VideoBuffer getVideoFrameImage() {
-			VideoBounds bounds = _vrContext.getRenderResolution().scale(getVideoFrameBounds());
-			String sourceText = _sourceText.value(_vrContext);
-			Color fillColor = _fillColor.value(_vrContext);
+			RenderResolution resolution = _vrContext.getRenderResolution();
+			VideoBounds bounds = resolution.scale(getVideoFrameBounds());
 
 			VideoBuffer vb = _vrSupport.createVideoBuffer(_vrContext.getColorMode(), bounds);
 			vb.allocateAsTexture();
 			vb.clear();
 
-			_vrSupport.renderText(getFont(), fillColor, sourceText, vb);
+			String psName = _font.value(_vrContext);
+			int fontSize = _fontSize.value(_vrContext);
+			FTGLfont font = getFont(psName, fontSize);
+			if (font != null) {
+				String sourceText = _sourceText.value(_vrContext);
+				Color fillColor = _fillColor.value(_vrContext);
+				HorizontalAlignment halign = _horizontalAlignment.value(_vrContext);
+				double leading = _leading.value(_vrContext);
+
+				String[] texts = LF.split(sourceText);
+
+				if (leading < 0) leading = fontSize * 1.2;
+				leading = resolution.scale(leading);
+
+				double[][] offsets = calcTextOffsets(font, texts, halign, leading, resolution);
+
+				_vrSupport.renderText(font, fillColor, texts, offsets, vb);
+			}
 
 			return vb;
 		}
@@ -210,52 +310,82 @@
 				VideoBuffer resultBuffer, DepthBuffer depthBuffer,
 				double[] mvMatrix, double[] prjMatrix) {
 
-			String sourceText = _sourceText.value(_vrContext);
-			Color fillColor = _fillColor.value(_vrContext);
+			RenderResolution resolution = _vrContext.getRenderResolution();
 
-			_vrSupport.renderText(
-					getFont(), fillColor, sourceText, resultBuffer, depthBuffer, mvMatrix, prjMatrix);
-		}
+			String psName = _font.value(_vrContext);
+			int fontSize = _fontSize.value(_vrContext);
+			FTGLfont font = getFont(psName, fontSize);
+			if (font != null) {
+				String sourceText = _sourceText.value(_vrContext);
+				Color fillColor = _fillColor.value(_vrContext);
+				HorizontalAlignment halign = _horizontalAlignment.value(_vrContext);
+				double leading = _leading.value(_vrContext);
+
+				String[] texts = LF.split(sourceText);
 
-		public AudioBuffer getAudioChunk() {
-			throw new UnsupportedOperationException("audio is not available");
-		}
+				if (leading < 0) leading = fontSize * 1.2;
+				leading = resolution.scale(leading);
 
-		private FTGLfont getFont() {
-			int fontSize = _fontSize.value(_vrContext);
+				double[][] offsets = calcTextOffsets(font, texts, halign, leading, resolution);
 
-			if (_ctcr) {
-				return _fontManager.getPolygonFont(FONTPATH, fontSize);
-			} else {
-				return _fontManager.getBufferFont(FONTPATH, fontSize);
+				_vrSupport.renderText(
+						font, fillColor, texts, offsets, resultBuffer, depthBuffer, mvMatrix, prjMatrix);
 			}
 		}
 
-	}
+		private FTGLfont getFont(String psName, int fontSize) {
+			Font font = _fontList.get(psName);
+			if (font == null && (font = _fontList.defaultFont()) == null) {
+				return null;
+			}
 
+			String fontPath = font.fontFile.getAbsolutePath();
+			int faceIndex = font.faceIndex;
 
-	// TODO フォントを選択できるようにする。以下は暫定。
+			if (_ctcr) {
+				return _fontManager.getPolygonFont(fontPath, faceIndex, fontSize);
+			} else {
+				return _fontManager.getBufferFont(fontPath, faceIndex, fontSize);
+			}
+		}
 
-	private static final String FONTPATH;
+		private double[][] calcTextOffsets(
+				FTGLfont font, String[] texts,
+				HorizontalAlignment halign, double leading,
+				RenderResolution resolution) {
+
+			double[][] offsets = new double[texts.length][2];
+
+			switch (halign) {
+				default:
+				case LEFT:
+					for (int i = 0; i < texts.length; ++i) {
+						offsets[i] = new double[] { 0, leading*i };
+					}
+					break;
+
+				case CENTER:
+					for (int i = 0; i < texts.length; ++i) {
+						double advance = resolution.scale(FTGL.ftglGetFontAdvance(font, texts[i]));
+						offsets[i] = new double[] { -advance/2, leading*i };
+					}
+					break;
+
+				case RIGHT:
+					for (int i = 0; i < texts.length; ++i) {
+						double advance = resolution.scale(FTGL.ftglGetFontAdvance(font, texts[i]));
+						offsets[i] = new double[] { -advance, leading*i };
+					}
+					break;
+			}
 
-	static {
-		String[] fonts = {
-				"C:\\WINDOWS\\Fonts\\meiryob.ttc",
-				"C:\\WINDOWS\\Fonts\\msgoth04.ttc",
-				"C:\\WINDOWS\\Fonts\\msgothic.ttc",
-				"/System/Library/Fonts/ヒラギノ角ゴ ProN W6.otf",
-				"/System/Library/Fonts/ヒラギノ角ゴ Pro W6.otf",
-				"/Library/Fonts/Osaka.dfont"
-		};
+			return offsets;
+		}
 
-		String fontpath = "/no/font/available.ttc";
-		for (String f : fonts) {
-			if (new File(f).isFile()) {
-				fontpath = f;
-				break;
-			}
+		public AudioBuffer getAudioChunk() {
+			throw new UnsupportedOperationException("audio is not available");
 		}
-		FONTPATH = fontpath;
+
 	}
 
 }
diff -ruN javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/internal/services/AbstractRenderContext.java javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/internal/services/AbstractRenderContext.java
--- javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/internal/services/AbstractRenderContext.java	2009-12-21 21:43:29.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/internal/services/AbstractRenderContext.java	2010-02-13 11:47:48.000000000 +0900
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Yoshikazu Kuramochi
+ * Copyright (c) 2009,2010 Yoshikazu Kuramochi
  * All rights reserved.
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -37,6 +37,7 @@
 import org.mozilla.javascript.ScriptableObject;
 
 import ch.kuramo.javie.api.Time;
+import ch.kuramo.javie.core.Composition;
 import ch.kuramo.javie.core.ExpressionScope;
 import ch.kuramo.javie.core.Expressionee;
 import ch.kuramo.javie.core.Expressioner;
@@ -56,6 +57,8 @@
 
 	private Scriptable _initialExprScope;
 
+	private final Set<Composition> _scopeCreatedComps = Util.newSet();
+
 	private final Map<Expressioner<?>, ExpressionScopeImpl> _scopeMap = Util.newMap();
 
 	private final WeakHashMap<Expressionee, WeakReference<?>> _exprElemPool = Util.newWeakHashMap();
@@ -121,8 +124,11 @@
 		_time = time;
 	}
 
-	public ExpressionScope createInitialExpressionScope() {
+	public ExpressionScope createInitialExpressionScope(Composition comp) {
+		_scopeCreatedComps.clear();
 		_scopeMap.clear();
+
+		_scopeCreatedComps.add(comp);
 		return new ExpressionScopeImpl(createNewExprScope(_initialExprScope));
 	}
 
@@ -227,16 +233,11 @@
 			}
 		}
 
-		public ExpressionScopeImpl createPrecompositionScope() {
-			Scriptable preCompScope = createNewExprScope(_initialExprScope);
-
-			// TODO 親コンポから子コンポのプロパティにアクセスするためには
-			//      アクセスするためのプロパティを this.scope に与えてやる必要がある。
-
-			// TODO 子コンポから親コンポのプロパティにアクセスするためには
-			//      アクセスするためのプロパティを preCompScope に与えてやる必要がある。
+		public ExpressionScope createPrecompositionScope(Composition preComp) {
+			if (_scopeCreatedComps.contains(preComp)) return null;
 
-			return new ExpressionScopeImpl(preCompScope);
+			_scopeCreatedComps.add(preComp);
+			return new ExpressionScopeImpl(createNewExprScope(_initialExprScope));
 		}
 
 		public void setThis(Expressionee exprnee) {
diff -ruN javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/internal/services/AbstractRenderContextProxy.java javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/internal/services/AbstractRenderContextProxy.java
--- javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/internal/services/AbstractRenderContextProxy.java	2009-12-21 21:43:29.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/internal/services/AbstractRenderContextProxy.java	2010-02-13 11:47:48.000000000 +0900
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Yoshikazu Kuramochi
+ * Copyright (c) 2009,2010 Yoshikazu Kuramochi
  * All rights reserved.
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -29,6 +29,7 @@
 import org.mozilla.javascript.Scriptable;
 
 import ch.kuramo.javie.api.Time;
+import ch.kuramo.javie.core.Composition;
 import ch.kuramo.javie.core.ExpressionScope;
 import ch.kuramo.javie.core.Expressionee;
 import ch.kuramo.javie.core.Expressioner;
@@ -113,8 +114,8 @@
 		getImpl().setTime(time);
 	}
 
-	public ExpressionScope createInitialExpressionScope() {
-		return getImpl().createInitialExpressionScope();
+	public ExpressionScope createInitialExpressionScope(Composition comp) {
+		return getImpl().createInitialExpressionScope(comp);
 	}
 
 	public <T> T getExpressionElement(Expressionee exprnee) {
diff -ruN javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/internal/services/FontListImpl.java javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/internal/services/FontListImpl.java
--- javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/internal/services/FontListImpl.java	1970-01-01 09:00:00.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/internal/services/FontListImpl.java	2010-02-14 21:15:45.000000000 +0900
@@ -0,0 +1,369 @@
+/*
+ * Copyright (c) 2010 Yoshikazu Kuramochi
+ * All rights reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package ch.kuramo.javie.core.internal.services;
+
+import static ftgl.FTGL.FT_Err_Invalid_Argument;
+import static ftgl.FTGL.FT_Err_Ok;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import ch.kuramo.javie.core.Util;
+import ch.kuramo.javie.core.services.Font;
+import ch.kuramo.javie.core.services.FontList;
+
+import com.sun.jna.Library;
+import com.sun.jna.Native;
+import com.sun.jna.Pointer;
+
+import ftgl.FTGL;
+import ftgl.FT_Face;
+import ftgl.FT_Library;
+import ftgl.FT_SfntName;
+
+public class FontListImpl implements FontList {
+
+	private static final Logger _logger = LoggerFactory.getLogger(FontListImpl.class);
+
+
+	private static final List<String> FONT_FILE_EXTENSIONS = Arrays.asList("ttf", "ttc", "dfont", "otf");
+
+	private static final FileFilter FONT_FILE_FILTER = new FileFilter() {
+		public boolean accept(File pathname) {
+			String name = pathname.getName();
+			int lastDot = name.indexOf('.');
+			if (lastDot != -1) {
+				String extension = name.substring(lastDot+1).toLowerCase();
+				return FONT_FILE_EXTENSIONS.contains(extension);
+			}
+			return false;
+		}
+	};
+
+	private static final String OS = System.getProperty("os.name").toLowerCase().replaceAll("\\s+", "");
+	private static final boolean MACOSX = OS.contains("macosx");
+	private static final boolean WINDOWS = OS.contains("windows");
+	private static final Locale LOCALE = Locale.getDefault();
+
+	private static final short PLATFORM_UNICODE = 0;
+	private static final short PLATFORM_MACINTOSH = 1;
+	private static final short PLATFORM_WINDOWS = 3;
+
+	private static final short LANG_MAC_en = 0;
+	private static final short LANG_MAC_ja = 11;
+	private static final short LANG_WIN_en_US = 0x0409;
+	private static final short LANG_WIN_ja_JP = 0x0411;
+
+	private static final short FULL_FONT_NAME = 4;
+	private static final short POSTSCRIPT_NAME = 6;
+
+
+	private static final String[] MACOSX_DEFAULT_FONTS = {
+		"HiraKakuProN-W3", "HiraKakuPro-W3", "HiraKakuProN-W6", "HiraKakuPro-W6",
+		"Osaka", "Osaka-Mono", "Helvetica", "Monaco"
+	};
+
+	private static final String[] WINDOWS_DEFAULT_FONTS = {
+		"Meiryo", "Meiryo-Bold", "MS-PGothic", "MS-Gothic", "MicrosoftSansSerif"
+	};
+
+
+	private final Map<String, Font> _fontMap = Util.newMap();
+
+	private List<Font> _fontList;
+
+	private Font _defaultFont;
+
+
+	public FontListImpl() {
+		initialize();
+	}
+
+	private List<File> listFontDirectories() {
+		String[] dirs;
+		if (MACOSX) {
+			dirs = new String[] {
+					System.getProperty("user.home") + "/Library/Fonts",
+					"/Library/Fonts",
+					"/Network/Library/Fonts",
+					"/System/Library/Fonts"
+			};
+		} else if (WINDOWS) {
+			char[] path = new char[WinShell32.MAX_PATH];
+			int hr = WinShell32.instance.SHGetFolderPathW(null, WinShell32.CSIDL_FONTS, null, 0, path);
+			if (hr == 0) {
+				int i = 0;
+				for (i = 0; i < path.length && path[i] != 0; ++i);	// This is OK.
+				dirs = new String[] { new String(path, 0, i) };
+			} else {
+				_logger.warn("no font folder found.");
+				return Collections.emptyList();
+			}
+		} else {
+			_logger.warn("font is not supported on this platform.");
+			return Collections.emptyList();
+		}
+
+		List<File> list = Util.newList();
+		for (String dir : dirs) {
+			File dirFile = new File(dir);
+			if (dirFile.isDirectory()) {
+				list.add(dirFile);
+			}
+		}
+		return list;
+	}
+
+	private List<File> listFontFiles() {
+		List<File> list = Util.newList();
+		for (File dir : listFontDirectories()) {
+			list.addAll(Arrays.asList(dir.listFiles(FONT_FILE_FILTER)));
+		}
+		return list;
+	}
+
+	private void initialize() {
+		FT_Library[] ftlib = new FT_Library[1];
+		long error = FTGL.ft_Init_FreeType(ftlib);
+		if (error != FT_Err_Ok) {
+			_logger.error("FT_Init_FreeType: error=" + error);
+			return;
+		}
+		try {
+			for (File fontFile : listFontFiles()) {
+				examineFontFile(ftlib[0], fontFile);
+			}
+		} finally {
+			error = FTGL.ft_Done_FreeType(ftlib[0]);
+			if (error != FT_Err_Ok) {
+				_logger.error("FT_Done_FreeType: error=" + error);
+			}
+		}
+
+		List<Font> list = Util.newList();
+		list.addAll(_fontMap.values());
+		Collections.sort(list, new Comparator<Font>() {
+			public int compare(Font o1, Font o2) {
+				return o1.fullName.compareTo(o2.fullName);
+			}
+		});
+
+		_fontList = Collections.unmodifiableList(list);
+
+
+		String[] defaultFonts = MACOSX ? MACOSX_DEFAULT_FONTS :
+								WINDOWS ? WINDOWS_DEFAULT_FONTS : new String[0];
+		for (String psName : defaultFonts) {
+			if ((_defaultFont = _fontMap.get(psName)) != null) break;
+		}
+		if (_defaultFont == null && _fontList.size() > 0) {
+			_defaultFont = _fontList.get(0);
+		}
+
+
+		//for (Font f : _fontList) {
+		//	System.out.println(f.fullName);
+		//	System.out.printf("  %s,%s,%d%n", f.psName, f.fontFile.getAbsolutePath(), f.faceIndex);
+		//}
+	}
+
+	private void examineFontFile(FT_Library ftlib, File fontFile) {
+		FT_Face[] face = new FT_Face[1];
+
+		for (int i = 0; ; ++i) {
+			int error = FTGL.ft_New_Face(ftlib, fontFile.getAbsolutePath(), i, face);
+			if (error != FT_Err_Ok) {
+				if (error != FT_Err_Invalid_Argument) {
+					_logger.error(String.format(
+							"FT_New_Face: error=%d (fontFile=%s, faceIndex=%d)",
+							error, fontFile.getAbsolutePath(), i));
+				}
+				return;
+			}
+			try {
+				if (!examineFontFace(fontFile, i, face[0])) {
+					return;
+				}
+			} finally {
+				error = FTGL.ft_Done_Face(face[0]);
+				if (error != FT_Err_Ok) {
+					_logger.error(String.format(
+							"FT_Done_Face: error=%d (fontFile=%s, faceIndex=%d)",
+							error, fontFile.getAbsolutePath(), i));
+				}
+			}
+		}
+	}
+
+	private boolean examineFontFace(File fontFile, int faceIndex, FT_Face face) {
+		SfntName psName = null;
+		SfntName fullName = null;
+
+		FT_SfntName[] sfntName = new FT_SfntName[1];
+		for (int j = 0, n = FTGL.ft_Get_Sfnt_Name_Count(face); j < n; ++j) {
+			int error = FTGL.ft_Get_Sfnt_Name(face, j, sfntName);
+			if (error != FT_Err_Ok) {
+				_logger.error(String.format(
+						"FT_Get_Sfnt_Name: error=%d (fontFile=%s, faceIndex=%d)",
+						error, fontFile.getAbsolutePath(), faceIndex));
+				break;
+			}
+
+			SfntName name = new SfntName(sfntName[0]);
+			switch (name.name_id) {
+				case POSTSCRIPT_NAME:
+					psName = preferredName(psName, name);
+					break;
+
+				case FULL_FONT_NAME:
+					fullName = preferredName(fullName, name);
+					break;
+			}
+		}
+
+		if (psName == null) {
+			_logger.debug("no postscript name found: " + fontFile.getAbsolutePath());
+			return false;
+		} else if (_fontMap.containsKey(psName.string)) {
+			_logger.debug("postscript name already exists: " + psName.string);
+			return false;
+		}
+
+		if (fullName == null) {
+			_logger.debug("no full name found, postscript name is used as full name: " + psName.string);
+			fullName = psName;
+		}
+		_fontMap.put(psName.string, new Font(psName.string, fullName.string, fontFile, faceIndex));
+
+		return true;
+	}
+
+	private SfntName preferredName(SfntName name1, SfntName name2) {
+		if (name1 == null && name2 == null) throw new IllegalArgumentException();
+		if (name1 == null) return name2;
+		if (name2 == null) return name1;
+
+		short preferedPlatId = MACOSX ? PLATFORM_MACINTOSH : WINDOWS ? PLATFORM_WINDOWS : PLATFORM_UNICODE;
+
+		// TODO en,ja以外にも対応する必要がある。
+		short preferedLangId = MACOSX ? (LOCALE.getLanguage().equals("ja") ? LANG_MAC_ja : LANG_MAC_en) :
+							   WINDOWS ? (LOCALE.getLanguage().equals("ja") ? LANG_WIN_ja_JP : LANG_WIN_en_US) : -1;
+
+		// platform_id が実行環境と一致する方を選択する。
+		if (name1.platform_id == preferedPlatId && name2.platform_id != preferedPlatId) {
+			return name1;
+		} else if (name1.platform_id != preferedPlatId && name2.platform_id == preferedPlatId) {
+			return name2;
+		}
+
+		// どちらの platform_id も実行環境と一致しない場合、PLATFORM_UNICODE の方を選択する。
+		if (name1.platform_id == PLATFORM_UNICODE && name2.platform_id != PLATFORM_UNICODE) {
+			return name1;
+		} else if (name1.platform_id != PLATFORM_UNICODE && name2.platform_id == PLATFORM_UNICODE) {
+			return name2;
+		}
+
+		// language_id が実行環境と一致する方を選択する。
+		if (name1.language_id == preferedLangId && name2.language_id != preferedLangId) {
+			return name1;
+		} else if (name1.language_id != preferedLangId && name2.language_id == preferedLangId) {
+			return name2;
+		}
+
+		// どちらの language_id も実行環境と一致しない場合、LANG_MAC_en または LANG_WIN_en_US と一致する方を選択する。 
+		preferedLangId = MACOSX ? LANG_MAC_en : WINDOWS ? LANG_WIN_en_US : -1;
+		if (name1.language_id == preferedLangId && name2.language_id != preferedLangId) {
+			return name1;
+		} else if (name1.language_id != preferedLangId && name2.language_id == preferedLangId) {
+			return name2;
+		}
+
+		// どちらも一致度が同じ場合は name1 を選択する。
+		return name1;
+	}
+
+	private static class SfntName {
+		final short platform_id;
+		//final short encoding_id;
+		final short language_id;
+		final short name_id;
+		final String string;
+
+		SfntName(FT_SfntName ftSfntName) {
+			platform_id = ftSfntName.platform_id;
+			//encoding_id = ftSfntName.encoding_id;
+			language_id = ftSfntName.language_id;
+			name_id = ftSfntName.name_id;
+			string = ftSfntName.stringAsJavaString();
+		}
+	}
+
+
+	public List<Font> list() {
+		return _fontList;
+	}
+
+	public Font get(String psName) {
+		return _fontMap.get(psName);
+	}
+
+	public Font defaultFont() {
+		return _defaultFont;
+	}
+
+}
+
+interface WinShell32 extends Library {
+
+	static final WinShell32 instance = (WinShell32) Native.loadLibrary("shell32", WinShell32.class);
+
+
+	int MAX_PATH = 260;
+	int CSIDL_FONTS = 0x0014;
+
+	/**
+	 * HRESULT SHGetFolderPathW(
+	 *		HWND   hwndOwner,
+	 *		int    nFolder,
+	 *		HANDLE hToken,
+	 *		DWORD  dwFlags,
+	 *		LPWSTR pszPath)
+	 */
+	int SHGetFolderPathW(
+			Pointer hwndOwner,
+			int     nFolder,
+			Pointer hToken,
+			int     dwFlags,
+			char[]  pszPath);
+
+}
diff -ruN javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/internal/services/FontManagerImpl.java javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/internal/services/FontManagerImpl.java
--- javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/internal/services/FontManagerImpl.java	2009-12-21 21:43:29.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/internal/services/FontManagerImpl.java	2010-02-14 21:15:45.000000000 +0900
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Yoshikazu Kuramochi
+ * Copyright (c) 2009,2010 Yoshikazu Kuramochi
  * All rights reserved.
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -41,8 +41,6 @@
 
 	private static final Logger logger = LoggerFactory.getLogger(FontManagerImpl.class);
 
-	private static final FTGL ftgl = FTGL.instance;
-
 	private static final int MAX_FONTS = 8;
 
 
@@ -52,7 +50,7 @@
 		protected boolean removeEldestEntry(Entry<String, FTGLfont> eldest) {
 			if (size() > MAX_FONTS) {
 				String key = eldest.getKey();
-				ftgl.ftglDestroyFont(eldest.getValue());
+				FTGL.ftglDestroyFont(eldest.getValue());
 				remove(key);
 				logger.info("font removed from cache: " + key);
 			}
@@ -62,41 +60,43 @@
 
 	void dispose() {
 		for (Entry<String, FTGLfont> e : _fontCache.entrySet()) {
-			ftgl.ftglDestroyFont(e.getValue());
+			FTGL.ftglDestroyFont(e.getValue());
 		}
 		_fontCache.clear();
 	}
 
-	public FTGLfont getPolygonFont(String filename, int size) {
-		return getFont(FontType.Polygon, filename, size);
+	public FTGLfont getPolygonFont(String filename, int faceIndex, int size) {
+		return getFont(FontType.Polygon, filename, faceIndex, size);
 	}
 
-	public FTGLfont getOutlineFont(String filename, int size) {
-		return getFont(FontType.Outline, filename, size);
+	public FTGLfont getOutlineFont(String filename, int faceIndex, int size) {
+		return getFont(FontType.Outline, filename, faceIndex, size);
 	}
 
-	public FTGLfont getExtrudeFont(String filename, int size) {
-		return getFont(FontType.Extrude, filename, size);
+	public FTGLfont getExtrudeFont(String filename, int faceIndex, int size) {
+		return getFont(FontType.Extrude, filename, faceIndex, size);
 	}
 
-	public FTGLfont getTextureFont(String filename, int size) {
-		return getFont(FontType.Texture, filename, size);
+	public FTGLfont getTextureFont(String filename, int faceIndex, int size) {
+		return getFont(FontType.Texture, filename, faceIndex, size);
 	}
 
-	public FTGLfont getBufferFont(String filename, int size) {
-		return getFont(FontType.Buffer, filename, size);
+	public FTGLfont getBufferFont(String filename, int faceIndex, int size) {
+		return getFont(FontType.Buffer, filename, faceIndex, size);
 	}
 
 
 	private enum FontType { Polygon, Outline, Extrude, Texture, Buffer }
 
-	private FTGLfont getFont(FontType type, String filename, int size) {
+	private FTGLfont getFont(FontType type, String filename, int faceIndex, int size) {
 		try {
 			filename = new File(filename).getCanonicalPath();
 		} catch (IOException e) {
 			logger.warn("cannot get canonical path for font: " + filename);
 		}
 
+		filename = String.format("%d,%s", faceIndex, filename);
+
 		String key = String.format("%s,%s,%d", type.name(), filename, size);
 
 		FTGLfont font = _fontCache.get(key);
@@ -106,37 +106,37 @@
 
 		switch (type) {
 			case Polygon:
-				font = ftgl.ftglCreatePolygonFont(filename);
+				font = FTGL.ftglCreatePolygonFont(filename);
 				break;
 
 			case Outline:
-				font = ftgl.ftglCreateOutlineFont(filename);
+				font = FTGL.ftglCreateOutlineFont(filename);
 				break;
 
 			case Extrude:
-				font = ftgl.ftglCreateExtrudeFont(filename);
+				font = FTGL.ftglCreateExtrudeFont(filename);
 				break;
 
 			case Texture:
-				font = ftgl.ftglCreateTextureFont(filename);
+				font = FTGL.ftglCreateTextureFont(filename);
 				break;
 
 			case Buffer:
-				font = ftgl.ftglCreateBufferFont(filename);
+				font = FTGL.ftglCreateBufferFont(filename);
 				break;
 
 			default:
 				throw new JavieRuntimeException("unsupported font type");
 		}
 
-		int error = ftgl.ftglGetFontError(font);
+		int error = FTGL.ftglGetFontError(font);
 		if (error != 0) {
-			ftgl.ftglDestroyFont(font);
+			FTGL.ftglDestroyFont(font);
 			throw new JavieRuntimeException(
 					String.format("ftglCreate%sFont failed: error=%d", type.name(), error));
 		}
-		ftgl.ftglSetFontCharMap(font, FTGL.FT_ENCODING_UNICODE);
-		ftgl.ftglSetFontFaceSize(font, size, 72);
+		FTGL.ftglSetFontCharMap(font, FTGL.FT_ENCODING_UNICODE);
+		FTGL.ftglSetFontFaceSize(font, size, 72);
 
 		_fontCache.put(key, font);
 		return font;
diff -ruN javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/internal/services/FontManagerProxy.java javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/internal/services/FontManagerProxy.java
--- javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/internal/services/FontManagerProxy.java	2009-12-21 21:43:29.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/internal/services/FontManagerProxy.java	2010-02-12 13:06:03.000000000 +0900
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Yoshikazu Kuramochi
+ * Copyright (c) 2009,2010 Yoshikazu Kuramochi
  * All rights reserved.
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -56,24 +56,24 @@
 		return impl;
 	}
 
-	public FTGLfont getPolygonFont(String filename, int size) {
-		return getImpl().getPolygonFont(filename, size);
+	public FTGLfont getPolygonFont(String filename, int faceIndex, int size) {
+		return getImpl().getPolygonFont(filename, faceIndex, size);
 	}
 
-	public FTGLfont getOutlineFont(String filename, int size) {
-		return getImpl().getOutlineFont(filename, size);
+	public FTGLfont getOutlineFont(String filename, int faceIndex, int size) {
+		return getImpl().getOutlineFont(filename, faceIndex, size);
 	}
 
-	public FTGLfont getExtrudeFont(String filename, int size) {
-		return getImpl().getExtrudeFont(filename, size);
+	public FTGLfont getExtrudeFont(String filename, int faceIndex, int size) {
+		return getImpl().getExtrudeFont(filename, faceIndex, size);
 	}
 
-	public FTGLfont getTextureFont(String filename, int size) {
-		return getImpl().getTextureFont(filename, size);
+	public FTGLfont getTextureFont(String filename, int faceIndex, int size) {
+		return getImpl().getTextureFont(filename, faceIndex, size);
 	}
 
-	public FTGLfont getBufferFont(String filename, int size) {
-		return getImpl().getBufferFont(filename, size);
+	public FTGLfont getBufferFont(String filename, int faceIndex, int size) {
+		return getImpl().getBufferFont(filename, faceIndex, size);
 	}
 
 }
diff -ruN javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/internal/services/VideoRenderSupportImpl.java javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/internal/services/VideoRenderSupportImpl.java
--- javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/internal/services/VideoRenderSupportImpl.java	2010-01-21 09:41:21.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/internal/services/VideoRenderSupportImpl.java	2010-02-15 14:34:19.000000000 +0900
@@ -990,7 +990,11 @@
 		});
 	}
 
-	public void renderText(final FTGLfont font, final Color fillColor, final String text, VideoBuffer resultBuffer) {
+	public void renderText(
+			final FTGLfont font, final Color fillColor,
+			final String[] texts, final double[][] offsets,
+			VideoBuffer resultBuffer) {
+
 		final int resultTexture = resultBuffer.getTexture();
 		final VideoBounds resultBounds = resultBuffer.getBounds();
 
@@ -999,11 +1003,13 @@
 				GL gl = _vrContext.getGL();
 				GLU glu = _vrContext.getGLU();
 
+				float scale = (float) _vrContext.getRenderResolution().scale;
+
 				ortho2D(gl, glu, resultBounds.width, resultBounds.height);
 				gl.glTranslatef((float) -resultBounds.x, (float) -resultBounds.y, 0);
 
-				float scale = (float) _vrContext.getRenderResolution().scale;
-				gl.glScalef(scale, -scale, scale);
+				double[] mvMatrix = new double[16];
+				getMatrix(mvMatrix, null);
 
 				gl.glFramebufferTexture2DEXT(GL.GL_FRAMEBUFFER_EXT,
 						GL.GL_COLOR_ATTACHMENT0_EXT, GL.GL_TEXTURE_RECTANGLE_EXT, resultTexture, 0);
@@ -1020,9 +1026,14 @@
 				// オリジナルのFTGLは内部でアルファブレンドの設定を行っているが、Javieはそれを無効にした修正版FTGLを使用している。
 				// Javieには次のアルファブレンドが必要なため。
 				gl.glEnable(GL.GL_BLEND);
-				gl.glBlendFuncSeparate(GL.GL_SRC_ALPHA, GL.GL_ZERO, GL.GL_ONE, GL.GL_ZERO);
+				gl.glBlendFuncSeparate(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA, GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA);
 
-				FTGL.instance.ftglRenderFont(font, text, FTGL.FTGL_RENDER_ALL);
+				for (int i = 0; i < texts.length; ++i) {
+					setMatrix(mvMatrix, null);
+					gl.glTranslatef((float)offsets[i][0], (float)offsets[i][1], 0);
+					gl.glScalef(scale, -scale, scale);
+					FTGL.ftglRenderFont(font, texts[i], FTGL.FTGL_RENDER_ALL);
+				}
 
 				gl.glDisable(GL.GL_BLEND);
 
@@ -1037,7 +1048,8 @@
 	}
 
 	public void renderText(
-			final FTGLfont font, final Color fillColor, final String text,
+			final FTGLfont font, final Color fillColor,
+			final String[] texts, final double[][] offsets,
 			VideoBuffer resultBuffer, DepthBuffer depthBuffer,
 			final double[] mvMatrix, final double[] prjMatrix) {
 
@@ -1051,14 +1063,16 @@
 			public Object execute() {
 				GL gl = _vrContext.getGL();
 
+				float scale = (float) _vrContext.getRenderResolution().scale;
+
 				gl.glViewport(0, 0, resultImageSize.width, resultImageSize.height);
 				gl.glMatrixMode(GL.GL_PROJECTION);
 				gl.glLoadMatrixd(prjMatrix, 0);
 				gl.glMatrixMode(GL.GL_MODELVIEW);
 				gl.glLoadMatrixd(mvMatrix, 0);
 
-				float scale = (float) _vrContext.getRenderResolution().scale;
-				gl.glScalef(scale, -scale, scale);
+				double[] mvMatrix = new double[16];
+				getMatrix(mvMatrix, null);
 
 
 				gl.glFramebufferTexture2DEXT(GL.GL_FRAMEBUFFER_EXT,
@@ -1085,7 +1099,12 @@
 				float b = (float)fillColor.b * a;
 				gl.glColor4f(r, g, b, a);
 
-				FTGL.instance.ftglRenderFont(font, text, FTGL.FTGL_RENDER_ALL);
+				for (int i = 0; i < texts.length; ++i) {
+					setMatrix(mvMatrix, null);
+					gl.glTranslatef((float)offsets[i][0], (float)offsets[i][1], 0);
+					gl.glScalef(scale, -scale, scale);
+					FTGL.ftglRenderFont(font, texts[i], FTGL.FTGL_RENDER_ALL);
+				}
 
 				if (depthTexture != 0) {
 					gl.glDisable(GL.GL_DEPTH_TEST);
diff -ruN javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/messages.properties javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/messages.properties
--- javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/messages.properties	2010-01-21 15:11:03.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/messages.properties	2010-02-15 14:30:33.000000000 +0900
@@ -65,3 +65,8 @@
 TrackMatte.ALPHA_INVERTED=Alpha Inverted
 TrackMatte.LUMA=Luma
 TrackMatte.LUMA_INVERTED=Luma Inverted
+
+
+HorizontalAlignment.LEFT=Left
+HorizontalAlignment.CENTER=Center
+HorizontalAlignment.RIGHT=Right
diff -ruN javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/messages_ja.properties javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/messages_ja.properties
--- javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/messages_ja.properties	2010-01-21 15:11:03.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/messages_ja.properties	2010-02-15 14:30:33.000000000 +0900
@@ -65,3 +65,8 @@
 TrackMatte.ALPHA_INVERTED=\u30a2\u30eb\u30d5\u30a1\u53cd\u8ee2
 TrackMatte.LUMA=\u30eb\u30df\u30ca\u30f3\u30b9
 TrackMatte.LUMA_INVERTED=\u30eb\u30df\u30ca\u30f3\u30b9\u53cd\u8ee2
+
+
+HorizontalAlignment.LEFT=\u5de6\u63c3\u3048
+HorizontalAlignment.CENTER=\u4e2d\u592e\u63c3\u3048
+HorizontalAlignment.RIGHT=\u53f3\u63c3\u3048
diff -ruN javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/output/PullSourceOutput.java javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/output/PullSourceOutput.java
--- javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/output/PullSourceOutput.java	2010-01-29 00:02:38.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/output/PullSourceOutput.java	2010-02-13 11:47:48.000000000 +0900
@@ -126,7 +126,7 @@
 		try {
 			GL gl = _vrContext.getGL();
 
-			comp.prepareExpression(_vrContext.createInitialExpressionScope());
+			comp.prepareExpression(_vrContext.createInitialExpressionScope(comp));
 
 			while (true) {
 				VideoBuffer vb = null;
@@ -174,7 +174,7 @@
 
 		_arContext.activate();
 		try {
-			comp.prepareExpression(_arContext.createInitialExpressionScope());
+			comp.prepareExpression(_arContext.createInitialExpressionScope(comp));
 
 			while (true) {
 				AudioBuffer ab = null;
diff -ruN javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/output/PushSourceOutput.java javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/output/PushSourceOutput.java
--- javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/output/PushSourceOutput.java	2010-01-30 14:43:53.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/output/PushSourceOutput.java	2010-02-13 11:47:48.000000000 +0900
@@ -1,3 +1,26 @@
+/*
+ * Copyright (c) 2010 Yoshikazu Kuramochi
+ * All rights reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
 package ch.kuramo.javie.core.output;
 
 import java.io.File;
@@ -68,7 +91,7 @@
 		try {
 			GL gl = _vrContext.getGL();
 
-			comp.prepareExpression(_vrContext.createInitialExpressionScope());
+			comp.prepareExpression(_vrContext.createInitialExpressionScope(comp));
 
 			for (long i = 0; i < numFrames && !monitor.isCanceled(); ++i) {
 				Time time = Time.fromFrameNumber(i, frameDuration);
@@ -108,7 +131,7 @@
 
 		_arContext.activate();
 		try {
-			comp.prepareExpression(_arContext.createInitialExpressionScope());
+			comp.prepareExpression(_arContext.createInitialExpressionScope(comp));
 
 			for (long i = 0; i < totalFrames && !monitor.isCanceled(); ) {
 				Time time = Time.fromFrameNumber(i, audioMode.sampleDuration);
diff -ruN javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/services/Font.java javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/services/Font.java
--- javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/services/Font.java	1970-01-01 09:00:00.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/services/Font.java	2010-02-12 00:10:05.000000000 +0900
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2010 Yoshikazu Kuramochi
+ * All rights reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package ch.kuramo.javie.core.services;
+
+import java.io.File;
+
+public class Font {
+
+	public final String psName;
+
+	public final String fullName;
+
+	public final File fontFile;
+
+	public final int faceIndex;
+
+
+	public Font(String psName, String fullName, File fontFile, int faceIndex) {
+		this.psName = psName;
+		this.fullName = fullName;
+		this.fontFile = fontFile;
+		this.faceIndex = faceIndex;
+	}
+
+}
diff -ruN javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/services/FontList.java javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/services/FontList.java
--- javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/services/FontList.java	1970-01-01 09:00:00.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/services/FontList.java	2010-02-12 00:10:05.000000000 +0900
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2010 Yoshikazu Kuramochi
+ * All rights reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package ch.kuramo.javie.core.services;
+
+import java.util.List;
+
+public interface FontList {
+
+	List<Font> list();
+
+	Font get(String psName);
+
+	Font defaultFont();
+
+}
diff -ruN javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/services/FontManager.java javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/services/FontManager.java
--- javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/services/FontManager.java	2009-12-21 21:43:29.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/services/FontManager.java	2010-02-12 13:06:03.000000000 +0900
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Yoshikazu Kuramochi
+ * Copyright (c) 2009,2010 Yoshikazu Kuramochi
  * All rights reserved.
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -27,14 +27,14 @@
 
 public interface FontManager {
 
-	FTGLfont getPolygonFont(String filename, int size);
+	FTGLfont getPolygonFont(String filename, int faceIndex, int size);
 
-	FTGLfont getOutlineFont(String filename, int size);
+	FTGLfont getOutlineFont(String filename, int faceIndex, int size);
 
-	FTGLfont getExtrudeFont(String filename, int size);
+	FTGLfont getExtrudeFont(String filename, int faceIndex, int size);
 
-	FTGLfont getTextureFont(String filename, int size);
+	FTGLfont getTextureFont(String filename, int faceIndex, int size);
 
-	FTGLfont getBufferFont(String filename, int size);
+	FTGLfont getBufferFont(String filename, int faceIndex, int size);
 
 }
diff -ruN javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/services/JavieCoreModule.java javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/services/JavieCoreModule.java
--- javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/services/JavieCoreModule.java	2009-12-25 22:46:12.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/services/JavieCoreModule.java	2010-02-12 00:10:38.000000000 +0900
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Yoshikazu Kuramochi
+ * Copyright (c) 2009,2010 Yoshikazu Kuramochi
  * All rights reserved.
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -35,6 +35,7 @@
 import ch.kuramo.javie.core.internal.services.AudioRenderContextProxy;
 import ch.kuramo.javie.core.internal.services.AudioRenderSupportImpl;
 import ch.kuramo.javie.core.internal.services.EffectRegistryImpl;
+import ch.kuramo.javie.core.internal.services.FontListImpl;
 import ch.kuramo.javie.core.internal.services.FontManagerProxy;
 import ch.kuramo.javie.core.internal.services.GLGlobalImpl;
 import ch.kuramo.javie.core.internal.services.MediaFileInputFactoryImpl;
@@ -124,6 +125,10 @@
 				.to(PIAudioRenderContextProxy.class)
 				.in(Scopes.SINGLETON);
 
+		bind(FontList.class)
+				.to(FontListImpl.class)
+				.in(Scopes.SINGLETON);
+
 		bind(FontManager.class)
 				.to(FontManagerProxy.class)
 				.in(Scopes.SINGLETON);
diff -ruN javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/services/VideoRenderSupport.java javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/services/VideoRenderSupport.java
--- javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/services/VideoRenderSupport.java	2010-01-21 09:35:04.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ch/kuramo/javie/core/services/VideoRenderSupport.java	2010-02-14 02:17:49.000000000 +0900
@@ -113,10 +113,11 @@
 
 	void scaleAndFlipVertical(VideoBuffer srcBuffer, VideoBuffer resultBuffer, double scale);
 
-	void renderText(FTGLfont font, Color fillColor, String text, VideoBuffer resultBuffer);
+	void renderText(FTGLfont font, Color fillColor, String[] texts, double[][] offsets, VideoBuffer resultBuffer);
 
 	void renderText(
-			FTGLfont font, Color fillColor, String text,
+			FTGLfont font, Color fillColor,
+			String[] texts, double[][] offsets,
 			VideoBuffer resultBuffer, DepthBuffer depthBuffer,
 			double[] mvMatrix, double[] prjMatrix);
 
diff -ruN javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ftgl/FTGL.java javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ftgl/FTGL.java
--- javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ftgl/FTGL.java	2009-12-21 02:10:00.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ftgl/FTGL.java	2010-02-14 21:11:52.000000000 +0900
@@ -4,37 +4,240 @@
 import com.sun.jna.Native;
 import com.sun.jna.ptr.DoubleByReference;
 
-public interface FTGL extends Library {
-
-	static final String libname = "ftgl";
-
-	static final FTGL instance = (FTGL) Native.loadLibrary(libname, FTGL.class);
+public class FTGL {
 
+	private static final FTGLLib lib = (FTGLLib) Native.loadLibrary("ftgl", FTGLLib.class);
 
 
 	////////////////////////////////////////////////////////////////////////////////
-	// freetype constants                                                         //
+	// ftgl                                                                       //
 	////////////////////////////////////////////////////////////////////////////////
 
-	public static final int FT_ENCODING_UNICODE = 1970170211;	// 'unic'
+	public static final int FTGL_RENDER_FRONT = 0x0001;
+	public static final int FTGL_RENDER_BACK  = 0x0002;
+	public static final int FTGL_RENDER_SIDE  = 0x0004;
+	public static final int FTGL_RENDER_ALL   = 0xffff;
+
+	public static final int FTGL_ALIGN_LEFT    = 0;
+	public static final int FTGL_ALIGN_CENTER  = 1;
+	public static final int FTGL_ALIGN_RIGHT   = 2;
+	public static final int FTGL_ALIGN_JUSTIFY = 3;
+
+
+	public synchronized static int ftglAttachFile(FTGLfont font, String path) {
+		return lib.ftglAttachFile(font, path);
+	}
+
+	public synchronized static FTGLfont ftglCreateBitmapFont(String file) {
+		return lib.ftglCreateBitmapFont(file);
+	}
+
+	public synchronized static FTGLfont ftglCreateBufferFont(String file) {
+		return lib.ftglCreateBufferFont(file);
+	}
+
+	public synchronized static FTGLfont ftglCreateExtrudeFont(String file) {
+		return lib.ftglCreateExtrudeFont(file);
+	}
+
+	public synchronized static FTGLfont ftglCreateOutlineFont(String file) {
+		return lib.ftglCreateOutlineFont(file);
+	}
+
+	public synchronized static FTGLfont ftglCreatePixmapFont(String file) {
+		return lib.ftglCreatePixmapFont(file);
+	}
+
+	public synchronized static FTGLfont ftglCreatePolygonFont(String file) {
+		return lib.ftglCreatePolygonFont(file);
+	}
+
+	public synchronized static FTGLlayout ftglCreateSimpleLayout() {
+		return lib.ftglCreateSimpleLayout();
+	}
+
+	public synchronized static FTGLfont ftglCreateTextureFont(String file) {
+		return lib.ftglCreateTextureFont(file);
+	}
+
+	public synchronized static void ftglDestroyFont(FTGLfont font) {
+		lib.ftglDestroyFont(font);
+	}
+
+	public synchronized static void ftglDestroyGlyph(FTGLglyph glyph) {
+		lib.ftglDestroyGlyph(glyph);
+	}
+
+	public synchronized static void ftglDestroyLayout(FTGLlayout layout) {
+		lib.ftglDestroyLayout(layout);
+	}
+
+	public synchronized static float ftglGetFontAdvance(FTGLfont font, String string) {
+		return lib.ftglGetFontAdvance(font, string);
+	}
+
+	public synchronized static float ftglGetFontAscender(FTGLfont font) {
+		return lib.ftglGetFontAscender(font);
+	}
+
+	public synchronized static void ftglGetFontBBox(FTGLfont font, String string, int len, float[] bounds) {
+		lib.ftglGetFontBBox(font, string, len, bounds);
+	}
+
+	public synchronized static int ftglGetFontCharMapCount(FTGLfont font) {
+		return lib.ftglGetFontCharMapCount(font);
+	}
+
+	public synchronized static int ftglGetFontCharMapList(FTGLfont font) {
+		return lib.ftglGetFontCharMapList(font);
+	}
+
+	public synchronized static float ftglGetFontDescender(FTGLfont font) {
+		return lib.ftglGetFontDescender(font);
+	}
+
+	public synchronized static int ftglGetFontError(FTGLfont font) {
+		return lib.ftglGetFontError(font);
+	}
+
+	public synchronized static int ftglGetFontFaceSize(FTGLfont font) {
+		return lib.ftglGetFontFaceSize(font);
+	}
+
+	public synchronized static float ftglGetFontLineHeight(FTGLfont font) {
+		return lib.ftglGetFontLineHeight(font);
+	}
+
+	public synchronized static float ftglGetGlyphAdvance(FTGLglyph glyph) {
+		return lib.ftglGetGlyphAdvance(glyph);
+	}
+
+	public synchronized static void ftglGetGlyphBBox(FTGLglyph glyph, float[] bounds) {
+		lib.ftglGetGlyphBBox(glyph, bounds);
+	}
+
+	public synchronized static int ftglGetGlyphError(FTGLglyph glyph) {
+		return lib.ftglGetGlyphError(glyph);
+	}
+
+	public synchronized static int ftglGetLayoutAlignement(FTGLlayout layout) {
+		return lib.ftglGetLayoutAlignement(layout);
+	}
+
+	public synchronized static void ftglGetLayoutBBox(FTGLlayout layout, String string, float[] bounds) {
+		lib.ftglGetLayoutBBox(layout, string, bounds);
+	}
+
+	public synchronized static int ftglGetLayoutError(FTGLlayout layout) {
+		return lib.ftglGetLayoutError(layout);
+	}
+
+	public synchronized static FTGLfont ftglGetLayoutFont(FTGLlayout layout) {
+		return lib.ftglGetLayoutFont(layout);
+	}
+
+	public synchronized static float ftglGetLayoutLineLength(FTGLlayout layout) {
+		return lib.ftglGetLayoutLineLength(layout);
+	}
+
+	public synchronized static float ftglGetLayoutLineSpacing(FTGLlayout layout) {
+		return lib.ftglGetLayoutLineSpacing(layout);
+	}
+
+	public synchronized static void ftglRenderFont(FTGLfont font, String string, int mode) {
+		lib.ftglRenderFont(font, string, mode);
+	}
+
+	public synchronized static void ftglRenderGlyph(
+			FTGLglyph glyph, double penx, double peny,
+			int renderMode, double[] advancex, double[] advancey) {
+		lib.ftglRenderGlyph(glyph, penx, peny, renderMode, advancex, advancey);
+	}
+
+	public synchronized static void ftglRenderGlyph(
+			FTGLglyph glyph, double penx, double peny,
+			int renderMode, DoubleByReference advancex, DoubleByReference advancey) {
+		lib.ftglRenderGlyph(glyph, penx, peny, renderMode, advancex, advancey);
+	}
+
+	public synchronized static void ftglRenderLayout(FTGLlayout layout, String string, int mode) {
+		lib.ftglRenderLayout(layout, string, mode);
+	}
+
+	public synchronized static int ftglSetFontCharMap(FTGLfont font, int encoding) {
+		return lib.ftglSetFontCharMap(font, encoding);
+	}
+
+	public synchronized static void ftglSetFontDepth(FTGLfont font, float depth) {
+		lib.ftglSetFontDepth(font, depth);
+	}
+
+	public synchronized static void ftglSetFontDisplayList(FTGLfont font, int useList) {
+		lib.ftglSetFontDisplayList(font, useList);
+	}
+
+	public synchronized static int ftglSetFontFaceSize(FTGLfont font, int size, int res) {
+		return lib.ftglSetFontFaceSize(font, size, res);
+	}
+
+	public synchronized static void ftglSetFontOutset(FTGLfont font, float front, float back) {
+		lib.ftglSetFontOutset(font, front, back);
+	}
+
+	public synchronized static void ftglSetLayoutAlignment(FTGLlayout layout, int alignment) {
+		lib.ftglSetLayoutAlignment(layout, alignment);
+	}
+
+	public synchronized static void ftglSetLayoutFont(FTGLlayout layout, FTGLfont fontInit) {
+		lib.ftglSetLayoutFont(layout, fontInit);
+	}
+
+	public synchronized static void ftglSetLayoutLineLength(FTGLlayout layout, float lineLength) {
+		lib.ftglSetLayoutLineLength(layout, lineLength);
+	}
+
+	public synchronized static void ftglSetLayoutLineSpacing(FTGLlayout layout, float lineSpacing) {
+		lib.ftglSetLayoutLineSpacing(layout, lineSpacing);
+	}
 
 
 	////////////////////////////////////////////////////////////////////////////////
-	// ftgl.h                                                                     //
+	// freetype                                                                   //
 	////////////////////////////////////////////////////////////////////////////////
 
+	public static final int FT_ENCODING_UNICODE		= 1970170211;	// 'unic'
+
+	public static final int FT_Err_Ok				= 0x00;
+	public static final int FT_Err_Invalid_Argument	= 0x06;
+
+
+	public static int ft_Done_Face(FT_Face face) {
+		return lib.ft_Done_Face(face);
+	}
+
+	public static int ft_Done_FreeType(FT_Library library) {
+		return lib.ft_Done_FreeType(library);
+	}
+
+	public static int ft_Get_Sfnt_Name_Count(FT_Face face) {
+		return lib.ft_Get_Sfnt_Name_Count(face);
+	}
 
-	static final int FTGL_RENDER_FRONT = 0x0001;
-	static final int FTGL_RENDER_BACK  = 0x0002;
-	static final int FTGL_RENDER_SIDE  = 0x0004;
-	static final int FTGL_RENDER_ALL   = 0xffff;
+	public static int ft_Get_Sfnt_Name(FT_Face face, int idx, FT_SfntName[] sfntName) {
+		return lib.ft_Get_Sfnt_Name(face, idx, sfntName);
+	}
 
-	static final int FTGL_ALIGN_LEFT    = 0;
-	static final int FTGL_ALIGN_CENTER  = 1;
-	static final int FTGL_ALIGN_RIGHT   = 2;
-	static final int FTGL_ALIGN_JUSTIFY = 3;
+	public static int ft_Init_FreeType(FT_Library[] alibrary) {
+		return lib.ft_Init_FreeType(alibrary);
+	}
 
+	public static int ft_New_Face(FT_Library library, String filename, int faceIndex, FT_Face[] aface) {
+		return lib.ft_New_Face(library, filename, faceIndex, aface);
+	}
 
+}
+
+interface FTGLLib extends Library {
 
 	////////////////////////////////////////////////////////////////////////////////
 	// FTGlyph.h                                                                  //
@@ -461,4 +664,16 @@
 	float ftglGetLayoutLineSpacing(FTGLlayout layout);
 
 
+
+	////////////////////////////////////////////////////////////////////////////////
+	// freetype function wrappers                                                 //
+	////////////////////////////////////////////////////////////////////////////////
+
+	int ft_Init_FreeType(FT_Library[] alibrary);
+	int ft_Done_FreeType(FT_Library library);
+	int ft_New_Face(FT_Library library, String filename, int face_index, FT_Face[] aface);
+	int ft_Done_Face(FT_Face face);
+	int ft_Get_Sfnt_Name_Count(FT_Face face);
+	int ft_Get_Sfnt_Name(FT_Face face, int idx, FT_SfntName[] sfntName);
+
 }
diff -ruN javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ftgl/FT_Face.java javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ftgl/FT_Face.java
--- javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ftgl/FT_Face.java	1970-01-01 09:00:00.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ftgl/FT_Face.java	2010-02-12 05:12:29.000000000 +0900
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2010 Yoshikazu Kuramochi
+ * All rights reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package ftgl;
+
+import com.sun.jna.PointerType;
+
+public class FT_Face extends PointerType {
+
+}
diff -ruN javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ftgl/FT_Library.java javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ftgl/FT_Library.java
--- javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ftgl/FT_Library.java	1970-01-01 09:00:00.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ftgl/FT_Library.java	2010-02-12 05:12:29.000000000 +0900
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2010 Yoshikazu Kuramochi
+ * All rights reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package ftgl;
+
+import com.sun.jna.PointerType;
+
+public class FT_Library extends PointerType {
+
+}
diff -ruN javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ftgl/FT_SfntName.java javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ftgl/FT_SfntName.java
--- javie-0.3.2-src/ch.kuramo.javie.core/src/main/java/ftgl/FT_SfntName.java	1970-01-01 09:00:00.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.core/src/main/java/ftgl/FT_SfntName.java	2010-02-13 13:30:31.000000000 +0900
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2010 Yoshikazu Kuramochi
+ * All rights reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package ftgl;
+
+import java.io.UnsupportedEncodingException;
+
+import com.sun.jna.Pointer;
+import com.sun.jna.Structure;
+
+public class FT_SfntName extends Structure {
+
+	/**
+	 * FT_UShort  platform_id;
+	 */
+	public short platform_id;
+
+	/**
+	 * FT_UShort  encoding_id;
+	 */
+	public short encoding_id;
+
+	/**
+	 * FT_UShort  language_id;
+	 */
+	public short language_id;
+
+	/**
+	 * FT_UShort  name_id;
+	 */
+	public short name_id;
+
+	/**
+	 * FT_Byte*   string;      // this string is *not* null-terminated!
+	 */
+	public Pointer string;
+
+	/**
+	 * FT_UInt    string_len;  // in bytes
+	 */
+	public int string_len;
+
+
+	public String stringAsJavaString() {
+		switch (platform_id) {
+			case 1:
+				return macintoshPlatformToJavaString();
+			case 3:
+				return windowsPlatformToJavaString();
+			default:
+				return toJavaString("UnicodeBigUnmarked");
+		}
+	}
+
+	private String macintoshPlatformToJavaString() {
+		switch (encoding_id) {
+			case 0:
+				return toJavaString("MacRoman");
+			case 1:
+				return toJavaString("Shift_JIS");
+
+			// TODO 他の encoding_id についても適切なJavaエンコーディングを指定して変換する。
+			default:
+				return toJavaString("ASCII");
+		}
+	}
+
+	private String windowsPlatformToJavaString() {
+		switch (encoding_id) {
+			case 0:	// Symbolの場合はUnicodeでエンコードされてるっぽい。
+			case 1:
+				return toJavaString("UnicodeBigUnmarked");
+			case 2:
+				return toJavaString("MS932");
+
+			// TODO 他の encoding_id についても適切なJavaエンコーディングを指定して変換する。
+			default:
+				return toJavaString("ASCII");
+		}
+	}
+
+	private String toJavaString(String encoding) {
+		try {
+			return new String(string.getByteArray(0, string_len), encoding);
+		} catch (UnsupportedEncodingException e) {
+			e.printStackTrace();
+		}
+		try {
+			return new String(string.getByteArray(0, string_len), "ASCII");
+		} catch (UnsupportedEncodingException e) {
+			// ASCIIは基本エンコーディングなので必ず存在する。
+			throw new Error(e);
+		}
+	}
+
+}
diff -ruN javie-0.3.2-src/ch.kuramo.javie.effects/META-INF/MANIFEST.MF javie-0.3.3-src/ch.kuramo.javie.effects/META-INF/MANIFEST.MF
--- javie-0.3.2-src/ch.kuramo.javie.effects/META-INF/MANIFEST.MF	2010-02-06 19:53:15.000000000 +0900
+++ javie-0.3.3-src/ch.kuramo.javie.effects/META-INF/MANIFEST.MF	2010-02-16 03:30:21.000000000 +0900
@@ -2,8 +2,8 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: Javie Effects
 Bundle-SymbolicName: ch.kuramo.javie.effects;singleton:=true
-Bundle-Version: 0.3.2.qualifier
+Bundle-Version: 0.3.3.qualifier
 Bundle-Vendor: rakusan
 Bundle-RequiredExecutionEnvironment: J2SE-1.5
-Require-Bundle: ch.kuramo.javie.api;bundle-version="0.3.2"
+Require-Bundle: ch.kuramo.javie.api;bundle-version="0.3.3"
 Eclipse-BuddyPolicy: global
