[bug 217977] initial commit
diff --git a/plugins/org.eclipse.actf.visualization.blind.html/.classpath b/plugins/org.eclipse.actf.visualization.blind.html/.classpath
new file mode 100644
index 0000000..751c8f2
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind.html/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/plugins/org.eclipse.actf.visualization.blind.html/.project b/plugins/org.eclipse.actf.visualization.blind.html/.project
new file mode 100644
index 0000000..10b3464
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind.html/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.actf.visualization.blind.html</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/plugins/org.eclipse.actf.visualization.blind.html/META-INF/MANIFEST.MF b/plugins/org.eclipse.actf.visualization.blind.html/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..de8e59f
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind.html/META-INF/MANIFEST.MF
@@ -0,0 +1,8 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Eclipse ACTF HTML Visualization Fragment (Incubation)
+Bundle-SymbolicName: org.eclipse.actf.visualization.blind.html;singleton:=true
+Bundle-Version: 0.0.1
+Bundle-Vendor: Eclipse.org
+Fragment-Host: org.eclipse.actf.visualization.blind;bundle-version="0.0.1"
+Bundle-Localization: plugin
diff --git a/plugins/org.eclipse.actf.visualization.blind.html/about.html b/plugins/org.eclipse.actf.visualization.blind.html/about.html
new file mode 100644
index 0000000..481dbcf
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind.html/about.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>June 5, 2006</p>	
+<h3>License</h3>
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;).  
+Unless otherwise indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;).  A copy of the EPL is available 
+at <a href="http://www.eclipse.org/org/documents/epl-v10.php">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is 
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content.  Check the Redistributor&rsquo;s license 
+that was provided with the Content.  If no such license exists, contact the Redistributor.  Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/plugins/org.eclipse.actf.visualization.blind.html/build.properties b/plugins/org.eclipse.actf.visualization.blind.html/build.properties
new file mode 100644
index 0000000..150249a
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind.html/build.properties
@@ -0,0 +1,16 @@
+###############################################################################
+# Copyright (c) 2008 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#     IBM Corporation - initial API and implementation
+###############################################################################
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               fragment.xml,\
+               about.html
diff --git a/plugins/org.eclipse.actf.visualization.blind.html/fragment.xml b/plugins/org.eclipse.actf.visualization.blind.html/fragment.xml
new file mode 100644
index 0000000..c951f36
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind.html/fragment.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.2"?>
+<fragment>
+   <extension
+         point="org.eclipse.actf.visualization.blind.blindVisualizer">
+      <blindVisualizer
+            class="org.eclipse.actf.visualization.blind.html.BlindVisualizerHtml"
+            id="org.eclipse.actf.visualization.blind.html.blindVisualizer1"/>
+   </extension>
+
+</fragment>
diff --git a/plugins/org.eclipse.actf.visualization.blind.html/src/org/eclipse/actf/visualization/blind/html/BlindVisualizerHtml.java b/plugins/org.eclipse.actf.visualization.blind.html/src/org/eclipse/actf/visualization/blind/html/BlindVisualizerHtml.java
new file mode 100644
index 0000000..0aa0144
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind.html/src/org/eclipse/actf/visualization/blind/html/BlindVisualizerHtml.java
@@ -0,0 +1,277 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.blind.html;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Vector;
+
+import org.eclipse.actf.model.IModelService;
+import org.eclipse.actf.model.IWebBrowserACTF;
+import org.eclipse.actf.model.dom.html.impl.SHDocument;
+import org.eclipse.actf.model.dom.html.util.HtmlParserUtil;
+import org.eclipse.actf.util.DebugPrintUtil;
+import org.eclipse.actf.util.html2view.Html2ViewMapMaker;
+import org.eclipse.actf.visualization.IVisualizationConst;
+import org.eclipse.actf.visualization.blind.BlindVisualizerBase;
+import org.eclipse.actf.visualization.blind.IBlindVisualizer;
+import org.eclipse.actf.visualization.blind.ui.internal.Messages;
+import org.eclipse.actf.visualization.engines.blind.BlindVizEnginePlugin;
+import org.eclipse.actf.visualization.engines.blind.eval.EvaluationResultBlind;
+import org.eclipse.actf.visualization.engines.blind.html.IVisualizeMapData;
+import org.eclipse.actf.visualization.engines.blind.html.VisualizeEngine;
+import org.eclipse.actf.visualization.engines.blind.html.eval.HtmlErrorLogListener;
+import org.eclipse.actf.visualization.engines.blind.html.util.HandleFramePage;
+import org.eclipse.actf.visualization.engines.blind.util.ParamBlind;
+import org.eclipse.actf.visualization.eval.EvaluationPreferencesUtil;
+import org.eclipse.actf.visualization.eval.HtmlCheckTargetImpl;
+import org.eclipse.actf.visualization.eval.IHtmlCheckTarget;
+import org.eclipse.actf.visualization.eval.IHtmlChecker;
+import org.eclipse.actf.visualization.eval.guideline.GuidelineHolder;
+import org.eclipse.actf.visualization.eval.html.HtmlEvalUtil;
+import org.eclipse.actf.visualization.eval.html.statistics.PageData;
+import org.eclipse.actf.visualization.eval.problem.HighlightTargetNodeInfo;
+import org.eclipse.actf.visualization.eval.problem.IProblemItem;
+import org.w3c.dom.Document;
+
+public class BlindVisualizerHtml extends BlindVisualizerBase implements
+		IBlindVisualizer {
+
+	public static final int FRAME = 1;
+
+	public static final String ORIG_HTML_FILE = "origSource.html";
+
+	public static final String IE_HTML_FILE = "ieSource.html";
+
+	private IWebBrowserACTF webBrowser;
+
+	@Override
+	public boolean setModelService(IModelService targetModel) {
+		webBrowser = null;
+		if (super.setModelService(targetModel)) {
+			webBrowser = (IWebBrowserACTF) targetModel;
+			return true;
+		}
+		return false;
+	}
+
+	public boolean isTarget(IModelService modelService) {
+		if (null != modelService && modelService instanceof IWebBrowserACTF) {
+			return true;
+		}
+		return false;
+	}
+
+	public int visualize() {
+		GuidelineHolder.getInstance().setTargetMimeType("text/html");
+
+		int frameId = 0;
+		checkResult = new EvaluationResultBlind();
+
+		try {
+
+			webBrowser.saveOriginalDocument(tmpDirS + ORIG_HTML_FILE);
+			webBrowser.saveDocumentAsHTMLFile(tmpDirS + IE_HTML_FILE);
+			// for srcViewer
+			webBrowser.saveOriginalDocument(tmpDirS + HTML_SOURCE_FILE);
+
+			Html2ViewMapMaker h2vmm = new Html2ViewMapMaker();
+
+			Vector html2ViewMapV = new Vector();
+			HtmlParserUtil hpu = new HtmlParserUtil();
+			HtmlErrorLogListener errorLogListener = new HtmlErrorLogListener();
+			hpu.addErrorLogListener(errorLogListener);
+			String targetFile = tmpDirS + MAPPED_HTML_FILE_PRE + frameId
+					+ ".html";
+
+			boolean isIEhtml = false;
+			if (EvaluationPreferencesUtil.isOriginalDOM()) {
+				html2ViewMapV = h2vmm.makeMap(ORIG_HTML_FILE,
+						MAPPED_HTML_FILE_PRE + frameId + ".html", tmpDirS);
+				// decode miss
+				if (html2ViewMapV.size() == 0) {
+					isIEhtml = true;
+				}
+			} else {
+				isIEhtml = true;
+			}
+
+			// for line<>id mapping
+			// HtmlLine2Id htmlLine2Id = new HtmlLine2Id(html2ViewMapV);
+
+			Document document;
+			Document ieDom;
+			Document originalDocument;
+			if (isIEhtml) {
+				ieDom = webBrowser.getLiveDocument();
+
+				// TODO replace with DomByCom (need clone/write support)
+				HtmlParserUtil tmpHPU = new HtmlParserUtil();
+				tmpHPU.parse(new FileInputStream(tmpDirS + IE_HTML_FILE));
+				document = tmpHPU.getSHDocument();
+
+				tmpHPU.parse(new FileInputStream(tmpDirS + ORIG_HTML_FILE));
+				originalDocument = tmpHPU.getSHDocument();
+
+			} else {
+				hpu.parse(new FileInputStream(targetFile));
+				document = hpu.getSHDocument();
+				originalDocument = document;
+				ieDom = webBrowser.getLiveDocument();
+			}
+			// System.out.println(document+" "+ _originalDom+" "+ ieDom);
+
+			boolean hasFrame = false;
+
+			if (document == null) {
+				return ERROR;
+			} else if (HandleFramePage.hasFrameset(document, webBrowser) == true) {
+				hasFrame = true;
+			}
+
+			setStatusMessage(Messages.getString("BlindView.Now_processing")); // //$NON-NLS-1$
+
+			pageData = new PageData();
+
+			VisualizeEngine engine = new VisualizeEngine();
+			engine.setBaseUrl(""); //$NON-NLS-1$
+			// TODO "\"->"/" windows
+			// engine.setBaseUrl("file:///"+RESULT_DIR);
+
+			engine.setTargetUrl(targetUrl);
+			engine.setDocument(document);
+			engine.setHtml2viewMapV(html2ViewMapV);
+
+			// TODO invisibleElements
+			// HashSet invisibleIdSet = new HashSet();
+			// if (webBrowser != null) {
+			// String[] invisibleIds = webBrowser.getInvisibleEleId();
+			// for (int i = 0; i < invisibleIds.length; i++) {
+			// invisibleIdSet.add(invisibleIds[i]);
+			// }
+			// }
+			// engine.setInvisibleIdSet(invisibleIdSet);
+
+			engine.setInvisibleIdSet(new HashSet());
+
+			engine.setPageData(pageData);
+			engine.calculate();
+
+			maxReachingTime = engine.getMaxTime();
+			setInfoMessage(createMaxTimeString());
+
+			resultDocument = engine.getResult();
+			checkResult.setProblemList(engine.getProbelems());
+			checkResult.setTargetUrl(targetUrl);
+
+			checkResult.addAssociateFile(engine.getVariantFile());
+
+			IVisualizeMapData mapData = engine.getVisualizeMapData();
+
+			// TODO
+			checkResult.setSourceFile(new File(tmpDirS + HTML_SOURCE_FILE));
+
+			boolean isDBCS = false;
+			if (ParamBlind.getInstance().iLanguage == ParamBlind.JP) {
+				isDBCS = true;
+			}
+
+			HtmlEvalUtil edu = new HtmlEvalUtil(document, resultDocument,
+					targetUrl, mapData.getOrig2idMap(), originalDocument,
+					ieDom, pageData, isDBCS, isIEhtml);
+
+			ArrayList<IProblemItem> tmpResults = new ArrayList<IProblemItem>(
+					1024);
+
+			// TODO re-impl BrowserAndStyleInfo
+			//
+			// BrowserAndStyleInfo data =
+			// webBrowser.getBrowserAndStyleInfo();
+			IHtmlCheckTarget checkTarget = new HtmlCheckTargetImpl(document,
+					webBrowser.getURL(), null, edu);
+
+			for (int i = 0; i < checkers.length; i++) {
+				if (checkers[i] instanceof IHtmlChecker) {
+					tmpResults.addAll(((IHtmlChecker) checkers[i])
+							.checkHtml(checkTarget));
+				} else if (checkers[i].isTargetFormat(webBrowser
+						.getCurrentMIMEType())
+						&& checkers[i].isEnabled()) {
+					tmpResults.addAll(checkers[i].check(checkTarget));
+				}
+			}
+
+			// TODO support blind biz -> visitor
+			for (int i = 0; i < tmpResults.size(); i++) {
+				IProblemItem tmpItem = (IProblemItem) tmpResults.get(i);
+				HighlightTargetNodeInfo nodeInfo = tmpItem
+						.getHighlightTargetNodeInfo();
+				if (nodeInfo != null) {
+					tmpItem.setHighlightTargetIds(nodeInfo
+							.getHighlightTargetIds(mapData.getOrig2idMap()));
+					if (EvaluationPreferencesUtil.isOriginalDOM()) {
+						tmpItem.setHighlightTargetSourceInfo(nodeInfo
+								.getHighlightTargetSourceInfo(html2ViewMapV));
+					}
+				}
+			}
+			checkResult.addProblemItems(tmpResults);
+			checkResult
+					.addProblemItems(errorLogListener.getHtmlProblemVector());
+			checkResult.accept(pageData);
+
+			// TODO move (add Icons into result doc) here
+
+			resultFile = BlindVizEnginePlugin.createTempFile(
+					IVisualizationConst.PREFIX_RESULT,
+					IVisualizationConst.SUFFIX_HTML);
+			File tmpFile = BlindVizEnginePlugin.createTempFile("tmp",
+					IVisualizationConst.SUFFIX_HTML);
+
+			try {
+				HtmlParserUtil.saveHtmlDocumentAsUTF8(
+						(SHDocument) resultDocument, tmpFile, resultFile);
+			} catch (Exception e3) {
+				DebugPrintUtil
+						.devOrDebugPrintln("error: saveHtmlDocumentAsUTF8");
+				try {
+					PrintWriter pw = new PrintWriter(new OutputStreamWriter(
+							new FileOutputStream(resultFile), "UTF-8"));
+					((SHDocument) resultDocument).printAsSGML(pw, true);
+					pw.flush();
+					pw.close();
+				} catch (Exception e4) {
+
+				}
+			}
+
+			if (hasFrame) {
+				return FRAME;
+			} else if (webBrowser != null && !webBrowser.isUrlExists()) {
+				// TODO
+				return ERROR;
+			}
+			return OK;
+
+		} catch (Exception e) {
+			setStatusMessage("Visualization Error");
+			e.printStackTrace();
+			return ERROR;
+		}
+
+	}
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.blind.odfbyhtml/.classpath b/plugins/org.eclipse.actf.visualization.blind.odfbyhtml/.classpath
new file mode 100644
index 0000000..751c8f2
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind.odfbyhtml/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/plugins/org.eclipse.actf.visualization.blind.odfbyhtml/.project b/plugins/org.eclipse.actf.visualization.blind.odfbyhtml/.project
new file mode 100644
index 0000000..f391120
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind.odfbyhtml/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.actf.visualization.blind.odfbyhtml</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/plugins/org.eclipse.actf.visualization.blind.odfbyhtml/META-INF/MANIFEST.MF b/plugins/org.eclipse.actf.visualization.blind.odfbyhtml/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..befda8f
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind.odfbyhtml/META-INF/MANIFEST.MF
@@ -0,0 +1,8 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Eclipse ACTF ODF Visualization Fragment (Incubation)
+Bundle-SymbolicName: org.eclipse.actf.visualization.blind.odfbyhtml;singleton:=true
+Bundle-Version: 0.0.1
+Bundle-Vendor: Eclipse.org
+Fragment-Host: org.eclipse.actf.visualization.blind;bundle-version="0.0.1"
+Bundle-Localization: plugin
diff --git a/plugins/org.eclipse.actf.visualization.blind.odfbyhtml/about.html b/plugins/org.eclipse.actf.visualization.blind.odfbyhtml/about.html
new file mode 100644
index 0000000..481dbcf
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind.odfbyhtml/about.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>June 5, 2006</p>	
+<h3>License</h3>
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;).  
+Unless otherwise indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;).  A copy of the EPL is available 
+at <a href="http://www.eclipse.org/org/documents/epl-v10.php">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is 
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content.  Check the Redistributor&rsquo;s license 
+that was provided with the Content.  If no such license exists, contact the Redistributor.  Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/plugins/org.eclipse.actf.visualization.blind.odfbyhtml/build.properties b/plugins/org.eclipse.actf.visualization.blind.odfbyhtml/build.properties
new file mode 100644
index 0000000..150249a
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind.odfbyhtml/build.properties
@@ -0,0 +1,16 @@
+###############################################################################
+# Copyright (c) 2008 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#     IBM Corporation - initial API and implementation
+###############################################################################
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               fragment.xml,\
+               about.html
diff --git a/plugins/org.eclipse.actf.visualization.blind.odfbyhtml/fragment.xml b/plugins/org.eclipse.actf.visualization.blind.odfbyhtml/fragment.xml
new file mode 100644
index 0000000..925ce90
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind.odfbyhtml/fragment.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.2"?>
+<fragment>
+   <extension
+         point="org.eclipse.actf.visualization.blind.blindVisualizer">
+      <blindVisualizer
+            class="org.eclipse.actf.visualization.blind.odfbyhtml.BlindVisualizerOdfByHtml"
+            id="org.eclipse.actf.visualization.blind.html.blindVisualizer2"/>
+   </extension>
+
+</fragment>
diff --git a/plugins/org.eclipse.actf.visualization.blind.odfbyhtml/src/org/eclipse/actf/visualization/blind/odfbyhtml/BlindVisualizerOdfByHtml.java b/plugins/org.eclipse.actf.visualization.blind.odfbyhtml/src/org/eclipse/actf/visualization/blind/odfbyhtml/BlindVisualizerOdfByHtml.java
new file mode 100644
index 0000000..05c00ee
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind.odfbyhtml/src/org/eclipse/actf/visualization/blind/odfbyhtml/BlindVisualizerOdfByHtml.java
@@ -0,0 +1,196 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.blind.odfbyhtml;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Vector;
+
+import org.eclipse.actf.model.IModelService;
+import org.eclipse.actf.model.dom.html.impl.SHDocument;
+import org.eclipse.actf.model.dom.html.util.HtmlParserUtil;
+import org.eclipse.actf.util.DebugPrintUtil;
+import org.eclipse.actf.util.FileUtils;
+import org.eclipse.actf.util.html2view.Html2ViewMapMaker;
+import org.eclipse.actf.visualization.IVisualizationConst;
+import org.eclipse.actf.visualization.blind.BlindVisualizerBase;
+import org.eclipse.actf.visualization.blind.IBlindVisualizer;
+import org.eclipse.actf.visualization.blind.ui.internal.Messages;
+import org.eclipse.actf.visualization.engines.blind.BlindVizEnginePlugin;
+import org.eclipse.actf.visualization.engines.blind.eval.EvaluationResultBlind;
+import org.eclipse.actf.visualization.engines.blind.html.IVisualizeMapData;
+import org.eclipse.actf.visualization.engines.blind.html.VisualizeEngine;
+import org.eclipse.actf.visualization.engines.blind.html.eval.HtmlErrorLogListener;
+import org.eclipse.actf.visualization.engines.blind.html.util.ODFVisualizeViewUtil;
+import org.eclipse.actf.visualization.eval.CheckTargetImpl;
+import org.eclipse.actf.visualization.eval.ICheckTarget;
+import org.eclipse.actf.visualization.eval.IChecker;
+import org.eclipse.actf.visualization.eval.extensions.CheckerExtension;
+import org.eclipse.actf.visualization.eval.guideline.GuidelineHolder;
+import org.eclipse.actf.visualization.eval.html.statistics.PageData;
+import org.eclipse.actf.visualization.eval.problem.HighlightTargetNodeInfo;
+import org.eclipse.actf.visualization.eval.problem.IProblemItem;
+import org.w3c.dom.Document;
+
+public class BlindVisualizerOdfByHtml extends BlindVisualizerBase implements
+		IBlindVisualizer {
+
+	private final String ODF_HTML_FILE_NAME = "ODF.html";
+
+	private final String odf_html_fileS = tmpDirS + ODF_HTML_FILE_NAME;
+
+	public boolean setModelService(IModelService targetModel) {
+		if (super.setModelService(targetModel)) {
+			if (targetUrl.startsWith("file://")) {
+				targetUrl = targetUrl.substring(8);
+			}
+			targetUrl = targetUrl.replaceAll("%20", " ");
+			return true;
+		}
+		return false;
+	}
+
+	public int visualize() {
+		if (null == modelService) {
+			return ERROR;
+		}
+
+		GuidelineHolder.getInstance().setTargetMimeType(
+				modelService.getCurrentMIMEType());
+
+		modelService.saveDocumentAsHTMLFile(odf_html_fileS);
+
+		checkResult = new EvaluationResultBlind();
+
+		try {
+
+			FileUtils
+					.copyFile(odf_html_fileS, tmpDirS + HTML_SOURCE_FILE, true);
+
+			Html2ViewMapMaker h2vmm = new Html2ViewMapMaker();
+			Vector html2ViewMapV = new Vector();
+
+			HtmlParserUtil hpu = new HtmlParserUtil();
+			HtmlErrorLogListener errorLogListener = new HtmlErrorLogListener();
+			hpu.addErrorLogListener(errorLogListener);
+			String targetFile = tmpDirS + MAPPED_HTML_FILE_PRE + ".html";
+
+			html2ViewMapV = h2vmm.makeMap(ODF_HTML_FILE_NAME,
+					MAPPED_HTML_FILE_PRE + ".html", tmpDirS);
+			if (html2ViewMapV.size() == 0) {
+				targetFile = odf_html_fileS;
+			}
+
+			HtmlParserUtil tmpHPU = new HtmlParserUtil();
+			tmpHPU.parse(new FileInputStream(targetFile));
+			Document document = tmpHPU.getSHDocument();
+
+			if (document == null) {
+				return ERROR;
+			}
+
+			setStatusMessage(Messages.getString("BlindView.Now_processing")); // //$NON-NLS-1$
+
+			pageData = new PageData();
+
+			VisualizeEngine engine = new VisualizeEngine();
+			engine.setBaseUrl(""); //$NON-NLS-1$
+			// TODO "\"->"/" windows
+			// engine.setBaseUrl("file:///"+RESULT_DIR);
+
+			engine.setTargetUrl(targetUrl);
+			engine.setDocument(document);
+			engine.setHtml2viewMapV(html2ViewMapV);
+			engine.setInvisibleIdSet(new HashSet());
+			engine.setPageData(pageData);
+			engine.calculate();
+
+			maxReachingTime = engine.getMaxTime();
+			setInfoMessage(createMaxTimeString());
+
+			resultDocument = engine.getResult();
+			checkResult.setProblemList(engine.getProbelems());
+			checkResult.setTargetUrl(targetUrl);
+			checkResult.addAssociateFile(engine.getVariantFile());
+
+			IVisualizeMapData mapData = engine.getVisualizeMapData();
+
+			// TODO
+			checkResult.setSourceFile(new File(tmpDirS + HTML_SOURCE_FILE));
+
+			ArrayList<IProblemItem> tmpResults = new ArrayList<IProblemItem>(
+					1024);
+
+			Document odfDoc = modelService.getDocument();
+			ICheckTarget checkTarget = new CheckTargetImpl(odfDoc, modelService
+					.getURL());
+			checkTarget.setAdditionalDocument("html", document);
+			IChecker[] checkers = CheckerExtension.getCheckers();
+			for (int i = 0; i < checkers.length; i++) {
+				// TODO mimetype -> ???
+				if (checkers[i].isTargetFormat(modelService
+						.getCurrentMIMEType())
+						&& checkers[i].isEnabled()) {
+					long startTime = System.currentTimeMillis();
+					tmpResults.addAll(checkers[i].check(checkTarget));
+					DebugPrintUtil.devOrDebugPrintln(System.currentTimeMillis()
+							- startTime);
+				}
+			}
+			ODFVisualizeViewUtil.visualizeError(resultDocument, tmpResults);
+
+			// TODO support blind biz -> visitor
+			for (int i = 0; i < tmpResults.size(); i++) {
+				IProblemItem tmpItem = (IProblemItem) tmpResults.get(i);
+				HighlightTargetNodeInfo nodeInfo = tmpItem
+						.getHighlightTargetNodeInfo();
+				if (nodeInfo != null) {
+					tmpItem.setHighlightTargetIds(nodeInfo
+							.getHighlightTargetIds(mapData.getOrig2idMap()));
+				}
+			}
+			checkResult.addProblemItems(tmpResults);
+			checkResult.accept(pageData);
+
+			// TODO move (add Icons into result doc) here
+
+			resultFile = BlindVizEnginePlugin.createTempFile(
+					IVisualizationConst.PREFIX_RESULT,
+					IVisualizationConst.SUFFIX_HTML);
+
+			try {
+				PrintWriter pw = new PrintWriter(new OutputStreamWriter(
+						new FileOutputStream(resultFile), "UTF-8"));
+				((SHDocument) resultDocument).printAsSGML(pw, true);
+				pw.flush();
+				pw.close();
+			} catch (Exception e3) {
+				e3.printStackTrace();
+			}
+		} catch (Exception e) {
+			setStatusMessage("Visualization Error");
+			e.printStackTrace();
+			return ERROR;
+		}
+
+		return 0;
+	}
+
+	public boolean isTarget(IModelService modelService) {
+		return (null != modelService && modelService.getCurrentMIMEType()
+				.startsWith("application/vnd.oasis.opendocument."));
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.blind/.classpath b/plugins/org.eclipse.actf.visualization.blind/.classpath
new file mode 100644
index 0000000..751c8f2
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/plugins/org.eclipse.actf.visualization.blind/.project b/plugins/org.eclipse.actf.visualization.blind/.project
new file mode 100644
index 0000000..20c1218
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.actf.visualization.blind</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/plugins/org.eclipse.actf.visualization.blind/.settings/org.eclipse.core.resources.prefs b/plugins/org.eclipse.actf.visualization.blind/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..d2d9315
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Thu Jan 31 21:51:24 JST 2008
+eclipse.preferences.version=1
+encoding//src/org/eclipse/actf/visualization/blind/ui/internal/messages.properties=8859_1
diff --git a/plugins/org.eclipse.actf.visualization.blind/META-INF/MANIFEST.MF b/plugins/org.eclipse.actf.visualization.blind/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..6a152ad
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind/META-INF/MANIFEST.MF
@@ -0,0 +1,18 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Eclipse ACTF Blind Visualization Plugin (Incubation)
+Bundle-SymbolicName: org.eclipse.actf.visualization.blind;singleton:=true
+Bundle-Version: 0.0.1
+Bundle-Activator: org.eclipse.actf.visualization.blind.BlindVizPlugin
+Bundle-Vendor: Eclipse.org
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.actf.common,
+ org.eclipse.actf.visualization.engines.blind,
+ org.eclipse.actf.visualization.engines.blind.html,
+ org.eclipse.actf.visualization.eval,
+ org.eclipse.actf.visualization.ui.report,
+ org.eclipse.actf.model.dom.html
+Eclipse-LazyStart: true
+Export-Package: org.eclipse.actf.visualization.blind.ui.views
diff --git a/plugins/org.eclipse.actf.visualization.blind/about.html b/plugins/org.eclipse.actf.visualization.blind/about.html
new file mode 100644
index 0000000..481dbcf
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind/about.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>June 5, 2006</p>	
+<h3>License</h3>
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;).  
+Unless otherwise indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;).  A copy of the EPL is available 
+at <a href="http://www.eclipse.org/org/documents/epl-v10.php">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is 
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content.  Check the Redistributor&rsquo;s license 
+that was provided with the Content.  If no such license exists, contact the Redistributor.  Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/plugins/org.eclipse.actf.visualization.blind/build.properties b/plugins/org.eclipse.actf.visualization.blind/build.properties
new file mode 100644
index 0000000..7f3f0ff
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind/build.properties
@@ -0,0 +1,19 @@
+###############################################################################
+# Copyright (c) 2007, 2008 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#     IBM Corporation - initial API and implementation
+###############################################################################
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               plugin.xml,\
+               plugin.properties,\
+               plugin_ja.properties,\
+               icons/,\
+               about.html
diff --git a/plugins/org.eclipse.actf.visualization.blind/icons/visualize.gif b/plugins/org.eclipse.actf.visualization.blind/icons/visualize.gif
new file mode 100644
index 0000000..621da47
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind/icons/visualize.gif
Binary files differ
diff --git a/plugins/org.eclipse.actf.visualization.blind/plugin.properties b/plugins/org.eclipse.actf.visualization.blind/plugin.properties
new file mode 100644
index 0000000..24b2d9a
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind/plugin.properties
@@ -0,0 +1,11 @@
+###############################################################################
+# Copyright (c) 2007, 2008 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#     IBM Corporation - initial API and implementation
+###############################################################################
+adesigner.blind.view.title=Blind
diff --git a/plugins/org.eclipse.actf.visualization.blind/plugin.xml b/plugins/org.eclipse.actf.visualization.blind/plugin.xml
new file mode 100644
index 0000000..bae7653
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind/plugin.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.2"?>
+<plugin>
+   <extension-point id="blindVisualizer" name="blind Visualizer" schema="schema/BlindVisualizer.exsd"/>
+  <extension
+         point="org.eclipse.ui.views">
+      <view
+            class="org.eclipse.actf.visualization.blind.ui.views.BlindView"
+            icon="icons/visualize.gif"
+            id="org.eclipse.actf.visualization.blind.ui.views.BlindView"
+            name="%adesigner.blind.view.title"/>
+   </extension>
+</plugin>
diff --git a/plugins/org.eclipse.actf.visualization.blind/plugin_ja.properties b/plugins/org.eclipse.actf.visualization.blind/plugin_ja.properties
new file mode 100644
index 0000000..720deb8
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind/plugin_ja.properties
@@ -0,0 +1,11 @@
+###############################################################################
+# Copyright (c) 2007, 2008 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#     IBM Corporation - initial API and implementation
+###############################################################################
+adesigner.blind.view.title=\u97f3\u58f0\u30e6\u30fc\u30b6\u30d3\u30ea\u30c6\u30a3
diff --git a/plugins/org.eclipse.actf.visualization.blind/schema/blindVisualizer.exsd b/plugins/org.eclipse.actf.visualization.blind/schema/blindVisualizer.exsd
new file mode 100644
index 0000000..486d5d4
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind/schema/blindVisualizer.exsd
@@ -0,0 +1,116 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.actf.visualization.blind">
+<annotation>
+      <appInfo>
+         <meta.schema plugin="org.eclipse.actf.visualization.blind" id="blindVisualizer" name="Blind Visualizer"/>
+      </appInfo>
+      <documentation>
+         [Enter description of this extension point.]
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <complexType>
+         <sequence minOccurs="1" maxOccurs="unbounded">
+            <element ref="blindVisualizer"/>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appInfo>
+                  <meta.attribute translatable="true"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="blindVisualizer">
+      <complexType>
+         <attribute name="id" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="class" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appInfo>
+                  <meta.attribute kind="java" basedOn="org.eclipse.actf.visualization.blind.IBlindVisualizer"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="since"/>
+      </appInfo>
+      <documentation>
+         [Enter the first release in which this extension point appears.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="examples"/>
+      </appInfo>
+      <documentation>
+         [Enter extension point usage example here.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="apiInfo"/>
+      </appInfo>
+      <documentation>
+         [Enter API information here.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="implementation"/>
+      </appInfo>
+      <documentation>
+         [Enter information about supplied implementation of this extension point.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="copyright"/>
+      </appInfo>
+      <documentation>
+         Copyright (c) 2007, 2008 IBM Corporation and others.&lt;br&gt;
+All rights reserved. This program and the accompanying materials are made
+available under the terms of the Eclipse Public License v1.0 which accompanies
+this distribution, and is available at &lt;a 
+href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
+      </documentation>
+   </annotation>
+
+</schema>
diff --git a/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/BlindVisualizerBase.java b/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/BlindVisualizerBase.java
new file mode 100644
index 0000000..59329a5
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/BlindVisualizerBase.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.blind;
+
+import java.io.File;
+
+import org.eclipse.actf.model.IModelService;
+import org.eclipse.actf.visualization.IVisualizationView;
+import org.eclipse.actf.visualization.blind.ui.internal.Messages;
+import org.eclipse.actf.visualization.engines.blind.BlindVizEnginePlugin;
+import org.eclipse.actf.visualization.engines.blind.eval.EvaluationResultBlind;
+import org.eclipse.actf.visualization.eval.IChecker;
+import org.eclipse.actf.visualization.eval.IEvaluationResult;
+import org.eclipse.actf.visualization.eval.extensions.CheckerExtension;
+import org.eclipse.actf.visualization.eval.html.statistics.PageData;
+import org.w3c.dom.Document;
+
+public abstract class BlindVisualizerBase implements IBlindVisualizer{
+
+	protected IChecker[] checkers = CheckerExtension.getCheckers();
+	protected String tmpDirS = BlindVizEnginePlugin.getTempDirectoryString();
+	protected String targetUrl = "";
+	protected IModelService modelService;
+
+	//for reuslt
+	protected IEvaluationResult checkResult = new EvaluationResultBlind();
+	protected Document resultDocument;
+	protected PageData pageData;
+	protected int maxReachingTime = 0;
+	protected File resultFile;
+
+	private IVisualizationView vizView;
+	
+	protected abstract boolean isTarget(IModelService modelService);
+	
+	public boolean setModelService(IModelService targetModel){
+		modelService = null;
+		targetUrl="";
+		if (!isTarget(targetModel)) {
+			return false;
+		}
+		
+		modelService = targetModel;
+		targetUrl = targetModel.getURL();
+		return true;
+	}
+
+	public void setVisualizationView(IVisualizationView targetView){
+		vizView = targetView;
+	}
+	
+	public String createMaxTimeString() {
+		return Messages.formatResourceString("BlindView.Maximum_Time",
+				maxReachingTime);
+	}
+
+	public IEvaluationResult getCheckResult() {
+		return checkResult;
+	}
+
+	public PageData getPageData() {
+		return pageData;
+	}
+
+	public Document getResultDocument() {
+		return resultDocument;
+	}
+
+	public File getResultFile() {
+		return resultFile;
+	}
+	
+	protected void setStatusMessage(String message){
+		if(null!=vizView){
+			vizView.setStatusMessage(message);
+		}
+	}
+
+	protected void setInfoMessage(String message){
+		if(null!=vizView){
+			vizView.setInfoMessage(message);
+		}
+	}
+
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/BlindVisualizerExtension.java b/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/BlindVisualizerExtension.java
new file mode 100644
index 0000000..b34464f
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/BlindVisualizerExtension.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.blind;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.Platform;
+
+public class BlindVisualizerExtension {
+
+	private static final String VISUALIZER = "blindVisualizer";
+
+	private static final String ATTR_CLASS = "class";
+
+	private static BlindVisualizerExtension[] extensions;
+
+	private static IBlindVisualizer[] visualizers = null;
+
+	public static IBlindVisualizer[] getVisualizers() {
+		if (visualizers != null) {
+			return visualizers;
+		}
+
+		BlindVisualizerExtension[] tmpExtensions = getExtensions();
+		ArrayList<IBlindVisualizer> tmpList = new ArrayList<IBlindVisualizer>();
+		if (tmpExtensions != null) {
+			for (int i = 0; i < tmpExtensions.length; i++) {
+				IBlindVisualizer tmpProvider = tmpExtensions[i]
+						.getElementViewerInfoProvider();
+				if (tmpProvider != null) {
+					tmpList.add(tmpProvider);
+				}
+			}
+		}
+		visualizers = new IBlindVisualizer[tmpList.size()];
+		tmpList.toArray(visualizers);
+		return visualizers;
+	}
+
+	private static BlindVisualizerExtension[] getExtensions() {
+		if (extensions != null)
+			return extensions;
+
+		IExtension[] tmpExtensions = Platform.getExtensionRegistry()
+				.getExtensionPoint(BlindVizPlugin.PLUGIN_ID,
+						VISUALIZER).getExtensions();
+
+		if (Platform.inDevelopmentMode() || Platform.inDebugMode()) {
+			System.out
+					.println("Blind Visualizer:" + tmpExtensions.length);
+		}
+		List<BlindVisualizerExtension> l = new ArrayList<BlindVisualizerExtension>();
+		for (int i = 0; i < tmpExtensions.length; i++) {
+			IConfigurationElement[] configElements = tmpExtensions[i]
+					.getConfigurationElements();
+			for (int j = 0; j < configElements.length; j++) {
+				BlindVisualizerExtension ex = parseExtension(configElements[j]);
+				if (ex != null) {
+					l.add(ex);
+				}
+			}
+		}
+		extensions = l.toArray(new BlindVisualizerExtension[l.size()]);
+		return extensions;
+	}
+
+	private static BlindVisualizerExtension parseExtension(
+			IConfigurationElement configElement) {
+		if (!configElement.getName().equals(VISUALIZER)) {
+			return null;
+		}
+		try {
+			return new BlindVisualizerExtension(configElement);
+		} catch (Exception e) {
+		}
+		return null;
+	}
+
+	private IBlindVisualizer visualizer = null;
+
+	private BlindVisualizerExtension(IConfigurationElement configElement) {
+		try {
+			this.visualizer = (IBlindVisualizer) configElement
+					.createExecutableExtension(ATTR_CLASS);
+		} catch (Exception e) {
+		}
+	}
+
+	private IBlindVisualizer getElementViewerInfoProvider() {
+		return this.visualizer;
+	}
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/BlindVizPlugin.java b/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/BlindVizPlugin.java
new file mode 100644
index 0000000..39ac2ed
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/BlindVizPlugin.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.blind;
+
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class BlindVizPlugin extends AbstractUIPlugin {
+
+	// The plug-in ID
+	public static final String PLUGIN_ID = "org.eclipse.actf.visualization.blind";
+
+	// The shared instance
+	private static BlindVizPlugin plugin;
+	
+	/**
+	 * The constructor
+	 */
+	public BlindVizPlugin() {
+		plugin = this;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+	 */
+	public void start(BundleContext context) throws Exception {
+		super.start(context);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+	 */
+	public void stop(BundleContext context) throws Exception {
+		plugin = null;
+		super.stop(context);
+	}
+
+	/**
+	 * Returns the shared instance
+	 *
+	 * @return the shared instance
+	 */
+	public static BlindVizPlugin getDefault() {
+		return plugin;
+	}
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/IBlindVisualizer.java b/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/IBlindVisualizer.java
new file mode 100644
index 0000000..50801c9
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/IBlindVisualizer.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.blind;
+
+import java.io.File;
+
+import org.eclipse.actf.model.IModelService;
+import org.eclipse.actf.visualization.IVisualizationView;
+import org.eclipse.actf.visualization.eval.IEvaluationResult;
+import org.eclipse.actf.visualization.eval.html.statistics.PageData;
+import org.w3c.dom.Document;
+
+public interface IBlindVisualizer {
+
+	public static final int ERROR = -1;
+
+	public static final int OK = 0;
+	
+	public static final String MAPPED_HTML_FILE_PRE = "MappedHTML";
+	
+	public static final String HTML_SOURCE_FILE = "source.html";
+
+	public abstract int visualize();
+
+	public abstract String createMaxTimeString();
+
+	public abstract IEvaluationResult getCheckResult();
+
+	public abstract PageData getPageData();
+
+	public abstract Document getResultDocument();
+
+	public abstract File getResultFile();		
+
+	public abstract boolean setModelService(IModelService modelService);
+	
+	public abstract void setVisualizationView(IVisualizationView targetView);
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/ui/actions/BlindSaveAction.java b/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/ui/actions/BlindSaveAction.java
new file mode 100644
index 0000000..94fd08f
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/ui/actions/BlindSaveAction.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.blind.ui.actions;
+
+import org.eclipse.actf.util.ui.Messages;
+import org.eclipse.actf.visualization.blind.ui.internal.PartControlBlind;
+import org.eclipse.actf.visualization.engines.blind.BlindVizEnginePlugin;
+import org.eclipse.jface.action.Action;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+
+
+
+public class BlindSaveAction extends Action {
+    PartControlBlind prb;
+    
+	public BlindSaveAction(PartControlBlind prb) {
+		setToolTipText(Messages.getString("Tooltip.Save")); //$NON-NLS-1$
+		//TODO
+		setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin(BlindVizEnginePlugin.PLUGIN_ID, "icons/ButtonSave.png"));
+		setText(Messages.getString("MenuConst.Save")); //$NON-NLS-1$
+        this.prb = prb;
+	}
+
+	public void run() {
+        prb.doSave();
+	}
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/ui/actions/BlindVisualizationAction.java b/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/ui/actions/BlindVisualizationAction.java
new file mode 100644
index 0000000..d91a8c3
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/ui/actions/BlindVisualizationAction.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.blind.ui.actions;
+
+import org.eclipse.actf.visualization.blind.ui.internal.PartControlBlind;
+import org.eclipse.actf.visualization.engines.blind.BlindVizEnginePlugin;
+import org.eclipse.actf.visualization.blind.ui.internal.Messages;
+import org.eclipse.jface.action.Action;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+
+
+
+public class BlindVisualizationAction extends Action {
+    PartControlBlind prb;
+
+    public BlindVisualizationAction(PartControlBlind prb) {
+        setToolTipText(Messages.getString("BlindView.Visualize_4")); //$NON-NLS-1$
+        //TODO
+        setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin(BlindVizEnginePlugin.PLUGIN_ID, "icons/visualize_A.png"));
+        setText(Messages.getString("BlindVisualizationAction.0")); //$NON-NLS-1$
+        this.prb = prb;
+    }
+
+    public void run() {
+        prb.doVisualize();
+    }
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/ui/internal/BlindToolBar.java b/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/ui/internal/BlindToolBar.java
new file mode 100644
index 0000000..906d162
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/ui/internal/BlindToolBar.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Norimasa HAYASHIDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.blind.ui.internal;
+
+import org.eclipse.actf.visualization.blind.ui.actions.BlindSaveAction;
+import org.eclipse.actf.visualization.blind.ui.actions.BlindVisualizationAction;
+import org.eclipse.actf.visualization.engines.blind.html.ui.actions.BlindOpenIdCssAction;
+import org.eclipse.actf.visualization.engines.blind.ui.actions.BlindSettingAction;
+import org.eclipse.jface.action.ActionContributionItem;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.action.ToolBarManager;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.ToolBar;
+
+
+public class BlindToolBar extends Composite {
+
+    PartControlBlind prb;
+    
+	public BlindToolBar(Composite parent, int style, PartControlBlind prb) {
+		super(parent, style);
+        this.prb = prb;
+		initLayout(parent);
+	}
+
+	private void initLayout(Composite parent) {
+
+		GridLayout gridLayout = new GridLayout();
+		gridLayout.marginTop = 0;
+		gridLayout.marginBottom = 1;
+		gridLayout.marginHeight = gridLayout.marginWidth = 1;
+		setLayout(gridLayout);
+
+		ToolBar toolBar = new ToolBar(this, SWT.RIGHT);
+		ToolBarManager toolBarManager = new ToolBarManager(toolBar);
+
+		ActionContributionItem visualizeActionItem = new ActionContributionItem(new BlindVisualizationAction(prb));
+		visualizeActionItem.setMode(ActionContributionItem.MODE_FORCE_TEXT);
+		toolBarManager.add(visualizeActionItem);
+		toolBarManager.add(new Separator());
+
+		ActionContributionItem settingActionItem = new ActionContributionItem(new BlindSettingAction());
+		settingActionItem.setMode(ActionContributionItem.MODE_FORCE_TEXT);
+		toolBarManager.add(settingActionItem);
+		toolBarManager.add(new Separator());
+
+		ActionContributionItem saveActionItem = new ActionContributionItem(new BlindSaveAction(prb));
+		saveActionItem.setMode(ActionContributionItem.MODE_FORCE_TEXT);
+		toolBarManager.add(saveActionItem);
+		toolBarManager.add(new Separator());
+
+		ActionContributionItem openIdCssActionItem = new ActionContributionItem(new BlindOpenIdCssAction());
+		openIdCssActionItem.setMode(ActionContributionItem.MODE_FORCE_TEXT);
+		toolBarManager.add(openIdCssActionItem);
+
+		toolBarManager.update(true);
+	}
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/ui/internal/BlindVisualizationBrowser.java b/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/ui/internal/BlindVisualizationBrowser.java
new file mode 100644
index 0000000..f50b92f
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/ui/internal/BlindVisualizationBrowser.java
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.blind.ui.internal;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.ole.win32.OLE;
+import org.eclipse.swt.ole.win32.OleAutomation;
+import org.eclipse.swt.ole.win32.OleControlSite;
+import org.eclipse.swt.ole.win32.OleFrame;
+import org.eclipse.swt.ole.win32.Variant;
+import org.eclipse.swt.widgets.Composite;
+
+
+public class BlindVisualizationBrowser {
+
+    private final static String WEBBROWSER_CONTROL_NAME = "Shell.Explorer"; //$NON-NLS-1$
+
+    private final static String NAVIGATE_METHOD_NAME = "Navigate"; //$NON-NLS-1$
+
+    private final static String URL_PARAM_NAME = "URL"; //$NON-NLS-1$
+
+    private final static Variant[] ARG_CLEAR_HIGHLIGHT = new Variant[] { new Variant("clearHighlight();") };
+
+    private OleAutomation oleAutomationIE;
+
+    private OleAutomation ieWindowAutomation = null;
+
+    private int id_exec_script;
+
+    private int id_navigate;
+
+    private int[] id_url_param;
+
+    public BlindVisualizationBrowser(Composite parent) {
+
+        GridLayout gridLayout = new GridLayout();
+        gridLayout.marginHeight = gridLayout.marginWidth = 0;
+        gridLayout.horizontalSpacing = gridLayout.verticalSpacing = 0;
+        parent.setLayout(gridLayout);
+
+        // Web browser
+        OleFrame webFrame = new OleFrame(parent, SWT.NONE);
+        OleControlSite webControlSite = new OleControlSite(webFrame, SWT.NONE, WEBBROWSER_CONTROL_NAME);
+        oleAutomationIE = new OleAutomation(webControlSite);
+
+        // enable OLE
+        webControlSite.doVerb(OLE.OLEIVERB_INPLACEACTIVATE);
+
+        // init ids
+        int[] rgdispid = oleAutomationIE.getIDsOfNames(new String[] { NAVIGATE_METHOD_NAME, URL_PARAM_NAME });
+        id_navigate = rgdispid[0];
+        id_url_param = new int[1];
+        id_url_param[0] = rgdispid[1];
+
+        GridData gridData2 = new GridData();
+        gridData2.horizontalAlignment = GridData.FILL;
+        gridData2.grabExcessHorizontalSpace = true;
+        gridData2.verticalAlignment = GridData.FILL;
+        gridData2.grabExcessVerticalSpace = true;
+        webFrame.setLayoutData(gridData2);
+
+    }
+
+    protected void setBrowserSilent() {
+        int[] rgdispid = oleAutomationIE.getIDsOfNames(new String[] { "Silent" }); //$NON-NLS-1$
+        int dispIdMember = rgdispid[0];
+        Variant varSilent = new Variant((short) 1); // set to true (0 = false)
+        oleAutomationIE.setProperty(dispIdMember, varSilent);
+    }
+
+    protected void disposeOleBrowser() {
+        if (oleAutomationIE != null) {
+            oleAutomationIE.dispose();
+        }
+    }
+
+    // Display the result HTML in blind IE
+    // Checked:
+    protected void navigate(String url) {
+
+        Variant[] rgvarg = new Variant[1];
+        rgvarg[0] = new Variant(url);
+
+        // Variant pVarResult =
+        oleAutomationIE.invoke(id_navigate, rgvarg, id_url_param);
+    }
+
+
+    private boolean initWindowAutomation() {
+        if (ieWindowAutomation == null) {
+            try {
+                // get IE WindowAutomation
+                int[] rgdispid = oleAutomationIE.getIDsOfNames(new String[] { "Document" });
+                int dispIdMember = rgdispid[0];
+                Variant result = oleAutomationIE.getProperty(dispIdMember);
+                OleAutomation htmlDocumentAutomation = result.getAutomation();
+                rgdispid = htmlDocumentAutomation.getIDsOfNames(new String[] { "parentWindow" });
+                dispIdMember = rgdispid[0];
+                result = htmlDocumentAutomation.getProperty(dispIdMember);
+                ieWindowAutomation = result.getAutomation();
+
+                rgdispid = ieWindowAutomation.getIDsOfNames(new String[] { "execScript" });
+                id_exec_script = rgdispid[0];
+            } catch (Exception e) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    protected void execScript(String str) {
+        if (initWindowAutomation()) {
+            Variant[] rgvarg = new Variant[1];
+            rgvarg[0] = new Variant(str);
+
+            ieWindowAutomation.invoke(id_exec_script, rgvarg);
+        }
+    }
+
+    protected void clearHighlight() {
+        if (initWindowAutomation()) {
+            ieWindowAutomation.invoke(id_exec_script, ARG_CLEAR_HIGHLIGHT);
+        }
+    }
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/ui/internal/Messages.java b/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/ui/internal/Messages.java
new file mode 100644
index 0000000..13533c9
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/ui/internal/Messages.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.blind.ui.internal;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+import org.eclipse.actf.visualization.blind.BlindVizPlugin;
+
+public class Messages {
+	private static final String BUNDLE_NAME = BlindVizPlugin.PLUGIN_ID+".ui.internal.messages"; //$NON-NLS-1$
+
+	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+			.getBundle(BUNDLE_NAME);
+
+	private Messages() {
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+
+	public static String formatResourceString(String key, Object arg) {
+		Object args[] = { arg };
+		return formatResourceString(key, args);
+	}
+
+	public static String formatResourceString(String key, Object[] args) {
+		return MessageFormat.format(getString(key), args);
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/ui/internal/PartControlBlind.java b/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/ui/internal/PartControlBlind.java
new file mode 100644
index 0000000..85475d3
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/ui/internal/PartControlBlind.java
@@ -0,0 +1,257 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.blind.ui.internal;
+
+import java.io.File;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.actf.mediator.Mediator;
+import org.eclipse.actf.model.IModelService;
+import org.eclipse.actf.model.ModelServiceUtils;
+import org.eclipse.actf.util.ui.DialogSave;
+import org.eclipse.actf.visualization.IVisualizationView;
+import org.eclipse.actf.visualization.blind.BlindVisualizerExtension;
+import org.eclipse.actf.visualization.blind.IBlindVisualizer;
+import org.eclipse.actf.visualization.engines.blind.BlindVizEnginePlugin;
+import org.eclipse.actf.visualization.engines.blind.eval.EvaluationResultBlind;
+import org.eclipse.actf.visualization.engines.blind.eval.PageEvaluation;
+import org.eclipse.actf.visualization.engines.blind.eval.SummaryEvaluation;
+import org.eclipse.actf.visualization.engines.blind.html.ui.elementViewer.IHighlightElementListener;
+import org.eclipse.actf.visualization.engines.blind.html.util.SaveReportBlind;
+import org.eclipse.actf.visualization.engines.blind.html.util.VisualizeReportUtil;
+import org.eclipse.actf.visualization.eval.IEvaluationResult;
+import org.eclipse.actf.visualization.eval.html.statistics.PageData;
+import org.eclipse.actf.visualization.eval.problem.HighlightTargetId;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Shell;
+import org.w3c.dom.Document;
+
+public class PartControlBlind implements IHighlightElementListener {
+
+	public final static String BLIND_REPORT_FILE = "report.htm";
+
+	private IBlindVisualizer[] blindVizualizers = BlindVisualizerExtension
+			.getVisualizers();
+
+	private BlindVisualizationBrowser _blindBrowser;
+
+	private boolean _canSave = false;
+
+	private PageData _pageData;
+
+	private String maxReachingTimeS = "";
+
+	private PageEvaluation _pageEval;
+
+	private Document resultDoc;
+
+	private Shell _shell;
+
+	private String targetUrl;
+
+	private Mediator mediator = Mediator.getInstance();
+
+	private IVisualizationView vizView;
+
+	private IEvaluationResult checkResult = new EvaluationResultBlind();
+
+	public PartControlBlind(IVisualizationView vizView, Composite parent) {
+		this.vizView = vizView;
+		this._shell = parent.getShell();
+
+		new BlindToolBar(parent, SWT.NONE, this);
+
+		this._blindBrowser = new BlindVisualizationBrowser(parent);
+		this._blindBrowser.setBrowserSilent();
+	}
+
+	public void doSave() {
+		String saveFile = DialogSave.open(_shell, DialogSave.HTML, targetUrl,
+				"_blind.htm"); //$NON-NLS-1$
+
+		if (null == this.resultDoc || null == saveFile) {
+			return;
+		}
+
+		String imageBriefDir = saveFile.substring(
+				saveFile.lastIndexOf("\\") + 1, saveFile.lastIndexOf("."))
+				+ "/";
+		// 2007.09.25 remove space character to include JavaScript files
+		imageBriefDir = imageBriefDir.replace(' ', '_');
+		saveReportFile(saveFile, imageBriefDir, true);
+	}
+
+	public int doVisualize() {
+		return doVisualize(true);
+	}
+
+	public int doVisualize(boolean isShowResult) {
+
+		IModelService modelService = ModelServiceUtils.getActiveModelService();
+		int ret = IBlindVisualizer.ERROR;
+		if (modelService == null) {
+			return ret;
+		}
+
+		String resultFilePath = "";
+
+		targetUrl = modelService.getURL();
+		maxReachingTimeS = "";
+
+		checkResult = new EvaluationResultBlind();
+		mediator.setEvaluationResult(vizView, checkResult);// clear result
+		_blindBrowser.navigate("about:blank");
+
+		_canSave = false;
+
+		vizView.setStatusMessage(Messages.getString("BlindView.Now_preparing"));
+
+		for (IBlindVisualizer bvh : blindVizualizers) {
+			if (bvh.setModelService(modelService)) {
+				bvh.setVisualizationView(vizView);
+
+				ret = bvh.visualize();
+
+				_pageData = bvh.getPageData();
+				checkResult = bvh.getCheckResult();
+				resultDoc = bvh.getResultDocument();
+				maxReachingTimeS = bvh.createMaxTimeString();
+
+				resultFilePath = bvh.getResultFile().getAbsolutePath();
+
+				if (ret > IBlindVisualizer.ERROR) { // OK, Frame
+					vizView.setStatusMessage(Messages
+							.getString("BlindView.Now_rendering"));
+					CreateReport cr = new CreateReport(checkResult, new File(
+							BlindVizEnginePlugin.getTempDirectory(), BLIND_REPORT_FILE));
+					if (isShowResult) {
+						_blindBrowser.navigate(resultFilePath);
+						_shell.getDisplay().asyncExec(cr);
+					} else {
+						_blindBrowser.navigate("about:blank");
+						_shell.getDisplay().syncExec(cr);
+					}
+
+					_canSave = true;
+				}
+				return ret;
+			}
+		}
+
+		System.out.println("not supported: " + modelService.getID() + " "
+				+ modelService.getCurrentMIMEType());
+		return IBlindVisualizer.ERROR;
+	}
+
+	/**
+	 * @return
+	 */
+	public PageEvaluation getPageEvaluation() {
+		return _pageEval;
+	}
+
+	public PageData getPageData() {
+		return _pageData;
+	}
+
+	public void saveReportFile(String sFileName, String imageBriefDir,
+			boolean bAccessory) {
+		if (_canSave) {
+			vizView.setStatusMessage(Messages
+					.getString("BlindView.saving_file")); // //$NON-NLS-1$
+
+			// TODO encoding
+			SaveReportBlind.saveReport((Document) resultDoc.cloneNode(true),
+					mediator.getEvaluationResult(vizView), sFileName,
+					imageBriefDir, maxReachingTimeS, _pageEval, bAccessory);
+
+			vizView.setStatusMessage(Messages
+					.getString("BlindView.end_saving_file")); // //$NON-NLS-1$
+		}
+	}
+
+	private class CreateReport extends Thread {
+		IEvaluationResult _checkResult;
+
+		File targetFile;
+
+		CreateReport(IEvaluationResult checkResult, File filePath) {
+			this._checkResult = checkResult;
+			this.targetFile = filePath;
+		}
+
+		public void run() {
+			_pageEval = PageEvaluation.createPageReport(_checkResult
+					.getProblemList(), _pageData);
+			VisualizeReportUtil.createReport(this.targetFile, _pageEval);
+			_shell.getDisplay().asyncExec(new Runnable() {
+				public void run() {
+
+					// TODO through mediator
+					_checkResult.setSummaryReportUrl(targetFile
+							.getAbsolutePath());
+					_checkResult.setSummaryReportText(_pageEval.getSummary());
+					_checkResult.setLineStyleListener(SummaryEvaluation
+							.getHighLightStringListener());
+					mediator.setEvaluationResult(vizView, _checkResult);
+
+					vizView.setStatusMessage(Messages
+							.getString("BlindView.Done"));
+				}
+			});
+		}
+	}
+
+	private void execScript(String script) {
+		_blindBrowser.execScript(script);
+	}
+
+	public void clearHighlight() {
+		_blindBrowser.clearHighlight();
+	}
+
+	protected IEvaluationResult getCheckResult() {
+		return checkResult;
+	}
+
+	public void highlight(List<HighlightTargetId> targetIdList) {
+		if (null != targetIdList) {
+			switch (targetIdList.size()) {
+			case 0:
+				break;
+			case 1:
+				execScript("setHighlight(" + targetIdList.get(0).getStartId()
+						+ "," + targetIdList.get(0).getEndId() + ");");
+				break;
+			default:
+				Iterator<HighlightTargetId> ite = targetIdList.iterator();
+				StringBuffer strStart = new StringBuffer(512);
+				StringBuffer strEnd = new StringBuffer(512);
+				HighlightTargetId tmpId = ite.next();
+				strStart.append(tmpId.getStartId());
+				strEnd.append(tmpId.getEndId());
+				while (ite.hasNext()) {
+					tmpId = ite.next();
+					strStart.append("," + tmpId.getStartId()); //$NON-NLS-1$
+					strEnd.append("," + tmpId.getEndId()); //$NON-NLS-1$
+				}
+
+				String highlightScript = "setHighlight2(new Array(" //$NON-NLS-1$
+						+ strStart.toString() + "), new Array(" //$NON-NLS-1$
+						+ strEnd.toString() + "));"; //$NON-NLS-1$
+				execScript(highlightScript);
+			}
+
+		}
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/ui/internal/SelectionListenerBlind.java b/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/ui/internal/SelectionListenerBlind.java
new file mode 100644
index 0000000..3c86310
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/ui/internal/SelectionListenerBlind.java
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.blind.ui.internal;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.actf.mediator.Mediator;
+import org.eclipse.actf.model.IModelService;
+import org.eclipse.actf.model.IWebBrowserACTF;
+import org.eclipse.actf.visualization.eval.problem.HighlightTargetId;
+import org.eclipse.actf.visualization.eval.problem.HighlightTargetSourceInfo;
+import org.eclipse.actf.visualization.eval.problem.IProblemItem;
+import org.eclipse.actf.visualization.ui.report.table.SrcViewerForPT;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.ISelectionListener;
+import org.eclipse.ui.IWorkbenchPart;
+import org.w3c.dom.Node;
+
+public class SelectionListenerBlind implements ISelectionListener {
+
+	private PartControlBlind prb;
+
+	public SelectionListenerBlind(PartControlBlind prb) {
+		this.prb = prb;
+	}
+
+	public void selectionChanged(IWorkbenchPart part, ISelection selection) {
+		if (selection == null || !(selection instanceof IStructuredSelection)) {
+			System.err.println(this.getClass().getName() + ":" + "Iselection");
+			return;
+		}
+
+		IModelService modelService = Mediator.getInstance()
+				.getActiveModelService();
+
+		// TODO
+		SrcViewerForPT srcViewerForPT = SrcViewerForPT.getInstance();
+		ArrayList<HighlightTargetSourceInfo> srcLineList = new ArrayList<HighlightTargetSourceInfo>();
+
+		if (modelService != null && modelService instanceof IWebBrowserACTF) {
+			((IWebBrowserACTF) modelService).recoveryHighlight();
+		}
+
+		prb.clearHighlight(); //$NON-NLS-1$
+		List<HighlightTargetId> validIdList = new ArrayList<HighlightTargetId>();
+
+		IStructuredSelection structuredSelection = (IStructuredSelection) selection;
+
+		Node targetNode = null;
+		for (Iterator i = structuredSelection.iterator(); i.hasNext();) {
+			Object target = i.next();
+			if (target instanceof IProblemItem) {
+				IProblemItem tmpItem = (IProblemItem) target;
+				if (prb.getCheckResult().getProblemList().contains(tmpItem)) {
+					targetNode = tmpItem.getTargetNode();
+					srcLineList.addAll(Arrays.asList(tmpItem
+							.getHighlightTargetSoruceInfo()));
+
+					if (tmpItem.isCanHighlight()) {
+						HighlightTargetId[] ids = tmpItem
+								.getHighlightTargetIds();
+						for (int j = 0; j < ids.length; j++) {
+							validIdList.add(ids[j]);
+						}
+					}
+				}
+			}
+		}
+
+		// TODO
+		if (srcViewerForPT != null) {
+			HighlightTargetSourceInfo[] srcInfo = new HighlightTargetSourceInfo[srcLineList
+					.size()];
+			srcLineList.toArray(srcInfo);
+			srcViewerForPT.highlightSrcViewer(srcInfo, prb.getCheckResult()
+					.getSourceFile());
+		}
+
+		HighlightTargetId[] targets = new HighlightTargetId[validIdList.size()];
+		validIdList.toArray(targets);
+
+		prb.highlight(validIdList);
+
+		if (targets.length == 1) {
+			// Scroll Browser
+			if (null != modelService) {
+				modelService.jumpToNode(targetNode);
+			}
+
+		}
+	}
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/ui/internal/messages.properties b/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/ui/internal/messages.properties
new file mode 100644
index 0000000..861dc8c
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/ui/internal/messages.properties
@@ -0,0 +1,26 @@
+###############################################################################
+# Copyright (c) 2006, 2008 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#     IBM Corporation - initial API and implementation
+###############################################################################
+#
+# BlindView
+#
+BlindView.Maximum_Time = Maximum Time: {0} seconds
+BlindView.Done = Done (blind visualization).
+BlindView.Now_preparing = Now preparing
+BlindView.Now_processing = Now processing (blind visualization)...
+BlindView.Now_rendering = Now rendering
+BlindView.saving_file = saving file ...
+BlindView.end_saving_file = end saving file
+#
+# Actions
+#
+BlindView.Visualize_4 = Visualize blind usability
+BlindVisualizationAction.0 = Visualize
+
diff --git a/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/ui/internal/messages_ja.properties b/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/ui/internal/messages_ja.properties
new file mode 100644
index 0000000..80cc9f0
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/ui/internal/messages_ja.properties
@@ -0,0 +1,25 @@
+###############################################################################
+# Copyright (c) 2006, 2008 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#     IBM Corporation - initial API and implementation
+###############################################################################
+#
+# BlindView
+#
+BlindView.Maximum_Time = \u6700\u5927\u5230\u9054\u6642\u9593\uff1a\u3000{0}\u79d2
+BlindView.Done = \u7d42\u4e86\u3000(\u97f3\u58f0\u8996\u899a\u5316)
+BlindView.Now_preparing = \u6e96\u5099\u4e2d\u2026
+BlindView.Now_processing = \u51e6\u7406\u4e2d\u3000(\u97f3\u58f0\u8996\u899a\u5316)
+BlindView.Now_rendering = \u30ec\u30f3\u30c0\u30ea\u30f3\u30b0\u4e2d
+BlindView.saving_file = \u4fdd\u5b58\u4e2d\u2026
+BlindView.end_saving_file = \u4fdd\u5b58\u7d42\u4e86
+#
+# Actions
+#
+BlindView.Visualize_4 = \u97f3\u58f0\u30e6\u30fc\u30b6\u30d3\u30ea\u30c6\u30a3\u8996\u899a\u5316\u5b9f\u884c
+BlindVisualizationAction.0 = \u8996\u899a\u5316\u5b9f\u884c
diff --git a/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/ui/views/BlindView.java b/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/ui/views/BlindView.java
new file mode 100644
index 0000000..17aeb57
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.blind/src/org/eclipse/actf/visualization/blind/ui/views/BlindView.java
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Norimasa HAYASHIDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.blind.ui.views;
+
+import org.eclipse.actf.util.ui.AbstractPartListener;
+import org.eclipse.actf.visualization.IVisualizationView;
+import org.eclipse.actf.visualization.VisualizationStatusLineContributionItem;
+import org.eclipse.actf.visualization.blind.ui.internal.PartControlBlind;
+import org.eclipse.actf.visualization.blind.ui.internal.SelectionListenerBlind;
+import org.eclipse.actf.visualization.engines.blind.html.ui.elementViewer.ElementViewerManager;
+import org.eclipse.actf.visualization.ui.report.table.ResultTableLabelProvider;
+import org.eclipse.actf.visualization.ui.report.table.ResultTableSorter;
+import org.eclipse.actf.visualization.ui.report.views.DetailedReportView;
+import org.eclipse.jface.action.IContributionItem;
+import org.eclipse.jface.viewers.IBaseLabelProvider;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.IViewSite;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchPartReference;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.part.ViewPart;
+
+
+public class BlindView extends ViewPart implements IVisualizationView {
+
+	public static final String ID = BlindView.class.getName();
+
+	private IBaseLabelProvider baseLabelProvider;
+
+	private ResultTableSorter viewerSorter;
+
+	private ElementViewerManager elementViewerManager;
+
+	private PartControlBlind partRightBlind;
+
+	public BlindView() {
+		super();
+		baseLabelProvider = new ResultTableLabelProvider();
+		viewerSorter = new ResultTableSorter();
+		elementViewerManager = ElementViewerManager.getInstance();
+	}
+
+	public void init(IViewSite site) throws PartInitException {
+		setSite(site);
+		setStatusLine();
+	}
+
+	public void createPartControl(Composite parent) {
+		partRightBlind = new PartControlBlind(this, parent);
+
+		// TODO use mediator
+		getSite().getPage().addSelectionListener(DetailedReportView.ID,
+				new SelectionListenerBlind(partRightBlind));
+
+		// for element viewer
+		elementViewerManager.setPartRightBlind(partRightBlind);
+		addPartListener();
+
+	}
+
+	public void setFocus() {
+	}
+
+	public void setStatusMessage(String statusMessage) {
+		IContributionItem[] items = getViewSite().getActionBars()
+				.getStatusLineManager().getItems();
+		for (int i = 0; i < items.length; i++) {
+			if (null != items[i]
+					&& items[i].getId().equals(
+							VisualizationStatusLineContributionItem.ID + ID)) {
+				((VisualizationStatusLineContributionItem) items[i])
+						.setStatusMessage(statusMessage);
+			}
+		}
+	}
+
+	public void setInfoMessage(String infoMessage) {
+		IContributionItem[] items = getViewSite().getActionBars()
+				.getStatusLineManager().getItems();
+		for (int i = 0; i < items.length; i++) {
+			if (null != items[i]
+					&& items[i].getId().equals(
+							VisualizationStatusLineContributionItem.ID + ID)) {
+				((VisualizationStatusLineContributionItem) items[i])
+						.setInfoMessage(infoMessage);
+			}
+		}
+	}
+
+	private void addPartListener() {
+		IWorkbenchPage activePage = PlatformUI.getWorkbench()
+				.getActiveWorkbenchWindow().getActivePage();
+		activePage.addPartListener(new AbstractPartListener() {
+			public void partActivated(IWorkbenchPartReference partRef) {
+				IWorkbenchPart part = partRef.getPart(false);
+				if (part instanceof IVisualizationView) {
+					if (part.equals(BlindView.this)) {
+						elementViewerManager.activateElementViewer();
+					} else {
+						elementViewerManager.hideElementViewer();
+					}
+				}
+			}
+		});
+	}
+
+	private void setStatusLine() {
+		getViewSite().getActionBars().getStatusLineManager().add(
+				new VisualizationStatusLineContributionItem(ID));
+	}
+
+	public IBaseLabelProvider getLabelProvider() {
+		return baseLabelProvider;
+	}
+
+	public ViewerSorter getTableSorter() {
+		viewerSorter.reset();
+		return viewerSorter;
+	}
+
+	public int getResultTableMode() {
+		return MODE_DEFAULT;
+	}
+
+	public void doVisualize() {
+		if (partRightBlind != null) {
+			partRightBlind.doVisualize();
+		}
+	}
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/.classpath b/plugins/org.eclipse.actf.visualization.engines.blind.html/.classpath
new file mode 100644
index 0000000..751c8f2
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/.cvsignore b/plugins/org.eclipse.actf.visualization.engines.blind.html/.cvsignore
new file mode 100644
index 0000000..ba077a4
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/.cvsignore
@@ -0,0 +1 @@
+bin
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/.project b/plugins/org.eclipse.actf.visualization.engines.blind.html/.project
new file mode 100644
index 0000000..3f83467
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.actf.visualization.engines.blind.html</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/META-INF/MANIFEST.MF b/plugins/org.eclipse.actf.visualization.engines.blind.html/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..ef70154
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/META-INF/MANIFEST.MF
@@ -0,0 +1,22 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Eclipse ACTF HTML Blind Visualization Engine Plug-in (Incubation)
+Bundle-SymbolicName: org.eclipse.actf.visualization.engines.blind.html;singleton:=true
+Bundle-Version: 0.0.1
+Bundle-Activator: org.eclipse.actf.visualization.engines.blind.html.HtmlVizPlugin
+Bundle-Vendor: Eclipse.org
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.core.runtime,
+ org.eclipse.ui,
+ org.eclipse.actf.common,
+ org.eclipse.actf.visualization.eval,
+ org.eclipse.actf.visualization.engines.blind,
+ org.eclipse.actf.visualization.engines.voicebrowser,
+ org.eclipse.actf.model.dom.html,
+ org.eclipse.actf.visualization.ui.report
+Eclipse-LazyStart: true
+Export-Package: org.eclipse.actf.visualization.engines.blind.html,
+ org.eclipse.actf.visualization.engines.blind.html.eval,
+ org.eclipse.actf.visualization.engines.blind.html.ui.actions,
+ org.eclipse.actf.visualization.engines.blind.html.ui.elementViewer,
+ org.eclipse.actf.visualization.engines.blind.html.util
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/about.html b/plugins/org.eclipse.actf.visualization.engines.blind.html/about.html
new file mode 100644
index 0000000..481dbcf
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/about.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>June 5, 2006</p>	
+<h3>License</h3>
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;).  
+Unless otherwise indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;).  A copy of the EPL is available 
+at <a href="http://www.eclipse.org/org/documents/epl-v10.php">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is 
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content.  Check the Redistributor&rsquo;s license 
+that was provided with the Content.  If no such license exists, contact the Redistributor.  Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/build.properties b/plugins/org.eclipse.actf.visualization.engines.blind.html/build.properties
new file mode 100644
index 0000000..a50fa6c
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/build.properties
@@ -0,0 +1,16 @@
+###############################################################################
+# Copyright (c) 2007, 2008 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#     IBM Corporation - initial API and implementation
+###############################################################################
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               about.html,\
+               plugin.xml
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/plugin.xml b/plugins/org.eclipse.actf.visualization.engines.blind.html/plugin.xml
new file mode 100644
index 0000000..d06388a
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/plugin.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.2"?>
+<plugin>
+   <extension-point id="elementInfoProvider" name="ElementInfoProvider" schema="schema/elementInfoProvider.exsd"/>   
+</plugin>
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/schema/elementInfoProvider.exsd b/plugins/org.eclipse.actf.visualization.engines.blind.html/schema/elementInfoProvider.exsd
new file mode 100644
index 0000000..98aaee1
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/schema/elementInfoProvider.exsd
@@ -0,0 +1,116 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.actf.visualization.engines.blind.html">
+<annotation>
+      <appInfo>
+         <meta.schema plugin="org.eclipse.actf.visualization.engines.blind.html" id="elementInfoProvider" name="ElementInfoProvider"/>
+      </appInfo>
+      <documentation>
+         [Enter description of this extension point.]
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <complexType>
+         <sequence>
+            <element ref="provider" minOccurs="1" maxOccurs="unbounded"/>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appInfo>
+                  <meta.attribute translatable="true"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="provider">
+      <complexType>
+         <attribute name="id" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="class" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appInfo>
+                  <meta.attribute kind="java" basedOn="org.eclipse.actf.util.ui.IElementViewerInfoProvider"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="since"/>
+      </appInfo>
+      <documentation>
+         [Enter the first release in which this extension point appears.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="examples"/>
+      </appInfo>
+      <documentation>
+         [Enter extension point usage example here.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="apiInfo"/>
+      </appInfo>
+      <documentation>
+         [Enter API information here.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="implementation"/>
+      </appInfo>
+      <documentation>
+         [Enter information about supplied implementation of this extension point.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="copyright"/>
+      </appInfo>
+      <documentation>
+         Copyright (c) 2007, 2008 IBM Corporation and others.&lt;br&gt;
+All rights reserved. This program and the accompanying materials are made
+available under the terms of the Eclipse Public License v1.0 which accompanies
+this distribution, and is available at &lt;a 
+href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
+      </documentation>
+   </annotation>
+
+</schema>
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/HtmlVizPlugin.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/HtmlVizPlugin.java
new file mode 100644
index 0000000..351a80c
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/HtmlVizPlugin.java
@@ -0,0 +1,50 @@
+package org.eclipse.actf.visualization.engines.blind.html;
+
+import org.eclipse.core.runtime.Plugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class HtmlVizPlugin extends Plugin {
+
+	// The plug-in ID
+	public static final String PLUGIN_ID = "org.eclipse.actf.visualization.engines.blind.html";
+
+	// The shared instance
+	private static HtmlVizPlugin plugin;
+	
+	/**
+	 * The constructor
+	 */
+	public HtmlVizPlugin() {
+		plugin = this;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.core.runtime.Plugins#start(org.osgi.framework.BundleContext)
+	 */
+	public void start(BundleContext context) throws Exception {
+		super.start(context);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.core.runtime.Plugin#stop(org.osgi.framework.BundleContext)
+	 */
+	public void stop(BundleContext context) throws Exception {
+		plugin = null;
+		super.stop(context);
+	}
+
+	/**
+	 * Returns the shared instance
+	 *
+	 * @return the shared instance
+	 */
+	public static HtmlVizPlugin getDefault() {
+		return plugin;
+	}
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/IVisualizeMapData.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/IVisualizeMapData.java
new file mode 100644
index 0000000..5cb0938
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/IVisualizeMapData.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.blind.html;
+
+import java.util.Map;
+
+import org.eclipse.actf.visualization.engines.blind.html.internal.util.VisualizationNodeInfo;
+import org.w3c.dom.Node;
+
+public interface IVisualizeMapData {
+
+	/**
+	 * @return Returns the orig2idMap.
+	 */
+	public abstract Map getOrig2idMap();
+
+	public abstract void addReplacedNodeMapping(Node result, Node replacement);
+
+	public abstract Node getOrigNode(Node result);
+
+	public abstract Node getResultNode(Node orig);
+
+	public abstract Node getReplacement(Node result);
+
+	public abstract Integer getIdOfNode(Node result);
+
+	public abstract Integer getIdOfOrigNode(Node orig);
+
+	public abstract VisualizationNodeInfo getNodeInfo(Node result);
+
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/VisualizeEngine.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/VisualizeEngine.java
new file mode 100644
index 0000000..42e2940
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/VisualizeEngine.java
@@ -0,0 +1,583 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Hironobu TAKAGI - initial API and implementation
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.blind.html;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Vector;
+
+import org.eclipse.actf.util.html2view.Html2ViewMapData;
+import org.eclipse.actf.visualization.engines.blind.html.eval.BlindProblem;
+import org.eclipse.actf.visualization.engines.blind.html.eval.ImgChecker;
+import org.eclipse.actf.visualization.engines.blind.html.internal.util.DocumentCleaner;
+import org.eclipse.actf.visualization.engines.blind.html.internal.util.LinkAnalyzer;
+import org.eclipse.actf.visualization.engines.blind.html.internal.util.NodeInfoCreator;
+import org.eclipse.actf.visualization.engines.blind.html.internal.util.VisualizationNodeInfo;
+import org.eclipse.actf.visualization.engines.blind.html.internal.util.VisualizationResultCleaner;
+import org.eclipse.actf.visualization.engines.blind.html.internal.util.VisualizeColorUtil;
+import org.eclipse.actf.visualization.engines.blind.html.internal.util.VisualizeMapDataImpl;
+import org.eclipse.actf.visualization.engines.blind.html.internal.util.VisualizeMapUtil;
+import org.eclipse.actf.visualization.engines.blind.html.internal.util.VisualizeViewUtil;
+import org.eclipse.actf.visualization.engines.blind.html.ui.elementViewer.VisualizeStyleInfo;
+import org.eclipse.actf.visualization.engines.blind.html.ui.elementViewer.VisualizeStyleInfoManager;
+import org.eclipse.actf.visualization.engines.blind.html.util.Id2LineViaAccId;
+import org.eclipse.actf.visualization.engines.blind.util.ParamBlind;
+import org.eclipse.actf.visualization.engines.blind.util.TextChecker;
+import org.eclipse.actf.visualization.engines.voicebrowser.JWAT;
+import org.eclipse.actf.visualization.engines.voicebrowser.JWATController;
+import org.eclipse.actf.visualization.engines.voicebrowser.Packet;
+import org.eclipse.actf.visualization.engines.voicebrowser.PacketCollection;
+import org.eclipse.actf.visualization.eval.EvaluationPreferencesUtil;
+import org.eclipse.actf.visualization.eval.IEvaluationItem;
+import org.eclipse.actf.visualization.eval.guideline.GuidelineHolder;
+import org.eclipse.actf.visualization.eval.html.statistics.PageData;
+import org.eclipse.actf.visualization.eval.problem.IProblemItem;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class VisualizeEngine {
+
+	public static String ERROR_ICON_NAME = "exclawhite21.gif";
+
+	private static final String errorStyle = "color: #dd0000; background-color: #FFFFFF; border-width: medium; border-style: solid; border-color: #dd0000;";
+
+	private static final String CHECK_ITEM_PATTERN = "B_\\p{Digit}+";
+
+	private String baseUrl = ""; // default value
+
+	private String targetUrl = "";
+
+	private Document orig = null;
+
+	private Document result = null;
+
+	private List<IProblemItem> problems = null;
+
+	private Vector html2viewMapV = new Vector();
+
+	private VisualizeMapDataImpl mapData = null;
+
+	private VisualizeStyleInfo styleInfo;
+
+	private JWATController jwatc = null;
+
+	private boolean fIsActivating = false;
+
+	private PacketCollection allPc = null;
+
+	private boolean servletMode = false;
+
+	private int iMaxTime;
+
+	private int iMaxTimeLeaf;
+
+	private Set invisibleIdSet = new HashSet();
+
+	private TextChecker textChecker;
+
+	private PageData pageData;
+
+	private GuidelineHolder guidelineHolder = GuidelineHolder.getInstance();
+
+	private boolean[] checkItems = new boolean[BlindProblem.NUM_PROBLEMS];
+
+	private File variantFile;
+
+	// TODO IGuidelineSelectionChangedListner
+
+	/**
+	 * Constructor for VisualizeEngine.
+	 */
+	public VisualizeEngine() {
+		result = null;
+		jwatInit();
+
+		initCheckItems();
+
+		textChecker = TextChecker.getInstance();
+	}
+
+	private void initCheckItems() {
+		Arrays.fill(checkItems, false);
+
+		Set itemSet = guidelineHolder.getMatchedCheckitemSet();
+
+		for (Iterator i = itemSet.iterator(); i.hasNext();) {
+			IEvaluationItem cItem = (IEvaluationItem) i.next();
+			// System.out.println(cItem.getId());
+			String id = cItem.getId();
+			if (id.matches(CHECK_ITEM_PATTERN)) {
+				id = id.substring(2);
+				try {
+					int item = Integer.parseInt(id);
+					if (item > -1 && item < BlindProblem.NUM_PROBLEMS) {
+						checkItems[item] = true;
+					} else {
+						// TODO
+					}
+				} catch (Exception e) {
+				}
+
+			}
+		}
+	}
+
+	/**
+	 * Sets the document.
+	 * 
+	 * @param document
+	 *            The document to set
+	 */
+	public void setDocument(Document document) {
+		// TODO move to screen reader engine
+		DocumentCleaner.removeDisplayNone(document);
+
+		orig = document;
+		result = (Document) document.cloneNode(true);
+		jwatc.setDocument(result);
+		pageData = new PageData();
+		mapData = new VisualizeMapDataImpl();
+
+		VisualizeMapUtil.createNode2NodeMap(document, result, mapData);
+	}
+
+	private void cleanupPacketCollection(PacketCollection pc) {
+		// remove text in noscript tag
+		if (pc != null) {
+			int size = pc.size();
+			for (int i = size - 1; i >= 0; i--) {
+				Packet p = (Packet) pc.get(i);
+
+				Node tmpNode = p.getNode();
+				while (tmpNode != null) {
+					if (tmpNode.getNodeName().equals("noscript")) {
+						pc.remove(i);
+						break;
+					}
+					tmpNode = tmpNode.getParentNode();
+				}
+			}
+		}
+	}
+
+	public void calculate() {
+		if (result == null) {
+			return;
+		} else {
+			problems = new Vector<IProblemItem>();
+			allPc = jwatc.getPacketCollection();
+
+			cleanupPacketCollection(allPc);
+
+			ParamBlind curParamBlind = ParamBlind.getInstance();
+
+			// get packet and create map and list
+			NodeInfoCreator nodeInfoCreator = new NodeInfoCreator(mapData,
+					textChecker, problems, invisibleIdSet, curParamBlind);
+			nodeInfoCreator.prepareNodeInfo(allPc);
+			nodeInfoCreator.createAdditionalNodeInfo(result);
+
+			// link analysis preparation
+			LinkAnalyzer linkAnalyzer = new LinkAnalyzer(result, allPc,
+					mapData, problems, invisibleIdSet, curParamBlind, pageData);
+
+			styleInfo = new VisualizeStyleInfo(orig, mapData);
+
+			/*
+			 * rewrite DOM from here
+			 */
+			// insert ID attributes to elements
+			mapData.makeIdMapping(Html2ViewMapData.ACTF_ID);
+
+			styleInfo.setImportedCssSet(DocumentCleaner.removeCSS(result,
+					targetUrl));
+
+			// prepare head
+			if (result.getElementsByTagName("head").getLength() == 0) {
+				Element tmpHead = result.createElement("head");
+				Element tmpHtml = result.getDocumentElement();
+				if (tmpHtml != null) {
+					tmpHtml.insertBefore(tmpHead, tmpHtml.getFirstChild());
+				}
+			}
+
+			// calculate time and set color
+			VisualizeColorUtil colorUtil = new VisualizeColorUtil(result,
+					mapData, curParamBlind);
+			colorUtil.setColorAll();
+
+			calMaxTime();
+
+			problems.addAll(linkAnalyzer.skipLinkCheck(iMaxTime, iMaxTimeLeaf));
+
+			replaceImgAndCheck(result, mapData, curParamBlind.oReplaceImage);
+
+			int errorCount = 0;
+			int missing = 0;
+			int wrong = 0;
+			int area = 0;
+
+			// remove unnecessary problems
+			for (Iterator<IProblemItem> i = problems.iterator(); i.hasNext();) {
+				IProblemItem tmpBP = i.next();
+				if (tmpBP instanceof BlindProblem) {
+					BlindProblem curBP = (BlindProblem) tmpBP;
+					if (checkItems[curBP.getProblemSubType()]) {
+						if (curBP.getSeverity() == IEvaluationItem.SEV_ERROR) {
+							switch (curBP.getProblemSubType()) {
+							case BlindProblem.NO_ALT_IMG:
+							case BlindProblem.NO_ALT_INPUT:
+								missing++;
+								errorCount++;
+								break;
+							case BlindProblem.WRONG_ALT_IMG:
+							case BlindProblem.WRONG_ALT_INPUT:
+							case BlindProblem.SEPARATE_DBCS_ALT_IMG:
+							case BlindProblem.SEPARATE_DBCS_ALT_INPUT:
+								wrong++;
+								errorCount++;
+							case BlindProblem.NO_ALT_AREA: // TODO
+							case BlindProblem.WRONG_ALT_AREA:
+							case BlindProblem.SEPARATE_DBCS_ALT_AREA:
+								area++;
+							}
+						}
+					} else {
+						// unselected guideline items
+						i.remove();
+					}
+				}
+			}
+			pageData.setImageAltErrorNum(errorCount);
+			pageData.setWrongAltNum(wrong);
+			pageData.setMissingAltNum(missing);
+
+			VisualizeViewUtil
+					.visualizeError(result, problems, mapData, baseUrl);
+
+			DocumentCleaner.removeJavaScript(mapData.getNodeInfoList(), result);
+			DocumentCleaner.removeMeta(result);
+			DocumentCleaner.removeObject(result);
+			DocumentCleaner.removeEmbed(result);
+			DocumentCleaner.removeApplet(result);
+			DocumentCleaner.removeBase(result);
+
+			VisualizationResultCleaner.clean(result, targetUrl);
+
+			// System.out.println("remove elements fin");
+
+			// TODO merge with visualizeError
+			Id2LineViaAccId id2line = null;
+			if (EvaluationPreferencesUtil.isOriginalDOM()) {
+				id2line = new Id2LineViaAccId(mapData.getId2AccIdMap(),
+						html2viewMapV);
+			}
+
+			for (Iterator i = problems.iterator(); i.hasNext();) {
+				BlindProblem tmpBP = (BlindProblem) i.next();
+				tmpBP.prepareHighlight();
+				if (id2line != null) {
+					tmpBP.setLineNumber(id2line);
+				}
+			}
+			// merge
+
+			VisualizeStyleInfoManager.getInstance()
+					.fireVisualizeStyleInfoUpdate(styleInfo);
+
+			if (curParamBlind.visualizeMode == ParamBlind.BLIND_BROWSER_MODE) {
+				VisualizeViewUtil.returnTextView(result, allPc, baseUrl);
+				return;
+			} else {
+				variantFile = VisualizeViewUtil.prepareActions(result, mapData,
+						baseUrl, servletMode);
+				return;
+			}
+		}
+	}
+
+	private void replaceImgAndCheck(Document doc, IVisualizeMapData mapData,
+			boolean remove) {
+
+		NodeList mapList = doc.getElementsByTagName("map");
+		Map<String, Element> mapMap = new HashMap<String, Element>();
+		int mapListsize = mapList.getLength();
+		for (int i = 0; i < mapListsize; i++) {
+			Element mapEl = (Element) mapList.item(i);
+			mapMap.put(mapEl.getAttribute("name"), mapEl);
+		}
+
+		NodeList nl = doc.getElementsByTagName("img");
+		int size = nl.getLength();
+		Vector<IProblemItem> problemV = new Vector<IProblemItem>();
+
+		ImgChecker imgChecker = new ImgChecker(mapData, mapMap, textChecker,
+				problemV, baseUrl, checkItems);
+
+		pageData.setTotalImageNumber(size);
+		for (int i = size - 1; i >= 0; i--) {
+
+			Element img = (Element) nl.item(i);
+			// replaceImgAndCheckForOneImg(img, mapMap, doc, remove, problemV);
+			imgChecker.checkAndReplaceImg(img, doc, remove);
+		}
+
+		size = problemV.size();
+
+		for (int i = size - 1; i >= 0; i--) {
+			IProblemItem tmpProblem = (IProblemItem) problemV.get(i);
+			problems.add(tmpProblem);
+		}
+
+		// TODO 0 char is Error?
+		// iframe
+		nl = doc.getElementsByTagName("iframe");
+		size = nl.getLength();
+		for (int i = size - 1; i >= 0; i--) {
+			Element iframe = (Element) nl.item(i);
+			Element div = doc.createElement("div");
+			// debug
+			div.setAttribute("comment", iframe.getAttribute("comment"));
+			div.setAttribute("id", iframe.getAttribute("id"));
+			String title = null;
+			boolean error = false;
+			//
+			NamedNodeMap map = iframe.getAttributes();
+			int mapSize = map.getLength();
+			Node titleNode = null;
+			for (int j = 0; j < mapSize; j++) {
+				Node node = map.item(j);
+				if (node.getNodeName().equals("title")) {
+					titleNode = node;
+					break;
+				}
+			}
+			if (titleNode != null) {
+				title = titleNode.getNodeValue();
+			} else {
+				error = true;
+				title = "untitled";
+			}
+
+			title.trim();
+			if (remove) {
+				if (title.length() > 0) {
+					div.appendChild(doc.createTextNode("[Internal frame:"
+							+ title + "]"));
+				}
+				div.setAttribute("width", iframe.getAttribute("width"));
+				div.setAttribute("height", iframe.getAttribute("height"));
+				if (error) {
+					div.setAttribute("style", errorStyle);
+				} else {
+					div.setAttribute("style", iframe.getAttribute("style"));
+				}
+				Node parent = iframe.getParentNode();
+				parent.insertBefore(div, iframe);
+				mapData.addReplacedNodeMapping(iframe, div);
+				parent.removeChild(iframe);
+			}
+		}
+
+		// image button
+		nl = doc.getElementsByTagName("input");
+		size = nl.getLength();
+		Vector<IProblemItem> tmpV = new Vector<IProblemItem>();
+		for (int i = size - 1; i >= 0; i--) {
+			Element input = (Element) nl.item(i);
+			String typeS = input.getAttribute("type").toLowerCase();
+			if (typeS.equalsIgnoreCase("image")) {
+
+				input.setAttribute("type", "button");
+				//				
+				NamedNodeMap map = input.getAttributes();
+				int mapSize = map.getLength();
+				Node altNode = null;
+				for (int j = 0; j < mapSize; j++) {
+					Node node = map.item(j);
+					if (node.getNodeName().equals("alt")) {
+						altNode = node;
+						break;
+					}
+				}
+				if (altNode != null) {
+					input.setAttribute("value", altNode.getNodeValue());
+				} else {
+					BlindProblem prob = new BlindProblem(
+							BlindProblem.NO_ALT_INPUT);
+					Integer idObj = mapData.getIdOfNode(input);
+					if (idObj != null) {
+						prob.setNode(input, idObj.intValue());
+					} else {
+						prob.setNode(input);
+					}
+					prob.setTargetNode(mapData.getOrigNode(input));
+					// (Node) result2documentMap.get(input));
+
+					tmpV.add(prob);
+					input.setAttribute("value", input.getAttribute("src"));
+					input.setAttribute("style", errorStyle);
+				}
+			} else if (typeS.matches("submit|reset|button")) {
+				// System.out.println(input);
+				BlindProblem prob = null;
+				String valueS = input.getAttribute("value");
+				if (valueS.length() == 0) {
+					if (typeS.equals("button")) {
+						// not readable
+						prob = new BlindProblem(
+								BlindProblem.NO_VALUE_INPUT_BUTTON);
+					}
+				} else if (textChecker.isSeparatedJapaneseChars(valueS)) {
+					prob = new BlindProblem(
+							BlindProblem.SEPARATE_DBCS_INPUT_VALUE, valueS);
+				}
+				if (prob != null) {
+					Integer idObj = mapData.getIdOfNode(input);
+					if (idObj != null) {
+						prob.setNode(input, idObj.intValue());
+					} else {
+						prob.setNode(input);
+					}
+					prob.setTargetNode(mapData.getOrigNode(input));
+					tmpV.add(prob);
+				}
+			}
+		}
+
+		for (int i = tmpV.size() - 1; i > -1; i--) {
+			problems.add(tmpV.get(i));
+		}
+
+	}
+
+	private void jwatInit() {
+		if (fIsActivating) {
+			return;
+		}
+		fIsActivating = true;
+		if (jwatc == null) {
+			try {
+				jwatc = JWAT.createJWATController();
+			} catch (Exception e) {
+				e.printStackTrace();
+			}
+		}
+	}
+
+	public Document getResult() {
+		return result;
+	}
+
+	public List<IProblemItem> getProbelems() {
+		return problems;
+	}
+
+	/**
+	 * @param string
+	 */
+	public void setBaseUrl(String string) {
+		baseUrl = string;
+	}
+
+	/**
+	 * @param string
+	 */
+	public void setTargetUrl(String string) {
+		targetUrl = string;
+	}
+
+	/**
+	 * @param b
+	 */
+	public void setServletMode(boolean b) {
+		servletMode = b;
+	}
+
+	// Added on 2003/10/20
+	private void calMaxTime() {
+		iMaxTime = 0;
+		iMaxTimeLeaf = 0;
+
+		int orgMaxTime = 0;
+
+		List elementList = mapData.getNodeInfoList();
+		int size = elementList.size();
+		for (int i = 0; i < size; i++) {
+
+			VisualizationNodeInfo curInfo = (VisualizationNodeInfo) elementList
+					.get(i);
+
+			int time = curInfo.getTime();
+			if (time > iMaxTime)
+				iMaxTime = time;
+
+			// TODO other sequencial elements (like list)
+			if (curInfo.isBlockElement() && !curInfo.isSequence()
+					&& time > iMaxTimeLeaf) {
+				iMaxTimeLeaf = time;
+			}
+
+			if (orgMaxTime < curInfo.getOrgTime()) {
+				orgMaxTime = curInfo.getOrgTime();
+			}
+
+		}
+		pageData.setMaxTime(iMaxTime);
+		pageData.setOrgMaxTime(orgMaxTime);
+	}
+
+	// Added on 2003/10/20
+	public int getMaxTime() {
+		return iMaxTime;
+	}
+
+	public VisualizeStyleInfo getStyleInfo() {
+		return styleInfo;
+	}
+
+	/**
+	 * @param invisibleIdSet
+	 *            The invisibleIdSet to set.
+	 */
+	public void setInvisibleIdSet(Set invisibleIdSet) {
+		this.invisibleIdSet = invisibleIdSet;
+	}
+
+	/**
+	 * @return Returns the mapData.
+	 */
+	public IVisualizeMapData getVisualizeMapData() {
+		return mapData;
+	}
+
+	public void setHtml2viewMapV(Vector html2viewMapV) {
+		this.html2viewMapV = html2viewMapV;
+	}
+
+	public void setPageData(PageData pageData) {
+		this.pageData = pageData;
+	}
+
+	public File getVariantFile() {
+		return variantFile;
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/eval/BlindProblem.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/eval/BlindProblem.java
new file mode 100644
index 0000000..4a4b893
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/eval/BlindProblem.java
@@ -0,0 +1,341 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Hironobu TAKAGI - initial API and implementation
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.html.eval;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.actf.util.html2view.Html2ViewMapData;
+import org.eclipse.actf.visualization.engines.blind.html.util.Id2LineViaAccId;
+import org.eclipse.actf.visualization.eval.problem.HighlightTargetId;
+import org.eclipse.actf.visualization.eval.problem.HighlightTargetSourceInfo;
+import org.eclipse.actf.visualization.eval.problem.IProblemItem;
+import org.eclipse.actf.visualization.eval.problem.ProblemItemImpl;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+
+
+public class BlindProblem extends ProblemItemImpl implements IProblemItem {
+
+    public static final int NO_ALT_IMG = 0;
+
+    public static final int NO_ALT_INPUT = 1;
+
+    public static final int NO_ALT_AREA = 2;
+
+    public static final int WRONG_ALT_IMG = 4;
+
+    public static final int WRONG_ALT_INPUT = 5;//TODO
+
+    public static final int WRONG_ALT_AREA = 6;
+
+    public static final int NO_DEST_LINK = 8;
+
+    public static final int REDUNDANT_ALT = 9;
+
+    public static final int NO_SKIPTOMAIN_LINK = 10;// without structure
+
+    public static final int TOO_LESS_STRUCTURE = 12;
+
+    public static final int NO_TEXT_INTRAPAGELINK = 14;
+
+    public static final int WRONG_TEXT = 15;
+
+    public static final int NO_ID_INPUT = 16;	//TODO
+
+    public static final int TOOFAR_SKIPTOMAIN_LINK = 17;
+
+    public static final int NO_DEST_SKIP_LINK = 18;
+
+    public static final int WRONG_SKIP_LINK_TEXT = 19;
+
+    public static final int NO_SKIPTOMAIN_WITH_STRUCTURE = 20;
+
+    public static final int ALERT_NO_SKIPTOMAIN_NO_STRUCTURE = 21;
+
+    public static final int LESS_STRUCTURE_WITH_SKIPLINK = 22;
+
+    public static final int LESS_STRUCTURE_WITH_HEADING = 23;
+
+    public static final int LESS_STRUCTURE_WITH_BOTH = 24;
+
+    public static final int NO_TEXT_WITH_TITLE_INTRAPAGELINK = 25;
+
+    public static final int WRONG_SKIP_LINK_TITLE = 26;
+
+    public static final int ALERT_WRONG_ALT = 27;
+
+    public static final int ALERT_REDUNDANT_TEXT = 28; // TODO
+
+    public static final int SEPARATE_DBCS_ALT_IMG = 29;
+    
+    public static final int SEPARATE_DBCS_ALT_INPUT =30; //TODO
+
+    public static final int SEPARATE_DBCS_ALT_AREA = 31;
+
+    public static final int ALERT_NO_DEST_INTRA_LINK = 33;
+
+    public static final int ALERT_SPELL_OUT = 34;
+
+    public static final int INVISIBLE_INTRAPAGE_LINK = 35;
+
+    public static final int NO_VALUE_INPUT_BUTTON = 36;
+
+    public static final int SEPARATE_DBCS_INPUT_VALUE = 37;
+
+    public static final int NUM_PROBLEMS = 38;// max id+1
+
+    // ////////////////////////////////////////////////////
+
+    private List<Node> nodeList = null;
+
+    private int nodeId = -1;
+
+    private boolean isMulti = false;
+
+    private ArrayList<HighlightTargetId> idsList = new ArrayList<HighlightTargetId>();
+
+    private int subType = -1; // TODO
+
+    /**
+     * Constructor for BlindProblem.
+     */
+    public BlindProblem(int _subtype) {
+        this(_subtype, "");
+    }
+
+    /**
+     * Constructor for BlindProblem.
+     */
+    public BlindProblem(int _subtype, String targetString) {
+        super("B_" + Integer.toString(_subtype));
+
+        subType = _subtype;
+
+        nodeList = new Vector<Node>();
+        setTargetString(targetString);
+
+        // for HPB? use ReportUtil?
+        switch (_subtype) {
+        case WRONG_ALT_IMG:
+        case WRONG_ALT_INPUT:
+        case WRONG_ALT_AREA:
+        case WRONG_TEXT:
+        case ALERT_WRONG_ALT:
+        case SEPARATE_DBCS_ALT_IMG:
+        case SEPARATE_DBCS_ALT_INPUT:
+        case SEPARATE_DBCS_ALT_AREA:
+        // case WRONG_SKIP_LINK_TEXT:
+        // case WRONG_SKIP_LINK_TITLE:
+        // case WRONG_TITLE_IFRAME:
+        case SEPARATE_DBCS_INPUT_VALUE:
+        case REDUNDANT_ALT:
+        case NO_DEST_LINK:
+        case NO_DEST_SKIP_LINK:
+        case ALERT_NO_DEST_INTRA_LINK:
+        case ALERT_SPELL_OUT:
+            this.targetStringForHPB = targetString;
+            break;
+        default:
+        }
+    }
+
+    /**
+     * Returns the node.
+     * 
+     * @return Node
+     */
+    public Node getTargetNodeInResultDoc() {
+        if (nodeList.size() > 0) {
+            return (Node) nodeList.get(0);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Sets the node.
+     * 
+     * @param node
+     *            The node to set
+     */
+    public void setNode(Node node) {
+        nodeList.add(0, node);
+    }
+
+    /**
+     * Adds the node.
+     * 
+     * @param node
+     *            The node to set
+     */
+    public void addNode(Node node) {
+        nodeList.add(node);
+    }
+
+    /**
+     * Sets the node.
+     * 
+     * @param node
+     *            The node to set
+     */
+    public void setNode(Node node, int id) {
+        nodeList.add(0, node);
+        this.nodeId = id;
+    }
+
+    /**
+     * @see java.lang.Object#toString()
+     */
+    public String toString() {
+        return "node=" + nodeId + ":" + getDescription();
+    }
+
+    /**
+     * Returns the nodeList.
+     * 
+     * @return List
+     */
+    public List getNodeList() {
+        return nodeList;
+    }
+
+    /**
+     * Sets the nodeId.
+     * 
+     * @param nodeId
+     *            The nodeId to set
+     */
+    public boolean setNodeId(int nodeId) {
+        if (this.nodeId == -1) {
+            this.nodeId = nodeId;
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    public void addNodeIds(HighlightTargetId target) {
+        isMulti = true;
+        idsList.add(target);
+    }
+
+    public void prepareHighlight() {
+
+        if (isMulti) {
+            HighlightTargetId[] targets = new HighlightTargetId[idsList.size()];
+            idsList.toArray(targets);
+            setHighlightTargetIds(targets);
+        } else {
+            // setHighlightTargetIds(nodeId, nodeId);
+            if (nodeId > -1) {
+                setHighlightTargetIds(new HighlightTargetId(nodeId, nodeId));
+            }
+        }
+    }
+
+    private int getElementId(Element target) {
+        int result = -1;
+        String tmpId = target.getAttribute("id");
+        if (tmpId.length() > 0 && tmpId.startsWith("id")) {
+            tmpId = tmpId.substring(tmpId.indexOf("id") + 2);
+            try {
+                result = Integer.parseInt(tmpId);
+            } catch (Exception e) {
+            }
+        }
+        return result;
+    }
+
+    public void setLineNumber(Id2LineViaAccId id2line) {
+
+        switch (subType) {
+        case WRONG_TEXT:
+            try {
+                // text_node -> span_for_visualize -> real_parent
+                Node tmpN = getTargetNodeInResultDoc().getParentNode().getParentNode();
+                if (tmpN != null && tmpN.getNodeType() == Node.ELEMENT_NODE) {
+                    int id = getElementId((Element) tmpN);
+                    if (id > -1) {
+                        // setLine(id2line.getLine(id));
+                        Html2ViewMapData tmpData = id2line.getViewMapData(id);
+                        if (tmpData != null) {
+                            setHighlightTargetSourceInfo(new HighlightTargetSourceInfo(tmpData, tmpData));
+                        }
+                    }
+                }
+            } catch (Exception e1) {
+                // e1.printStackTrace();
+            }
+            break;
+        case NO_ALT_AREA:
+        case WRONG_ALT_AREA:
+        case SEPARATE_DBCS_ALT_AREA:
+            // int tmpNodeId = nodeId;
+            Node tmpN = getTargetNodeInResultDoc();
+            if (tmpN.getNodeType() == Node.ELEMENT_NODE) {
+                int id = getElementId((Element) tmpN);
+                if (id > -1) {
+                    Html2ViewMapData tmpData = id2line.getViewMapData(id);
+                    setHighlightTargetSourceInfo(new HighlightTargetSourceInfo(tmpData, tmpData));
+                    // setLine(id2line.getLine(id));
+                }
+            }
+            break;
+        default:
+            // TODO divide more by using case 
+            if (isMulti) {
+
+                ArrayList<HighlightTargetSourceInfo> tmpArray = new ArrayList<HighlightTargetSourceInfo>();
+
+                HighlightTargetId[] targets = new HighlightTargetId[idsList.size()];
+                idsList.toArray(targets);
+                for (int i = 0; i < targets.length; i++) {
+                    Html2ViewMapData startData = id2line.getViewMapData(targets[i].getStartId());
+                    Html2ViewMapData endData = id2line.getViewMapData(targets[i].getEndId());
+
+                    if (startData == null) {
+                        startData = endData;
+                    }
+                    if (endData == null) {
+                        endData = startData;
+                    }
+
+                    if (startData != null) {
+                        tmpArray.add(new HighlightTargetSourceInfo(startData, endData));
+                    }
+                }
+
+                HighlightTargetSourceInfo[] sourceInfo = new HighlightTargetSourceInfo[tmpArray.size()];
+                tmpArray.toArray(sourceInfo);
+                setHighlightTargetSourceInfo(sourceInfo);
+
+            } else {
+
+                Html2ViewMapData tmpData = id2line.getViewMapData(nodeId);
+                if (tmpData != null) {
+                    setHighlightTargetSourceInfo(new HighlightTargetSourceInfo(tmpData, tmpData));
+                }
+                // check
+                // setLine(id2line.getLine(nodeId));
+
+            }
+        }
+    }
+
+    public int getProblemSubType() {
+        return (subType);
+    }
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/eval/HtmlErrorLogListener.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/eval/HtmlErrorLogListener.java
new file mode 100644
index 0000000..9ae944f
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/eval/HtmlErrorLogListener.java
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.html.eval;
+
+import java.util.Vector;
+
+import org.eclipse.actf.model.dom.sgml.IErrorLogListener;
+import org.eclipse.actf.model.dom.sgml.ISGMLConstants;
+import org.eclipse.actf.util.html2view.Html2ViewMapData;
+import org.eclipse.actf.visualization.eval.EvaluationPreferencesUtil;
+import org.eclipse.actf.visualization.eval.problem.IProblemItem;
+import org.eclipse.actf.visualization.eval.problem.ProblemItemImpl;
+
+
+
+
+public class HtmlErrorLogListener implements IErrorLogListener {
+
+	//TODO move to eval plugin (eval.html) (& move IErrorLogListener to common/util)
+	
+	private boolean isNoDoctype = false;
+
+	private boolean isNonPublic = false;
+
+	private boolean isInvalidDoctype = false;
+
+	private Vector<IProblemItem> problemV = new Vector<IProblemItem>();
+
+	private String orgDoctype = "";
+	
+	private boolean flag = true;
+
+	public void errorLog(int arg0, String arg1) {
+		if (arg0 != ISGMLConstants.ILLEGAL_ATTRIBUTE || arg1.indexOf(Html2ViewMapData.ACTF_ID) < 0) {
+			// TODO create HTML problems
+			switch (arg0) {
+			case ISGMLConstants.DOCTYPE_MISSED:
+				isNoDoctype = true;
+				break;
+			case ISGMLConstants.ILLEGAL_DOCTYPE:
+				if (arg1.indexOf("Invalid DOCTYPE declaration.") > -1) {
+					isNonPublic = true;
+				} else if (arg1.matches(".*Instead of \".*\" use \".*\" as a DTD.")) {
+					orgDoctype = arg1.substring(arg1.indexOf("\"") + 1);
+					orgDoctype = orgDoctype.substring(0, orgDoctype.indexOf("\""));
+					if (orgDoctype.matches("-//W3C//DTD XHTML ((1.0 (Strict|Transitional|Frameset))|1.1|Basic 1.0)//EN")) {
+						orgDoctype = "";
+					} else {
+						isInvalidDoctype = true;
+					}
+				}
+				break;
+			case ISGMLConstants.ILLEGAL_CHILD:
+                //TBD "li" case (C_1000.7)
+                //System.out.println(arg0+" : "+arg1);
+				if (arg1.matches(".*<head.*> must be before <body.*")) {
+					addHtmlProblem("C_1000.1", arg1);
+				} else if (arg1.matches(".*<html.*> is not allowed as a child of <.*")) {
+					addHtmlProblem("C_1000.2", arg1);
+				} else if (arg1.matches(".*<body.*> is not allowed as a child of <.*")) {
+					addHtmlProblem("C_1000.3", arg1);
+				} else if (arg1.matches(".*Order of <html.*>'s children is wrong.*")) {
+					addHtmlProblem("C_1000.5", arg1);
+				}
+				break;
+			default:
+			}
+		}
+	}
+
+	private void addHtmlProblem(String id, String target) {
+		IProblemItem tmpCP = new ProblemItemImpl(id);
+		int line = -1;
+		String tmpS[] = target.split(":");
+		if (tmpS.length > 0) {
+			try {
+				line = Integer.parseInt(tmpS[0].trim());
+			} catch (Exception e) {
+			}
+		}
+		if (line > -1) {
+			tmpCP.setLine(line);
+		}
+		problemV.add(tmpCP);
+	}
+
+	public boolean isNoDoctypeDeclaration() {
+		return (isNoDoctype || isNonPublic || isInvalidDoctype);
+	}
+
+	public boolean isNonPublicDoctype() {
+		return (isNonPublic);
+	}
+
+	public boolean isInvalidDoctype() {
+		return (isInvalidDoctype);
+	}
+
+	public String getDeclaratedDoctype() {
+		return (orgDoctype);
+	}
+
+	public Vector<IProblemItem> getHtmlProblemVector() {
+		if(flag){
+			// (IE based LIVE DOM)->DOCTYPE was removed by IE
+			if (EvaluationPreferencesUtil.isOriginalDOM()
+					&& isNoDoctypeDeclaration()) {
+				if (isInvalidDoctype() || isNonPublicDoctype()) {
+					problemV.add(new ProblemItemImpl("C_1000.6"));
+				} else {
+					problemV.add(new ProblemItemImpl("C_1000.7"));
+				}
+			}			
+			flag = false;
+		}
+		return (problemV);
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/eval/ImgChecker.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/eval/ImgChecker.java
new file mode 100644
index 0000000..ae4f5c2
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/eval/ImgChecker.java
@@ -0,0 +1,259 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.html.eval;
+
+import java.util.Map;
+import java.util.Vector;
+
+import org.eclipse.actf.visualization.engines.blind.html.IVisualizeMapData;
+import org.eclipse.actf.visualization.engines.blind.html.VisualizeEngine;
+import org.eclipse.actf.visualization.engines.blind.html.internal.util.VisualizationNodeInfo;
+import org.eclipse.actf.visualization.engines.blind.util.TextChecker;
+import org.eclipse.actf.visualization.eval.problem.IProblemItem;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+public class ImgChecker {
+
+	// separated from visualizeEngine
+	// TODO refactoring
+	// TODO UseMap (object)
+
+	private IVisualizeMapData mapData;
+
+	// private Map node2infoMap;
+
+	// private Map idMap;
+
+	private Map mapMap;
+
+	private TextChecker textChecker;
+
+	private Vector<IProblemItem> problemV;
+
+	private String baseUrl;
+
+	private boolean[] checkItems;
+
+	/**
+	 * @param result2documentMap
+	 * @param node2infoMap
+	 * @param idMap
+	 * @param mapMap
+	 * @param removedNodeMap
+	 * @param textChecker
+	 * @param problemV
+	 * @param baseUrl
+	 * @param checkItems
+	 */
+	public ImgChecker(IVisualizeMapData mapData, Map mapMap,
+			TextChecker textChecker, Vector<IProblemItem> problemV,
+			String baseUrl, boolean[] checkItems) {
+
+		this.mapData = mapData;
+		this.mapMap = mapMap;
+		this.textChecker = textChecker;
+		this.problemV = problemV;
+		this.baseUrl = baseUrl;
+		this.checkItems = checkItems;
+	}
+
+	public boolean checkAndReplaceImg(Element img, Document doc, boolean remove) {
+
+		Element mapEl = null;
+		NodeList areaNL = null;
+		// NodeList aNL = null;
+
+		String mapName = img.getAttribute("usemap");
+		if (mapName.length() > 0) {
+
+			mapEl = (Element) mapMap.get(mapName.substring(1));
+			if (mapEl != null) {
+
+				areaNL = mapEl.getElementsByTagName("area");
+				// "a" -> CheckerEngine 57.2
+			}
+		}
+
+		String imgText = checkAlt(img);
+
+		if (remove) {
+			Node parent = img.getParentNode();
+
+			Element spanEl = doc.createElement("span");
+			spanEl.setAttribute("width", img.getAttribute("width"));
+			spanEl.setAttribute("height", img.getAttribute("height"));
+			spanEl.setAttribute("id", img.getAttribute("id"));
+			spanEl.setAttribute("style", img.getAttribute("style"));
+
+			boolean isVisible = true;
+			VisualizationNodeInfo info = mapData.getNodeInfo(img);
+			if (info != null) {
+				isVisible = !info.isInvisible();
+			}
+
+			if (imgText.length() > 0 && isVisible) {
+				spanEl.appendChild(doc.createTextNode(imgText));
+			}
+			parent.insertBefore(spanEl, img);
+
+			// image map
+			if (areaNL != null) {
+				int size = areaNL.getLength();
+				for (int i = 0; i < size; i++) {
+					Element areaEl = doc.createElement("span");
+					areaEl.setAttribute("style", img.getAttribute("style"));
+					spanEl.appendChild(areaEl);
+
+					Element areaE = (Element) areaNL.item(i);
+					BlindProblem prob = null;
+					Integer idObj = null;
+
+					if (!areaE.hasAttribute("alt")) {
+						if (areaE.hasAttribute("href")) {
+							prob = new BlindProblem(BlindProblem.NO_ALT_AREA,
+									mapEl.getAttribute("name") + " , href=\""
+											+ areaE.getAttribute("href") + "\"");
+							prob.setTargetNode(mapData.getOrigNode(areaE));
+						}
+					} else {
+						String alt = areaE.getAttribute("alt");
+						if (alt.length() > 0) {
+							if (textChecker.isInappropriateAlt(alt)) {
+								prob = new BlindProblem(
+										BlindProblem.WRONG_ALT_AREA, alt);
+
+							} else if (textChecker
+									.isSeparatedJapaneseChars(alt)) {
+								prob = new BlindProblem(
+										BlindProblem.SEPARATE_DBCS_ALT_AREA,
+										alt);
+
+							}
+
+						} else {
+							if (areaE.hasAttribute("href")) {
+								prob = new BlindProblem(
+										BlindProblem.WRONG_ALT_AREA, alt);
+							}
+						}
+						if (prob != null) {
+							prob.setTargetNode(mapData.getOrigNode(areaE));
+						}
+						areaEl.appendChild(doc
+								.createTextNode("[" + alt + ".] "));
+					}
+
+					if (prob != null) {
+						idObj = mapData.getIdOfNode(img);
+						if (idObj != null) {
+							prob.setNode(areaE, idObj.intValue());
+						} else {
+							prob.setNode(areaE);
+						}
+						problemV.add(prob);
+
+						idObj = mapData.getIdOfNode(areaE);
+
+						if (checkItems[prob.getProblemSubType()]) {
+							Element errorImg = doc.createElement("img");
+							errorImg.setAttribute("alt", "error icon");
+							errorImg.setAttribute("title", prob
+									.getDescription());
+							if (idObj != null) {
+								errorImg.setAttribute("onmouseover",
+										"updateBaloon('id" + idObj + "');");
+							}
+							errorImg.setAttribute("src", baseUrl + "img/"
+									+ VisualizeEngine.ERROR_ICON_NAME);
+							areaEl.appendChild(errorImg);
+						}
+					}
+				}
+			}
+
+			mapData.addReplacedNodeMapping(img, spanEl);
+			parent.removeChild(img);
+		}
+		// TODO
+		return true;
+	}
+
+	private String checkAlt(Element img) {
+
+		boolean noAltError = false;
+		String altS = "";
+
+		BlindProblem prob = null;
+
+		if (!img.hasAttribute("alt")) {
+			prob = new BlindProblem(BlindProblem.NO_ALT_IMG, img
+					.getAttribute("src"));
+			noAltError = true;
+		} else {
+			altS = img.getAttribute("alt");
+			if (altS.length() > 0) {
+				if (textChecker.isInappropriateAlt(altS)) {
+					prob = new BlindProblem(BlindProblem.WRONG_ALT_IMG, altS);
+				} else if (textChecker.isSeparatedJapaneseChars(altS)) {
+					prob = new BlindProblem(BlindProblem.SEPARATE_DBCS_ALT_IMG,
+							altS);
+				} else {
+					switch (textChecker.isInappropriateAlt2(altS)) {
+					case 3:
+						prob = new BlindProblem(BlindProblem.ALERT_SPELL_OUT,
+								altS);
+						break;
+					case 2:
+						prob = new BlindProblem(BlindProblem.WRONG_ALT_IMG,
+								altS);
+						break;
+					case 1:
+						prob = new BlindProblem(BlindProblem.ALERT_WRONG_ALT,
+								altS);
+						break;
+					case 0:
+					default:
+						break;
+					}
+				}
+			}
+		}
+		if (prob != null) {
+			prob.setTargetNode(mapData.getOrigNode(img));
+			Integer idObj = mapData.getIdOfNode(img);
+			if (idObj != null) {
+				prob.setNode(img, idObj.intValue());
+			} else {
+				prob.setNode(img);
+			}
+			problemV.add(prob);
+		}
+
+		String imgText = null;
+		VisualizationNodeInfo info = mapData.getNodeInfo(img);
+		if (info != null && info.getPacket() != null) {
+			imgText = info.getPacket().getText();
+		} else {
+			// alt="" or without alt
+			if (noAltError) {
+				imgText = "";
+			} else {
+				imgText = altS;
+			}
+		}
+		return (imgText);
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/Messages.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/Messages.java
new file mode 100644
index 0000000..2dc4566
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/Messages.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.html.internal;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+import org.eclipse.actf.visualization.engines.blind.html.HtmlVizPlugin;
+
+public class Messages {
+	private static final String BUNDLE_NAME = HtmlVizPlugin.PLUGIN_ID+".internal.messages"; //$NON-NLS-1$
+
+	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+			.getBundle(BUNDLE_NAME);
+
+	private Messages() {
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/messages.properties b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/messages.properties
new file mode 100644
index 0000000..f73aec6
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/messages.properties
@@ -0,0 +1,12 @@
+###############################################################################
+# Copyright (c) 2006, 2008 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#     IBM Corporation - initial API and implementation
+###############################################################################
+BlindView.Open_ID = Open ID/AccessKey/Class/CSS Inspector.
+
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/messages_ja.properties b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/messages_ja.properties
new file mode 100644
index 0000000..3fdb058
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/messages_ja.properties
@@ -0,0 +1,12 @@
+###############################################################################
+# Copyright (c) 2006, 2008 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#     IBM Corporation - initial API and implementation
+###############################################################################
+BlindView.Open_ID = ID/AccessKey/Class/CSS\u60c5\u5831\u3092\u958b\u304f
+
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/util/DocumentCleaner.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/util/DocumentCleaner.java
new file mode 100644
index 0000000..8a61305
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/util/DocumentCleaner.java
@@ -0,0 +1,353 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.html.internal.util;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.StringReader;
+import java.net.URL;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class DocumentCleaner {
+
+    // separated from VisualizeEngine
+
+    public static Set removeCSS(Document result, String baseUrl) {
+        HashSet<String> cssSet = new HashSet<String>();
+
+        URL baseURL = null;
+        try {
+            baseURL = new URL(baseUrl);
+        } catch (Exception e1) {
+            //e1.printStackTrace();
+            //System.out.println("DocCleaner: create base URL: " + baseUrl);
+        }
+
+        //Remove CSS
+        NodeList linkEl = result.getElementsByTagName("link");
+        if (linkEl != null) {
+            int xy = linkEl.getLength();
+            for (int i = xy - 1; i >= 0; i--) {
+                Element x = (Element) linkEl.item(i);
+                if ("text/css".equals(x.getAttribute("type"))) {
+                    String hrefS = getHref(x, baseURL);
+                    if (!hrefS.equals(""))
+                        cssSet.add(hrefS);
+                    x.getParentNode().removeChild(x);
+                }
+            }
+        }
+        NodeList styleEl = result.getElementsByTagName("style");
+        if (styleEl != null) {
+            int xy = styleEl.getLength();
+            for (int i = xy - 1; i >= 0; i--) {
+                Element x = (Element) styleEl.item(i);
+                if (x.getAttribute("type").equals("text/css")) {
+                    NodeList tmpNL = x.getChildNodes();
+                    for (int j = 0; j < tmpNL.getLength(); j++) {
+                        Node tmpN = tmpNL.item(j);
+                        getImportUrl(tmpN.toString(), baseURL, cssSet);
+                    }
+                }
+                x.getParentNode().removeChild(x);
+            }
+        }
+        NodeList bodyNl = result.getElementsByTagName("body");
+        for (int i = 0; i < bodyNl.getLength(); i++) {
+            Element bodyEl = (Element) bodyNl.item(i);
+            bodyEl.removeAttribute("style");
+        }
+        return (cssSet);
+    }
+
+    private static String createFullPath(URL baseURL, String spec) {
+        String result = spec;
+        if (baseURL != null) {
+            try {
+                URL targetUrl = new URL(baseURL, spec);
+                //System.out.println(targetUrl.toString());
+                result = targetUrl.toString();
+            } catch (Exception e) {
+                //e.printStackTrace();
+            }
+        }
+        return (result);
+    }
+
+    private static String getHref(Element target, URL baseURL) {
+        String result = "";
+        if (target.hasAttribute("href")) {
+            result = target.getAttribute("href");
+            result = createFullPath(baseURL, result);
+        }
+        return (result);
+    }
+
+    private static void getImportUrl(String target, URL baseURL, Set<String> cssSet) {
+        BufferedReader tmpBR = new BufferedReader(new StringReader(target));
+        String tmpS;
+        int index;
+        try {
+            while ((tmpS = tmpBR.readLine()) != null) {
+                if ((index = tmpS.indexOf("@import")) > -1) {
+                    tmpS = tmpS.substring(index + 7);
+                    //TODO
+                    if ((index = tmpS.indexOf("url(\"")) > -1) {
+                        tmpS = tmpS.substring(index + 5);
+                        if ((index = tmpS.indexOf("\");")) > -1) {
+                            tmpS = tmpS.substring(0, index);
+                            tmpS = createFullPath(baseURL, tmpS);
+                            cssSet.add(tmpS);
+                        }
+                    }
+                }
+            }
+        } catch (IOException e) {
+            //e.printStackTrace();
+        }
+    }
+
+    public static void removeBase(Document result) {
+        NodeList objectNl = result.getElementsByTagName("base");
+        int size = objectNl.getLength();
+        for (int i = size - 1; i >= 0; i--) {
+            Element objectEl = (Element) objectNl.item(i);
+            objectEl.getParentNode().removeChild(objectEl);
+        }
+    }
+
+    public static void removeApplet(Document result) {
+        NodeList appletNl = result.getElementsByTagName("applet");
+        int size = appletNl.getLength();
+        for (int i = size - 1; i >= 0; i--) {
+            Element appletEl = (Element) appletNl.item(i);
+            String id = appletEl.getAttribute("id");
+            Element divEl = result.createElement("div");
+            divEl.setAttribute("id", id);
+            //remove param
+            Node curChild = appletEl.getLastChild();
+            while (curChild != null) {
+                Node next = curChild.getPreviousSibling();
+                if (!curChild.getNodeName().equals("param")) {
+                    if (divEl.hasChildNodes()) {
+                        divEl.insertBefore(curChild, divEl.getFirstChild());
+                    } else {
+                        divEl.appendChild(curChild);
+                    }
+                }
+                curChild = next;
+            }
+            appletEl.getParentNode().insertBefore(divEl, appletEl);
+            appletEl.getParentNode().removeChild(appletEl);
+        }
+    }
+
+    public static void removeObject(Document result) {
+        NodeList objectNl = result.getElementsByTagName("object");
+        int size = objectNl.getLength();
+        for (int i = size - 1; i >= 0; i--) {
+            Element objectEl = (Element) objectNl.item(i);
+            String id = objectEl.getAttribute("id");
+            Element divEl = result.createElement("div");
+            divEl.setAttribute("id", id);
+            //remove param
+
+            Node curChild = objectEl.getLastChild();
+            while (curChild != null) {
+                Node next = curChild.getPreviousSibling();
+                if (!curChild.getNodeName().equals("param")) {
+                    if (divEl.hasChildNodes()) {
+                        divEl.insertBefore(curChild, divEl.getFirstChild());
+                    } else {
+                        divEl.appendChild(curChild);
+                    }
+                }
+                curChild = next;
+            }
+
+            objectEl.getParentNode().insertBefore(divEl, objectEl);
+            objectEl.getParentNode().removeChild(objectEl);
+        }
+    }
+
+    public static void removeEmbed(Document doc) { //remove onload and
+        // onmouseover
+        NodeList nl = doc.getElementsByTagName("embed");
+        int size = nl.getLength();
+        for (int i = size - 1; i >= 0; i--) {
+            Element el = (Element) nl.item(i);
+            String id = el.getAttribute("id");
+            Element newDiv = doc.createElement("div");
+            newDiv.setAttribute("id", id);
+
+            Node parent = el.getParentNode();
+
+            NodeList noembedL = el.getElementsByTagName("noembed");
+            Node childNoembed = null;
+            boolean hasNoembed = false;
+            for (int j = 0; j < noembedL.getLength(); j++) {
+                //System.out.println(j + "/" + noembedL.getLength() + " " + hasNoembed);
+                childNoembed = noembedL.item(j);
+                if (el == childNoembed.getParentNode()) {
+                    hasNoembed = true;
+                    break;
+                }
+            }
+
+            Node startNode;
+
+            if (hasNoembed) {
+                NodeList tmpNL = childNoembed.getChildNodes();
+                for (int k = tmpNL.getLength() - 1; k >= 0; k--) {
+                    newDiv.insertBefore(tmpNL.item(k), newDiv.getFirstChild());
+                }
+                startNode = childNoembed.getNextSibling();
+            } else {
+                newDiv.appendChild(doc.createTextNode("(Embeded element)"));
+                startNode = el.getFirstChild();
+            }
+
+            parent.insertBefore(newDiv, el);
+            while (startNode != null) {
+                Node next = startNode.getNextSibling();
+                parent.insertBefore(startNode, el);
+                startNode = next;
+            }
+            parent.removeChild(el);
+        }
+    }
+
+    public static void removeOnMouse(Element element) {
+        String str = element.getAttribute("onmouseover");
+        if ((str != null) && (str.length() > 0)) {
+            element.removeAttribute("onmouseover");
+        }
+        str = element.getAttribute("onmouseout");
+        if ((str != null) && (str.length() > 0)) {
+            element.removeAttribute("onmouseout");
+        }
+        str = element.getAttribute("onmousemove");
+        if ((str != null) && (str.length() > 0)) {
+            element.removeAttribute("onmousemove");
+        }
+        str = element.getAttribute("onclick");
+        if ((str != null) && (str.length() > 0)) {
+            element.removeAttribute("onclick");
+        }
+        str = element.getAttribute("onresize");
+        if ((str != null) && (str.length() > 0)) {
+            element.removeAttribute("onresize");
+        }
+
+    }
+
+    public static void removeOnLoad(Element element) {
+        String str = element.getAttribute("onload");
+        if ((str != null) && (str.length() > 0)) {
+            element.removeAttribute("onload");
+        }
+    }
+
+    public static void removeDisplayNone(Document doc) {
+        NodeList tmpNL = doc.getElementsByTagName("div");
+        for (int i = 0; i < tmpNL.getLength(); i++) {
+            Element tmpE = (Element) tmpNL.item(i);
+            //System.out.println(tmpE.getAttribute("style"));
+            if (tmpE.getAttribute("style").indexOf("DISPLAY: none") > -1) {
+                Node parent = tmpE.getParentNode();
+                if (parent != null) {
+                    //System.out.println("remove display: none");
+                    parent.removeChild(tmpE);
+                }
+            }
+        }
+    }
+
+    public static void removeBgcolor(Document doc) {
+        NodeList bodyNl = doc.getElementsByTagName("body");
+
+        if (bodyNl.getLength() > 0) {
+
+            Element bodyEl = (Element) bodyNl.item(0);
+            bodyEl.removeAttribute("bgcolor");
+        }
+    }
+
+    public static void removeMeta(Document doc) {
+        NodeList nl = doc.getElementsByTagName("meta");
+        int size = nl.getLength();
+        for (int i = 0; i < size; i++) {
+            Element el = (Element) nl.item(i); //item(i)?
+            String http_equiv = el.getAttribute("http-equiv");
+            if ((http_equiv != null) && (http_equiv.equalsIgnoreCase("refresh")||http_equiv.equalsIgnoreCase("Content-Type"))) {
+                el.removeAttribute("http-equiv");
+            }
+        }
+    }
+
+    public static void removeJavaScript(List nodeList, Document doc) {
+        /*
+         * remove onload and onmouseover
+         */
+        NodeList nl = doc.getElementsByTagName("script");
+        int size = nl.getLength();
+        for (int i = size - 1; i >= 0; i--) {
+            try {
+                Element el = (Element) nl.item(i);
+                //if (el.getParentNode().getNodeName().equals("head")) {
+                el.getParentNode().removeChild(el);
+            } catch (Exception e) {
+                //
+            }
+        }
+
+        nl = doc.getElementsByTagName("body");
+        size = nl.getLength();
+        for (int i = 0; i < size; i++) {
+            try {
+                ((Element) nl.item(i)).removeAttribute("onload");
+                //	Added on 2004/03/03
+                ((Element) nl.item(i)).removeAttribute("onunload");
+            } catch (Exception e) {
+                //
+            }
+        }
+        size = nodeList.size();
+        for (int i = 0; i < size; i++) {
+            Node node = ((VisualizationNodeInfo) nodeList.get(i)).getNode();
+            if (node.getNodeType() == Node.ELEMENT_NODE) {
+                try {
+                    Element el = (Element) node;
+                    String onload = el.getAttribute("onload");
+                    if (onload.length() > 0) {
+                        el.removeAttribute("onload");
+                    }
+                    String onmouseover = el.getAttribute("onmouseover");
+                    if (onmouseover.length() > 0) {
+                        el.removeAttribute("onmouseover");
+                    }
+                } catch (Exception e) {
+                    //
+                }
+            }
+
+        }
+    }
+    
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/util/LinkAnalyzer.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/util/LinkAnalyzer.java
new file mode 100644
index 0000000..25ddced
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/util/LinkAnalyzer.java
@@ -0,0 +1,525 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.html.internal.util;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Stack;
+import java.util.Vector;
+
+import org.eclipse.actf.visualization.engines.blind.html.eval.BlindProblem;
+import org.eclipse.actf.visualization.engines.blind.util.ParamBlind;
+import org.eclipse.actf.visualization.engines.voicebrowser.Packet;
+import org.eclipse.actf.visualization.engines.voicebrowser.PacketCollection;
+import org.eclipse.actf.visualization.eval.html.HtmlTagUtil;
+import org.eclipse.actf.visualization.eval.html.statistics.PageData;
+import org.eclipse.actf.visualization.eval.problem.HighlightTargetId;
+import org.eclipse.actf.visualization.eval.problem.IProblemItem;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+public class LinkAnalyzer {
+
+	private static final String SKIP_TO_MAIN_LINK_DEFINITION = ".*([sS]kip|[jJ]ump to|[lL]ink to) .+|.*(\u672c\u6587|\u30e1\u30a4\u30f3|\u3092\u8aad\u3080|(\u3078|\u306b)\u30b8\u30e3\u30f3\u30d7|(\u3078|\u306b)\u79fb\u52d5|\u3078\u306e\u30ea\u30f3\u30af).*";
+
+	// TODO
+	private static final String WRONG_SKIPLINK_DEFINITION = ".+ ([sS]kip to|[jJ]ump to) .+";
+
+	private static final int MAX_SKIPLINK_REACHING_TIME = 20;
+
+	private static final int MIN_MAX_TIME_TO_ELIMINATE_SKIP_LINK = 90;
+
+	private List<Element> intraPageLinkList = new ArrayList<Element>();
+
+	private Map<String, Element> anchorMap = new HashMap<String, Element>();
+
+	private Map<Element, String> skipLinkMap = new HashMap<Element, String>();
+
+	private Document doc;
+
+	private PacketCollection allPc;
+
+	private VisualizeMapDataImpl mapData;
+
+	private Set invisibleIdSet;
+
+	private List<IProblemItem> problems;
+
+	private int intralinkErrorCount = 0;
+
+	private int skiplinkErrorCount = 0;
+
+	private TextCounter textCounter;
+
+	private PageData pageData;
+
+	/**
+	 * 
+	 */
+	public LinkAnalyzer(Document result, PacketCollection allPc,
+			VisualizeMapDataImpl mapData, List<IProblemItem> problems,
+			Set invisibleIdSet, ParamBlind paramBlind, PageData pageData) {
+		this.doc = result;
+		this.allPc = allPc;
+		this.mapData = mapData;
+		this.invisibleIdSet = invisibleIdSet;
+		this.problems = problems;
+		this.pageData = pageData;
+
+		textCounter = new TextCounter(paramBlind.iLanguage);
+		listIntraPageLinks();
+		analyzeIntraPageLinkMapping();
+	}
+
+	private void listIntraPageLinks() {
+		// list up links and anchors
+		NodeList aNl = doc.getElementsByTagName("a");
+		int aNlSize = aNl.getLength();
+		for (int i = 0; i < aNlSize; i++) {
+			Element curEl = (Element) aNl.item(i);
+			String href = curEl.getAttribute("href");
+			String name = curEl.getAttribute("name");
+			if ((href != null) && (href.length() > 0)) {
+				if (href.charAt(0) == '#') {
+
+					VisualizationNodeInfo info = mapData.getNodeInfo(curEl);
+					StringBuffer sb = new StringBuffer();
+
+					// 07/28/2004 fix IndexOutOfBoundsException
+					int size = allPc.size();
+					if (info != null) {
+						for (int j = info.getPacketId(); j < size; j++) {
+							Packet p = (Packet) allPc.get(j);
+							String str = p.getText();
+							if (str != null) {
+								sb.append(str);
+							}
+							if (!p.getContext().isInsideAnchor()) {
+								break;
+							}
+						}
+					}
+					int words = textCounter.getWordCount(sb.toString());
+
+					String linkTitleOrg = "";
+					String linkTitle = "";
+
+					BlindProblem prob = null;
+
+					if (curEl.hasAttribute("title")) {
+						linkTitle = curEl.getAttribute("title");
+						linkTitleOrg = linkTitle;
+
+						if (words == 0) {
+							words += textCounter.getWordCount(linkTitleOrg);
+							if (words > 0) {
+								prob = new BlindProblem(
+										BlindProblem.NO_TEXT_WITH_TITLE_INTRAPAGELINK,
+										linkTitle);
+
+								prob.setTargetNode(mapData.getOrigNode(curEl));
+								Integer idObj = mapData.getIdOfNode(curEl);
+								if (idObj != null) {
+									prob.setNode(curEl, idObj.intValue());
+								} else {
+									prob.setNode(curEl);
+								}
+								// skiplinkErrorCount++;
+								problems.add(prob);
+							}
+						}
+
+						linkTitle = linkTitle.trim();
+						linkTitle = linkTitle.replaceAll("\\[|\\]|\\.|\\!|\\>",
+								"");
+					}
+
+					String linkText = sb.toString();
+					linkText = linkText.trim();
+					linkText = linkText.replaceAll("\\[|\\]|\\.|\\!|\\>", "");
+
+					prob = null;
+
+					if (words > 0) {
+
+						if (linkText.matches(SKIP_TO_MAIN_LINK_DEFINITION)) {
+							skipLinkMap.put(curEl, sb.toString());
+						} else if (linkTitle
+								.matches(SKIP_TO_MAIN_LINK_DEFINITION)) {
+							skipLinkMap.put(curEl, linkTitleOrg);
+						} else {
+							if (linkTitle.matches(WRONG_SKIPLINK_DEFINITION)) {
+								prob = new BlindProblem(
+										BlindProblem.WRONG_SKIP_LINK_TITLE,
+										linkText);
+							}
+
+							if (linkText.matches(WRONG_SKIPLINK_DEFINITION)) {
+								prob = new BlindProblem(
+										BlindProblem.WRONG_SKIP_LINK_TEXT,
+										linkText);
+							}
+						}
+						intraPageLinkList.add(curEl);
+					} else {
+						String noScriptText = HtmlTagUtil
+								.getNoScriptText(curEl);
+						if (noScriptText.length() > 0) {
+							// TODO new alert
+							// TODO append text -> result?
+						} else {
+							prob = new BlindProblem(
+									BlindProblem.NO_TEXT_INTRAPAGELINK, href);
+							if (!(curEl.hasAttribute("onclick") || curEl
+									.hasAttribute("onmouseover"))) {
+
+								intralinkErrorCount++;
+							}
+						}
+					}
+
+					// add problem
+					if (prob != null) {
+						prob.setTargetNode(mapData.getOrigNode(curEl));
+						Integer idObj = mapData.getIdOfNode(curEl);
+						if (idObj != null) {
+							prob.setNode(curEl, idObj.intValue());
+						} else {
+							prob.setNode(curEl);
+						}
+						// skiplinkErrorCount++;
+						problems.add(prob);
+					}
+				}
+			}
+
+			if ((name != null) && (name.length() > 0)) {
+				anchorMap.put(name, curEl);
+			}
+		}
+
+		// TODO consider intrapage link map by using "area"
+	}
+
+	private void analyzeIntraPageLinkMapping() {
+		Iterator it = intraPageLinkList.iterator();
+		while (it.hasNext()) {
+			Element lel = (Element) it.next();
+
+			String href = lel.getAttribute("href").substring(1);
+			// lel.getAttribute("href").substring(1).toLowerCase();
+
+			Element tmpTarget = lel;
+			boolean isVisible = true;
+			while (isVisible && tmpTarget != null) {
+				String idS = tmpTarget.getAttribute("id");
+				if (invisibleIdSet.contains(idS)) {
+					// System.out.println(idS);
+					BlindProblem prob = new BlindProblem(
+							BlindProblem.INVISIBLE_INTRAPAGE_LINK, "\""
+									+ HtmlTagUtil.getTextAltDescendant(lel)
+									+ "\"(href=#" + href + ", id=" + idS + ") ");
+					prob.setTargetNode(mapData.getOrigNode(lel));
+					Integer idObj = mapData.getIdOfNode(lel);
+					if (idObj != null) {
+						prob.setNode(lel, idObj.intValue());
+					} else {
+						prob.setNode(lel);
+					}
+
+					intralinkErrorCount++;
+					problems.add(prob);
+
+					isVisible = false;
+				}
+
+				Node tmpN = tmpTarget.getParentNode();
+				if (tmpN != null && tmpN.getNodeType() == Node.ELEMENT_NODE) {
+					tmpTarget = (Element) tmpN;
+				} else {
+					tmpTarget = null;
+				}
+			}
+			if (!isVisible) {
+				continue;
+			}
+
+			if (href.length() == 0) {
+				NodeList tmpNL = doc.getElementsByTagName("body");
+				if (tmpNL != null && tmpNL.getLength() > 0) {
+					Node tmpBody = tmpNL.item(0);
+					mapData.addIntraPageLinkMapping(lel, tmpBody);
+				}
+				continue;
+			}
+
+			Element ael = (Element) anchorMap.get(href);
+			if (ael != null) {
+				mapData.addIntraPageLinkMapping(lel, ael);
+			} else {
+				Element idEl = doc.getElementById(href);
+				if (idEl != null) {
+					mapData.addIntraPageLinkMapping(lel, idEl);
+				} else {
+					BlindProblem prob = null;
+
+					boolean toTop = false;
+					String linkText = HtmlTagUtil.getTextAltDescendant(lel);
+					if (linkText.matches(".*(\u5148\u982d|\u30c8\u30c3\u30d7|\u4e0a|top|start).*")) {
+						toTop = true;
+					}
+
+					if (skipLinkMap.containsKey(lel)) {
+						if (href.matches(".*top.*") || toTop) {// TBD accuracy
+							prob = new BlindProblem(
+									BlindProblem.ALERT_NO_DEST_INTRA_LINK, href);
+						} else {
+							prob = new BlindProblem(
+									BlindProblem.NO_DEST_SKIP_LINK, href);
+							// TODO onclick?
+							intralinkErrorCount++;
+							skiplinkErrorCount++;
+						}
+
+						skipLinkMap.remove(lel);
+					} else {
+						if (href.matches(".*top.*") || toTop) {// TBD accuracy
+							prob = new BlindProblem(
+									BlindProblem.ALERT_NO_DEST_INTRA_LINK, href);
+						} else {
+							prob = new BlindProblem(BlindProblem.NO_DEST_LINK,
+									href);
+							if (!(lel.hasAttribute("onClick") || lel
+									.hasAttribute("onmouseover"))) {
+								intralinkErrorCount++;
+							}
+						}
+					}
+
+					prob.setTargetNode(mapData.getOrigNode(lel));
+					Integer idObj = mapData.getIdOfNode(lel);
+					if (idObj != null) {
+						prob.setNode(lel, idObj.intValue());
+					} else {
+						prob.setNode(lel);
+					}
+					problems.add(prob);
+				}
+			}
+		}
+	}
+
+	/**
+	 * 
+	 */
+	public Vector<IProblemItem> skipLinkCheck(int maxTime, int maxTimeLeaf) {
+		// TODO consider leaf time
+
+		Vector<IProblemItem> problemV = new Vector<IProblemItem>();
+
+		VisualizationNodeInfo skipLinkNodeInfo = null;
+		int minSkipLinkTime = Integer.MAX_VALUE;
+
+		int headingCount = 0;
+		int skipLinkCount = skipLinkMap.size();
+		int intraDestCount = 0;
+		int forwardIntraLinkCount = 0;
+		int headingDestCount = 0;
+
+		HashSet<Integer> forwardSkipDestIdSet = new HashSet<Integer>();
+		HashSet<Node> skipDestIdSet = new HashSet<Node>();
+		// TODO href="#" -> body
+		HashSet<Integer> headingDestIdSet = new HashSet<Integer>();
+		// TODO href="#" -> body
+
+		Vector<HighlightTargetId> overTimeElementV = new Vector<HighlightTargetId>();
+		Set<Node> overTimeElementChildSet = new HashSet<Node>();
+
+		List nodeList = mapData.getNodeInfoList();
+		Iterator it = nodeList.iterator();
+		while (it.hasNext()) {
+			VisualizationNodeInfo curInfo = (VisualizationNodeInfo) it.next();
+			Node curNode = curInfo.getNode();
+			if (curNode != null) {
+				if (skipLinkMap.containsKey(curNode)) {
+					if (curInfo.getTime() < minSkipLinkTime) {
+						// skip link detected
+						skipLinkNodeInfo = curInfo;
+						minSkipLinkTime = curInfo.getTime();
+					}
+				}
+
+				if (curInfo.isHeading()) {
+					// TODO check (do not include elements under the headings) 
+					headingCount++;
+					headingDestIdSet.add(new Integer(curInfo.getId()));
+				}
+
+				Node tmpNode = curNode;
+				if (curInfo.isBlockElement() && !curInfo.isSequence()) {
+					if (curInfo.getTime() > 120
+							&& !overTimeElementChildSet.contains(curNode)) {
+						overTimeElementV.add(new HighlightTargetId(curInfo
+								.getId(), curInfo.getId()));
+
+						Stack<Node> stack = new Stack<Node>();
+						tmpNode = tmpNode.getFirstChild();
+						while (tmpNode != null) {
+							if (tmpNode.getNodeType() == Node.ELEMENT_NODE) {
+								overTimeElementChildSet.add(tmpNode);
+							}
+
+							if (tmpNode.hasChildNodes()) {
+								stack.push(tmpNode);
+								tmpNode = tmpNode.getFirstChild();
+							} else if (tmpNode.getNextSibling() != null) {
+								tmpNode = tmpNode.getNextSibling();
+							} else {
+								tmpNode = null;
+								while ((tmpNode == null) && (stack.size() > 0)) {
+									tmpNode = (Node) stack.pop();
+									tmpNode = tmpNode.getNextSibling();
+								}
+							}
+						}
+
+					}
+				}
+
+			}
+		}
+
+		Map linkMap = mapData.getIntraPageLinkMap();
+		for (Iterator linkIt = linkMap.keySet().iterator(); linkIt.hasNext();) {
+			Node source = (Node) linkIt.next();
+			Node dest = (Node) linkMap.get(source);
+			// System.out.println("ok: "+source+" : "+dest);
+
+			skipDestIdSet.add(dest);
+
+			Map idMap = mapData.getResult2idMap();
+			if (idMap.containsKey(source) && idMap.containsKey(dest)) {
+				// System.out.println("id found");
+				int sourceId = mapData.getIdOfNode(source).intValue();
+				Integer destIdInteger = mapData.getIdOfNode(dest);
+				int destId = destIdInteger.intValue();
+				if (sourceId < destId) {
+					VisualizationNodeInfo info = mapData.getNodeInfo(source);
+					if (info != null) {
+						int timeFromTop = info.getTime();
+						if (timeFromTop < 60) {
+							forwardSkipDestIdSet.add(destIdInteger);
+						}
+					} else {
+						// can't calc time
+						forwardSkipDestIdSet.add(destIdInteger);
+					}
+				}
+				;
+			}
+		}
+
+		forwardIntraLinkCount = forwardSkipDestIdSet.size();
+		intraDestCount = skipDestIdSet.size();
+		headingDestCount = headingDestIdSet.size();
+
+		// TODO use block element time (isBlock && !isSequence)
+		// TODO alert only single heading
+
+		int overTimeCount = overTimeElementV.size();
+		HighlightTargetId[] overId = new HighlightTargetId[overTimeCount];
+		overTimeElementV.toArray(overId);
+
+		pageData.setSkipMainNum(skipLinkCount);
+		pageData.setForwardIntraPageLinkNum(forwardIntraLinkCount);
+		pageData.setBrokenSkipMainNum(skiplinkErrorCount);
+		pageData.setBrokenIntraPageLinkNum(intralinkErrorCount);
+
+		// TODO
+		// number/ratio of overTimeElement 
+		// number of forwardIntraLink/link target
+		// efficiency of forwardIntraLink
+		// time difference (original/with intra)?
+
+		if (skipLinkNodeInfo == null) {
+			if (headingCount > 0 || forwardIntraLinkCount > 0) {
+				if (maxTime >= MIN_MAX_TIME_TO_ELIMINATE_SKIP_LINK) {
+					problemV.add(new BlindProblem(
+							BlindProblem.NO_SKIPTOMAIN_WITH_STRUCTURE));
+				}
+			} else {
+				if (maxTime < MIN_MAX_TIME_TO_ELIMINATE_SKIP_LINK) {
+					// if max time is less than 90 sec, skip link can be
+					// eliminated.
+					problemV.add(new BlindProblem(
+							BlindProblem.ALERT_NO_SKIPTOMAIN_NO_STRUCTURE, ""
+									+ maxTime));
+					// return true;
+				} else {
+					problemV.add(new BlindProblem(
+							BlindProblem.NO_SKIPTOMAIN_LINK));
+				}
+
+			}
+		} else if (minSkipLinkTime >= MAX_SKIPLINK_REACHING_TIME) {
+			// TODO remove this problem if the page has skip link at top of the page
+			BlindProblem prob = new BlindProblem(
+					BlindProblem.TOOFAR_SKIPTOMAIN_LINK, minSkipLinkTime + " ");
+			Integer idObj = mapData.getIdOfNode(skipLinkNodeInfo.getNode());
+			if (idObj != null) {
+				prob.setNode(skipLinkNodeInfo.getNode(), idObj.intValue());
+			} else {
+				prob.setNode(skipLinkNodeInfo.getNode());
+			}
+			prob.setTargetNode(mapData.getOrigNode(skipLinkNodeInfo.getNode()));
+			problemV.add(prob);
+			// return false;
+		}
+
+		if (overTimeCount > 0) {
+			BlindProblem tmpBP = null;
+			if (headingCount > 0) {
+				if (forwardIntraLinkCount > 0) {
+					tmpBP = new BlindProblem(
+							BlindProblem.LESS_STRUCTURE_WITH_BOTH);
+				} else {
+					tmpBP = new BlindProblem(
+							BlindProblem.LESS_STRUCTURE_WITH_HEADING);
+				}
+			} else {
+				if (forwardIntraLinkCount > 0) {
+					tmpBP = new BlindProblem(
+							BlindProblem.LESS_STRUCTURE_WITH_SKIPLINK);
+				} else {
+					tmpBP = new BlindProblem(BlindProblem.TOO_LESS_STRUCTURE);
+				}
+			}
+			for (int i = 0; i < overTimeCount; i++) {
+				tmpBP.addNodeIds(overId[i]);
+			}
+
+			problemV.add(tmpBP);
+
+		}
+
+		return (problemV);
+	}
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/util/NodeInfoCreator.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/util/NodeInfoCreator.java
new file mode 100644
index 0000000..18226d4
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/util/NodeInfoCreator.java
@@ -0,0 +1,425 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.html.internal.util;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Stack;
+
+import org.eclipse.actf.visualization.engines.blind.html.eval.BlindProblem;
+import org.eclipse.actf.visualization.engines.blind.util.ParamBlind;
+import org.eclipse.actf.visualization.engines.blind.util.TextChecker;
+import org.eclipse.actf.visualization.engines.voicebrowser.Packet;
+import org.eclipse.actf.visualization.engines.voicebrowser.PacketCollection;
+import org.eclipse.actf.visualization.eval.html.HtmlTagUtil;
+import org.eclipse.actf.visualization.eval.problem.IProblemItem;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+public class NodeInfoCreator {
+
+	private static final String HEADING_TAGS = "h1|h2|h3|h4|h5|h6";
+
+	private static final String LIST_TAGS = "ul|ol|dl";
+
+	private static final Set BLOCK_TAG_SET = HtmlTagUtil.getBlockElementSet();
+
+	private VisualizeMapDataImpl mapData;
+
+	private TextChecker textChecker;
+
+	private List<IProblemItem> problems;
+
+	private Set invisibleIdSet;
+
+	private TextCounter textCounter;
+
+	/**
+	 * 
+	 */
+	public NodeInfoCreator(VisualizeMapDataImpl mapData, TextChecker textChecker,
+			List<IProblemItem> problems, Set invisibleIdSet,
+			ParamBlind paramBlind) {
+		this.mapData = mapData;
+		this.textChecker = textChecker;
+		this.problems = problems;
+		this.invisibleIdSet = invisibleIdSet;
+		textCounter = new TextCounter(paramBlind.iLanguage);
+	}
+
+	private String removePeriod(String targetS, Node targetNode) {
+		if (targetNode != null) {
+			String nodeS = targetNode.getNodeName();
+			if (nodeS.equals("img") || nodeS.equals("applet")) {// AREA?
+				if (targetS.endsWith(".]")) {
+					targetS = targetS.substring(0, targetS.lastIndexOf(".]"))
+							+ "]";
+				}
+			}
+		}
+		return targetS;
+	}
+
+	private boolean isIdRequiredInput(Element el) {
+		String tagName = el.getNodeName();
+		if (tagName.equals("select")) {
+			return true;
+		} else if (tagName.equals("textarea")) {
+			return true;
+		} else if (tagName.equals("input")) {
+			String type = el.getAttribute("type");
+			if ((type.length() == 0) | type.equals("text")
+					| type.equals("textarea") | type.equals("radio")
+					| type.equals("checkbox")) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	public void prepareNodeInfo(PacketCollection pc) {
+		// node - nodeInfo
+		int size = 0;
+
+		if (pc == null) {
+			return;
+		} else {
+			size = pc.size();
+		}
+
+		int totalWords = 0;
+		int lineNumber = 0;
+		int previousLineNumber = 0;
+
+		String prevText = null;
+		Packet prevPacket = null;
+
+		for (int it = 0; it < size; it++) {
+			Packet p = (Packet) pc.get(it);
+
+			Node node = p.getNode();
+			if (node.getNodeType() == Node.ELEMENT_NODE) {
+				String nodeName = node.getNodeName();
+				if (nodeName.equals("option")) {
+					Element el = (Element) node;
+					Node attrNode = el.getAttributeNode("selected");
+					if (attrNode == null)
+						continue; // !!!!
+				} else if (nodeName.equals("area")) {
+					continue; // !!!!
+				} else if (nodeName.equals("map")) {
+					continue; // !!!!
+				}
+			}
+
+			String curText = p.getText();
+			if ((curText != null) && (curText.length() > 0)) {
+
+				// TODO consider ALT text ('['+alt+']')
+				// check inappropritate text
+				if (textChecker.isSeparatedJapaneseChars(curText)) {
+					BlindProblem prob = new BlindProblem(
+							BlindProblem.WRONG_TEXT, curText);
+					prob.setNode(p.getNode());
+					prob.setTargetNode(mapData.getOrigNode(p.getNode()));
+					problems.add(prob);
+				}
+
+				// check redundant texts
+				if ((prevPacket != null)
+						&& (p.getContext().isInsideAnchor() == prevPacket
+								.getContext().isInsideAnchor())) {
+					Node curNode = p.getNode();
+					Node prevNode = prevPacket.getNode();
+
+					if (!curNode.getNodeName().equals("input")) {
+						// TODO temporal solution to avoid label problem of
+						// JWAT.
+						// JWAT count same text twice, if an input has a label.
+
+						if (textChecker.isRedundantText(prevText, curText)) {
+							if (!HtmlTagUtil.hasAncestor(curNode, "noscript")
+									&& !HtmlTagUtil.hasAncestor(prevNode,
+											"noscript")) {
+								// remove "." from error (comment from JIM)
+								prevText = removePeriod(prevText, prevNode);
+								curText = removePeriod(curText, curNode);
+
+								BlindProblem prob = new BlindProblem(
+										BlindProblem.REDUNDANT_ALT, "\""
+												+ prevText + "\" & \""
+												+ curText + "\"");
+								prob.setNode(prevNode);
+								prob.addNode(curNode);
+
+								// TODO insideAnchor -> check same target?
+								if (prevNode.getNodeName().equals("img")) {
+									prob.setTargetNode(mapData
+											.getOrigNode(prevNode));
+									prob.setTargetStringForHPB(prevText);
+									problems.add(prob);
+								} else if (curNode.getNodeName().equals("img")) {
+									prob.setTargetNode(mapData
+											.getOrigNode(curNode));
+									prob.setTargetStringForHPB(curText);
+									problems.add(prob);
+								} else {
+									// TODO ALERT_REDUNDANT_TEXT
+								}
+							}
+						}
+					}
+				}
+
+				prevText = curText;
+				prevPacket = p;
+			}
+
+			VisualizationNodeInfo already = mapData.getNodeInfo(p.getNode());
+
+			if (already != null) { /* end tag? */
+				// TODO ??
+			} else {
+				VisualizationNodeInfo info = new VisualizationNodeInfo();
+				info.setPacket(p);
+				// info.setNode(p.getNode());
+				int words = textCounter.getWordCount(p.getText());
+
+				// take into acount structurization
+				boolean isVisible = true;
+
+				Node curNode = p.getNode();
+				while (curNode != null) {
+					String nodeName = curNode.getNodeName();
+					if (curNode.getNodeType() == Node.ELEMENT_NODE) {
+						Element tmpE = (Element) curNode;
+						if (tmpE.hasAttribute("accesskey")) {
+							info.setAccesskey(true);
+						}
+						if (invisibleIdSet.contains(tmpE.getAttribute("id"))) {
+							info.setInvisible(true);
+							isVisible = false;
+							// System.out.println(tmpE.getAttribute("id"));
+						}
+					}
+
+					if (nodeName.matches(HEADING_TAGS)) {
+						info.setHeading(true);
+						info.appendComment("Heading: " + nodeName + ".");
+					} else if (nodeName.equals("th")) {
+						info.setTableHeader(true);
+						info.appendComment("Table header.");
+					} else if (nodeName.equals("label")) {
+						info.setLabel(true);
+						info.appendComment("Label for '"
+								+ ((Element) curNode).getAttribute("for")
+								+ "'. ");
+					}
+
+					if (nodeName.equals("body")) {
+						break;
+					}
+					curNode = curNode.getParentNode();
+				}
+
+				if (isVisible) {
+					info.setWords(words);
+					info.setTotalWords(totalWords);
+					info.setOrgTotalWords(totalWords);
+					totalWords += words;
+					if (words > 0) {
+						lineNumber++;
+					}
+					info.setTotalLines(previousLineNumber);
+					info.setOrgTotalLines(previousLineNumber);
+					info.setLines(lineNumber - previousLineNumber);
+
+					previousLineNumber = lineNumber;
+				} else {
+					// invisible
+					info.setWords(0);
+					info.setTotalWords(totalWords);
+					info.setOrgTotalWords(totalWords);
+					info.setTotalLines(previousLineNumber);
+					info.setOrgTotalLines(previousLineNumber);
+					info.setLines(0);
+				}
+				info.setPacketId(it);
+
+				mapData.addNodeInfoMapping(p.getNode(), info);
+			}
+		}
+	}
+
+	public void createAdditionalNodeInfo(Document doc) {
+		// create elementList
+		// set node info ID
+		// List nodeList = new ArrayList(1024);
+		int origTotalWords = 0;
+		int origTotalLines = 0;
+
+		Map mapTextMap = VisualizeMapUtil.createMapTextMap(doc);
+
+		NodeList bodyNl = doc.getElementsByTagName("body");
+		if (bodyNl.getLength() > 0) {
+			if (bodyNl.getLength() > 1) {
+				System.out.println("multiple body");
+			}
+			Element bodyEl = (Element) bodyNl.item(0);
+
+			// TODO traversel
+
+			if (bodyEl.hasChildNodes()) {
+
+				Stack<Node> stack = new Stack<Node>();
+				stack.push(bodyEl);
+				Node curNode = bodyEl.getFirstChild();
+				VisualizationNodeInfo lastInfo = null;
+				int counter = 0;
+				// int tableCount = 0;
+				int listCount = 0;
+
+				while ((curNode != null) && (stack.size() > 0)) {
+					String curNodeName = curNode.getNodeName();
+					VisualizationNodeInfo curInfo = mapData
+							.getNodeInfo(curNode);
+
+					if (curNode.getNodeType() == Node.TEXT_NODE) {
+						// add text nodes involved in the PacketCollection.
+						if (curInfo != null) {
+							curInfo.setId(counter);
+							mapData.addNodeInfoIntoList(curInfo);
+							counter++;
+							lastInfo = curInfo;
+						}
+					} else if (curNode.getNodeType() == Node.ELEMENT_NODE) {
+						if (curInfo != null) {
+							curInfo.setId(counter);
+							mapData.addNodeInfoIntoList(curInfo);
+							counter++;
+							lastInfo = curInfo;
+						} else {
+							// create NodeInfo for nodes not in packet.
+							// ("b", "img" without alt, etc.)
+							try {
+								curInfo = new VisualizationNodeInfo(lastInfo);
+								curInfo.setWords(0);
+								curInfo.setLines(0);
+								curInfo.setId(counter);
+								curInfo.setNode(curNode);
+								counter++;
+								mapData.addNodeInfoIntoList(curInfo);
+
+								// TODO check invisible
+
+								mapData.addNodeInfoMapping(curNode, curInfo);
+
+							} catch (NullPointerException npe) {
+								// no previous info error
+								npe.printStackTrace();
+							}
+						}
+
+						if (curNodeName.equals("img")) {
+							// TODO handle invisible map
+							String map = ((Element) curNode)
+									.getAttribute("usemap");
+							if ((map != null) && (map.length() > 0)) {
+								int words = curInfo.getWords();
+								String curText = (String) mapTextMap.get(map
+										.toLowerCase().substring(1));
+								int add = textCounter.getWordCount(curText);
+								curInfo.setWords(words + add);
+								curInfo.setLines(curInfo.getLines() + 1);
+							}
+						}
+					}
+
+					if (curInfo != null) {
+						curInfo.setTotalWords(origTotalWords);
+						curInfo.setOrgTotalWords(origTotalWords);
+						curInfo.setTotalLines(origTotalLines);
+						curInfo.setOrgTotalLines(origTotalLines);
+						origTotalWords = origTotalWords + curInfo.getWords();
+						origTotalLines = origTotalLines + curInfo.getLines();
+
+						if (listCount > 0) {
+							curInfo.setSequence(true);
+						}
+						if (BLOCK_TAG_SET.contains(curNodeName)) {
+							curInfo.setBlockElement(true);
+						}
+
+						if (curNode.getNodeType() == Node.ELEMENT_NODE) {
+							if (isIdRequiredInput((Element) curNode)) {
+								curInfo.setIdRequiredInput(true);
+								curInfo.appendComment("Input with id, '"
+										+ ((Element) curNode)
+												.getAttribute("id") + "'. ");
+							}
+						}
+
+						mapData.addNodeIdMapping(curInfo.getNode(),
+								new Integer(curInfo.getId()));
+
+					}
+
+					boolean isListTag = curNodeName.matches(LIST_TAGS);
+					if (curNode.hasChildNodes()) {
+						// if (curNodeName.equals("table")) {
+						// tableCount++;
+						// }
+						if (isListTag) {
+							listCount++;
+						}
+
+						stack.push(curNode);
+						curNode = curNode.getFirstChild();
+					} else if (curNode.getNextSibling() != null) {
+						// if (curNodeName.equals("table")) {
+						// tableCount--;
+						// }
+						if (isListTag) {
+							listCount--;
+						}
+						curNode = curNode.getNextSibling();
+					} else {
+						// if (curNodeName.equals("table")) {
+						// tableCount--;
+						// }
+						if (isListTag) {
+							listCount--;
+						}
+
+						curNode = null;
+						while ((curNode == null) && (stack.size() > 0)) {
+							curNode = (Node) stack.pop();
+							curNodeName = curNode.getNodeName();
+							// if (curNodeName.equals("table")) {
+							// tableCount--;
+							// }
+							if (isListTag) {
+								listCount--;
+							}
+							curNode = curNode.getNextSibling();
+						}
+					}
+				}
+				// System.out.println(tableCount);
+			}
+		}
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/util/TextCounter.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/util/TextCounter.java
new file mode 100644
index 0000000..0eb7697
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/util/TextCounter.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Hironobu TAKAGI - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.html.internal.util;
+
+import java.util.StringTokenizer;
+
+import org.eclipse.actf.visualization.engines.blind.util.ParamBlind;
+
+
+
+public class TextCounter {
+
+    private int lang;
+
+    /**
+     *  
+     */
+    public TextCounter(int lang) {
+        this.lang = lang;
+    }
+
+    public int getWordCount(String str) {
+        if (str == null) {
+            return 0;
+        }
+        
+        switch (lang) {
+        case ParamBlind.JP: //japanese
+            //TODO enhance
+            return str.length();
+        default: //english
+            StringTokenizer st = new StringTokenizer(str, " \t\n\r\f,.[]():/\"");
+            return st.countTokens();
+        }
+
+    }
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/util/VisualizationAttributeInfo.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/util/VisualizationAttributeInfo.java
new file mode 100644
index 0000000..636a892
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/util/VisualizationAttributeInfo.java
@@ -0,0 +1,175 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.html.internal.util;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Stack;
+
+import org.eclipse.actf.util.ui.IElementViewerAccessKeyInfo;
+import org.eclipse.actf.util.ui.IElementViewerIdInfo;
+import org.eclipse.actf.util.ui.IElementViewerInfoProvider;
+import org.eclipse.actf.visualization.engines.blind.html.IVisualizeMapData;
+import org.eclipse.actf.visualization.engines.blind.html.ui.elementViewer.ElementInfoProviderExtension;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class VisualizationAttributeInfo {
+	String attributeName;
+
+	String attributeValue;
+
+	String tagName;
+
+	String category = "";
+
+	String helpUrl = "";
+
+	String description = "";
+
+	int nodeId;
+
+	private static IElementViewerInfoProvider[] provider = ElementInfoProviderExtension
+			.getProviders();
+
+	VisualizationAttributeInfo(Element target, IVisualizeMapData mapData,
+			String targetAttribute) {
+		attributeName = targetAttribute;
+		tagName = target.getNodeName();
+		attributeValue = target.getAttribute(targetAttribute);
+
+		try {
+			nodeId = mapData.getIdOfOrigNode(target).intValue();
+		} catch (Exception e) {
+			//
+			nodeId = -1;
+		}
+
+		// TODO use Properties
+		if (attributeName.equalsIgnoreCase("id")) {
+			for (int i = 0; i < provider.length; i++) {
+				IElementViewerIdInfo idInfo = provider[i]
+						.getIdInfo(attributeValue);
+				if (idInfo != null) {
+					category = idInfo.getCategory();
+					helpUrl = idInfo.getHelpUrl();
+				}
+			}
+		}
+
+		if (attributeName.equalsIgnoreCase("accesskey")) {
+
+			for (int i = 0; i < provider.length; i++) {
+				IElementViewerAccessKeyInfo keyInfo = provider[i]
+						.getAccessKeyInfo(attributeValue);
+				if (keyInfo != null) {
+					description = keyInfo.getDescription();
+					helpUrl = keyInfo.getHelpUrl();
+				}
+			}
+			attributeValue = "Alt+ " + attributeValue;
+		}
+	}
+
+	/**
+	 * @return
+	 */
+	public String getAttribtueName() {
+		return attributeName;
+	}
+
+	/**
+	 * @return
+	 */
+	public String getAttributeValue() {
+		return attributeValue;
+	}
+
+	/**
+	 * @return
+	 */
+	public int getNodeId() {
+		return nodeId;
+	}
+
+	/**
+	 * @return
+	 */
+	public String getTagName() {
+		return tagName;
+	}
+
+	/**
+	 * @return
+	 */
+	public String getHelpUrl() {
+		return helpUrl;
+	}
+
+	/**
+	 * @return
+	 */
+	public String getCategory() {
+		return category;
+	}
+
+	/**
+	 * @return
+	 */
+	public String getDescription() {
+		return description;
+	}
+
+	public String toString() {
+		return (tagName + " : " + attributeValue + " : " + nodeId);
+	}
+
+	public static List listUp(Document target, IVisualizeMapData mapData,
+			String targetAttribute) {
+		List<VisualizationAttributeInfo> result = new ArrayList<VisualizationAttributeInfo>();
+
+		// TODO use XPath
+		NodeList bodyNl = target.getElementsByTagName("body");
+
+		if (bodyNl.getLength() > 0) {
+			Node tmpN = bodyNl.item(0);
+			Stack<Node> stack = new Stack<Node>();
+			while (tmpN != null) {
+				if (tmpN.getNodeType() == Node.ELEMENT_NODE) {
+					Element currentE = (Element) tmpN;
+					if (currentE.hasAttribute(targetAttribute)) {
+						result.add(new VisualizationAttributeInfo(currentE,
+								mapData, targetAttribute));
+					}
+				}
+
+				if (tmpN.hasChildNodes()) {
+					stack.push(tmpN);
+					tmpN = tmpN.getFirstChild();
+				} else if (tmpN.getNextSibling() != null) {
+					tmpN = tmpN.getNextSibling();
+				} else {
+					tmpN = null;
+					while ((tmpN == null) && (stack.size() > 0)) {
+						tmpN = (Node) stack.pop();
+						tmpN = tmpN.getNextSibling();
+					}
+				}
+			}
+		}
+
+		return (result);
+	}
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/util/VisualizationNodeInfo.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/util/VisualizationNodeInfo.java
new file mode 100644
index 0000000..c333b64
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/util/VisualizationNodeInfo.java
@@ -0,0 +1,481 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Hironobu TAKAGI - initial API and implementation
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.html.internal.util;
+
+import org.eclipse.actf.visualization.engines.voicebrowser.Packet;
+import org.w3c.dom.Node;
+
+
+public class VisualizationNodeInfo {
+
+	//separated from VisualizeEngine
+	
+    private int orgTotalWords;
+
+    private int orgTotalLines;
+
+    private int orgTime = 0;
+
+    private int totalWords;
+
+    private int totalLines;
+
+    private int words;
+
+    private int lines;
+
+    private int id;
+
+    private int packetId;
+
+    private Packet packet = null;
+
+    private Node node = null; // only when packet is null
+
+    private boolean isHeading = false;
+
+    private boolean tableHeader = false;
+
+    private boolean isLabel = false;
+
+    private boolean isIdRequiredInput = false;
+
+    private boolean isSequence = false;
+
+    private boolean isBlockElement = false;
+
+    private boolean isInvisible = false;
+
+    private int time = 0;
+
+    private String comment = "";
+
+    VisualizationNodeInfo() {
+        //node = null;
+        totalWords = 0;
+        totalLines = 0;
+        words = 0;
+        lines = 0;
+
+        //
+        id = 0;
+        packetId = 0;
+        packet = null;
+        node = null;
+    }
+
+    VisualizationNodeInfo(VisualizationNodeInfo info) {
+        if (info != null) {
+            totalWords = info.getTotalWords();
+            totalLines = info.getTotalLines();
+            words = info.getWords();
+            lines = info.getLines();
+
+            packet = info.getPacket();
+            packetId = info.getPacketId();
+
+            if (packet == null) {
+                node = info.getNode();
+            }
+
+            //TODO if parent, use comment
+            //comment = info.comment;
+            comment = "";
+
+            //
+            id = 0;
+
+            if ((packet == null) && (node != null)) {
+                System.out.println("115: to be fixed");
+            }
+        } else {
+            //node = null;
+            totalWords = 0;
+            totalLines = 0;
+            words = 0;
+            lines = 0;
+
+            //
+            id = 0;
+            packetId = 0;
+            packet = null;
+            node = null;
+            comment = "";
+        }
+    }
+
+    /**
+     * Returns the node.
+     * 
+     * @return Node
+     */
+    public Node getNode() {
+        //return node;
+        if (packet != null) {
+            return packet.getNode();
+        } else {
+            if (node == null) {
+                System.err.println("VisualizationNodeInfo.getNode: to be fixed");
+            }
+            return node;
+        }
+    }
+
+    /**
+     * Returns the totalWords.
+     * 
+     * @return int
+     */
+    public int getTotalWords() {
+        return totalWords;
+    }
+
+    /**
+     * Sets the node.
+     * 
+     * @param node
+     *            The node to set
+     */
+    public void setNode(Node node) {
+
+        /*
+         * original code
+         * 1. NodeInfoMap.get(targetNode)  (get nodeinfo)
+         * 2-a. nodeinfo != null -> setPacket(nodeinfo.getPacket()) 
+         * 2-b. nodeinfo == null -? setPacket(Null) & setNode(targetNode)
+         *  
+         */
+
+        packet = null;//important!  //TODO modify getNode?
+        this.node = node;
+    }
+
+    /**
+     * Sets the totalWords.
+     * 
+     * @param totalWords
+     *            The totalWords to set
+     */
+    public void setTotalWords(int totalWords) {
+        this.totalWords = totalWords;
+    }
+
+    /**
+     * Returns the lines.
+     * 
+     * @return int
+     */
+    public int getLines() {
+        return lines;
+    }
+
+    /**
+     * Returns the totalLines.
+     * 
+     * @return int
+     */
+    public int getTotalLines() {
+        return totalLines;
+    }
+
+    /**
+     * Returns the words.
+     * 
+     * @return int
+     */
+    public int getWords() {
+        return words;
+    }
+
+    /**
+     * Sets the lines.
+     * 
+     * @param lines
+     *            The lines to set
+     */
+    public void setLines(int lines) {
+        this.lines = lines;
+    }
+
+    /**
+     * Sets the totalLines.
+     * 
+     * @param totalLines
+     *            The totalLines to set
+     */
+    public void setTotalLines(int totalLines) {
+        this.totalLines = totalLines;
+    }
+
+    /**
+     * Sets the words.
+     * 
+     * @param words
+     *            The words to set
+     */
+    public void setWords(int words) {
+        this.words = words;
+    }
+
+    /**
+     * Returns the id.
+     * 
+     * @return int
+     */
+    public int getId() {
+        return id;
+    }
+
+    /**
+     * Sets the id.
+     * 
+     * @param id
+     *            The id to set
+     */
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    /**
+     * Returns the packetId.
+     * 
+     * @return int
+     */
+    public int getPacketId() {
+        return packetId;
+    }
+
+    /**
+     * Sets the packetId.
+     * 
+     * @param packetId
+     *            The packetId to set
+     */
+    public void setPacketId(int packetId) {
+        this.packetId = packetId;
+    }
+
+    /**
+     * @see java.lang.Object#toString()
+     */
+    public String toString() {
+        StringBuffer sb = new StringBuffer();
+
+        sb.append(" Info=");
+        sb.append(this.getTime() + " : ");
+        sb.append(this.getTotalWords());
+        sb.append(",");
+        sb.append(this.getWords());
+        sb.append(",");
+        sb.append(this.getTotalLines());
+        sb.append(",");
+        sb.append(this.getLines());
+        sb.append(",");
+        sb.append(this.getNode());
+        return sb.toString();
+    }
+
+    /**
+     * Returns the packet.
+     * 
+     * @return Packet
+     */
+    public Packet getPacket() {
+        return packet;
+    }
+
+    /**
+     * Sets the packet.
+     * 
+     * @param packet
+     *            The packet to set
+     */
+    public void setPacket(Packet packet) {
+        this.packet = packet;
+    }
+
+    /**
+     * Returns the headingOrListitem.
+     * 
+     * @return boolean
+     */
+    public boolean isHeading() {
+        return isHeading;
+    }
+
+    /**
+     * Sets the headingOrListitem.
+     * 
+     * @param headingOrListitem
+     *            The headingOrListitem to set
+     */
+    public void setHeading(boolean headingOrListitem) {
+        this.isHeading = headingOrListitem;
+    }
+
+    /**
+     * Returns the time.
+     * 
+     * @return int
+     */
+    public int getTime() {
+        return time;
+    }
+
+    /**
+     * Sets the time.
+     * 
+     * @param time
+     *            The time to set
+     */
+    public void setTime(int time) {
+        this.time = time;
+    }
+
+    /**
+     * @return
+     */
+    public String getComment() {
+        return comment;
+    }
+
+    /**
+     * @param string
+     */
+    public void appendComment(String string) {
+
+        //TODO duplicate check
+        if (comment.length() != 0) {
+            //			System.out.println("appendComment: " +comment+" + "+string);
+            comment = comment + " " + string;
+        } else {
+            comment = string;
+        }
+    }
+
+    /**
+     * @return
+     */
+    public boolean isTableHeader() {
+        return tableHeader;
+    }
+
+    /**
+     * @param b
+     */
+    public void setTableHeader(boolean b) {
+        tableHeader = b;
+    }
+
+    /**
+     * @return
+     */
+    public boolean isLabel() {
+        return isLabel;
+    }
+
+    /**
+     * @param b
+     */
+    public void setLabel(boolean b) {
+        isLabel = b;
+    }
+
+    /**
+     * @return
+     */
+    public boolean isIdRequiredInput() {
+        return isIdRequiredInput;
+    }
+
+    /**
+     * @param b
+     */
+    public void setIdRequiredInput(boolean b) {
+        isIdRequiredInput = b;
+    }
+
+    /**
+     * @param hasAccesskey
+     */
+    public void setAccesskey(boolean hasAccesskey) {
+    }
+
+    /**
+     * @return
+     */
+    public boolean isSequence() {
+        return isSequence;
+    }
+
+    /**
+     * @param b
+     */
+    public void setSequence(boolean b) {
+        isSequence = b;
+    }
+
+    /**
+     * @return
+     */
+    public boolean isBlockElement() {
+        return isBlockElement;
+    }
+
+    /**
+     * @param b
+     */
+    public void setBlockElement(boolean b) {
+        isBlockElement = b;
+    }
+
+    /**
+     * @return Returns the isInvisible.
+     */
+    public boolean isInvisible() {
+        return isInvisible;
+    }
+
+    /**
+     * @param isInvisible
+     *            The isInvisible to set.
+     */
+    public void setInvisible(boolean isInvisible) {
+        this.isInvisible = isInvisible;
+    }
+
+    public int getOrgTime() {
+        return orgTime;
+    }
+
+    public int getOrgTotalLines() {
+        return orgTotalLines;
+    }
+
+    public int getOrgTotalWords() {
+        return orgTotalWords;
+    }
+
+    public void setOrgTime(int orgTime) {
+        this.orgTime = orgTime;
+    }
+
+    public void setOrgTotalLines(int orgTotalLines) {
+        this.orgTotalLines = orgTotalLines;
+    }
+
+    public void setOrgTotalWords(int orgTotalWords) {
+        this.orgTotalWords = orgTotalWords;
+    }
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/util/VisualizationResultCleaner.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/util/VisualizationResultCleaner.java
new file mode 100644
index 0000000..5034f29
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/util/VisualizationResultCleaner.java
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.html.internal.util;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class VisualizationResultCleaner {
+
+	//TODO merge into DocumentCleaner
+	
+	public static void clean(Document _result, String url) {
+		// base tag for image/css
+		/*
+		 * NodeList nl = result.getElementsByTagName("head"); Element head =
+		 * (Element) nl.item(0); Element base = result.createElement("base");
+		 * base.setAttribute("href",
+		 * testApp.getPartLeftWebBrowser().getCurURL());
+		 * //head.appendChild(base); head.insertBefore(base,
+		 * head.getFirstChild());
+		 */
+
+		// remove tricky comment for IE encoding detection
+		NodeList htmlNl = _result.getElementsByTagName("html");
+		int size = htmlNl.getLength();
+		for (int i = 0; i < size; i++) {
+			Element htmlE = (Element) htmlNl.item(0);
+			NodeList childNl = htmlE.getChildNodes();
+			for (int j = childNl.getLength() - 1; j > -1; j--) {
+				if (childNl.item(j).getNodeType() == Node.COMMENT_NODE) {
+					htmlE.removeChild(childNl.item(j));
+				}
+			}
+			if (i == 0) {
+				//TODO file protocol
+				htmlE.insertBefore(htmlE.getOwnerDocument().createComment(" saved from url=(0014)about:internet "),htmlE.getFirstChild());
+			}
+		}
+
+		NodeList framesetNl = _result.getElementsByTagName("frameset");
+		if (framesetNl.getLength() > 0) {
+			try {
+				NodeList frameNL = _result.getElementsByTagName("noframes");
+				for (int i = 0; i < frameNL.getLength(); i++) {
+					Node tmpN = frameNL.item(i);
+					Node parentN = tmpN.getParentNode();
+					NodeList childNL = tmpN.getChildNodes();
+					for (int j = 0; j < childNL.getLength(); j++) {
+						_result.getDocumentElement().appendChild(
+								childNL.item(j).cloneNode(true));
+					}
+					parentN.removeChild(tmpN);
+				}
+
+				// TODO noframe message
+				if (frameNL.getLength() < 1) {
+					_result.getDocumentElement().appendChild(
+							_result.createElement("body"));
+				}
+
+				for (int i = 0; i < framesetNl.getLength(); i++) {
+					Node tmpN = framesetNl.item(i);
+					try {
+						tmpN.getParentNode().removeChild(tmpN);
+					} catch (Exception e) {
+						e.printStackTrace();
+					}
+				}
+			} catch (Exception e2) {
+			}
+		}
+
+		NodeList headNl = _result.getElementsByTagName("head");
+		if (headNl.getLength() > 0) {
+			Element meta = _result.createElement("meta");
+			meta.setAttribute("http-equiv", "Content-type");
+			meta.setAttribute("content", "text/html; charset=UTF-8");
+			Element first = (Element) headNl.item(0);
+			if (first.hasChildNodes()) {
+				first.insertBefore(meta, first.getFirstChild());
+			} else {
+				first.appendChild(meta);
+			}
+
+			NodeList titleNl = first.getElementsByTagName("title");
+			if (titleNl.getLength() > 0) {
+				Element title = (Element) titleNl.item(0);
+				Node titleText = title.getFirstChild();
+				if (titleText != null
+						&& titleText.getNodeType() == Node.TEXT_NODE) {
+					titleText.setNodeValue("Visualization result of "
+							+ titleText.getNodeValue());
+				} else {
+					titleText = _result.createTextNode("Visualization result");
+					title.insertBefore(titleText, title.getFirstChild());
+				}
+			} else {
+				Element title = _result.createElement("title");
+				title.appendChild(_result
+						.createTextNode("Visualization result"));
+				first.appendChild(title);
+			}
+
+		}
+	}
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/util/VisualizeColorUtil.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/util/VisualizeColorUtil.java
new file mode 100644
index 0000000..b49f857
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/util/VisualizeColorUtil.java
@@ -0,0 +1,428 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.html.internal.util;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.actf.visualization.engines.blind.html.IVisualizeMapData;
+import org.eclipse.actf.visualization.engines.blind.util.ParamBlind;
+import org.eclipse.swt.graphics.RGB;
+import org.w3c.dom.Comment;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+
+public class VisualizeColorUtil {
+
+    private static final double WORD_JP = (60.0 / (488.0 / 1.3));
+    
+    private Document result;
+
+    private IVisualizeMapData mapData;
+
+    private List nodeInfoList;
+
+    private Map linkMap;
+
+    private ParamBlind param;
+
+    /**
+     * @param result
+     * @param mapData
+     * @param nodeList
+     * @param linkMap
+     * @param param
+     */
+    public VisualizeColorUtil(Document result, VisualizeMapDataImpl mapData, ParamBlind param) {
+        this.result = result;
+        this.mapData = mapData;
+        this.nodeInfoList = mapData.getNodeInfoList();
+        this.linkMap = mapData.getIntraPageLinkMap();
+        this.param = param;
+    }
+
+    public void setColorAll() {
+        int changed = 0;
+
+        DocumentCleaner.removeBgcolor(result);
+
+        initHeadings();
+        
+        for (int i = 0; i < 10; i++) { // appropriate? 10?
+            changed = calcWords();
+            //calcWordsRefresh();
+
+            if (changed == 0)
+                break;
+        } //set color onto each element.
+
+        calcTime();
+        
+        calcOrgTime();
+
+        setColor();
+    }
+
+    private void setColor() {
+
+        String strRGB = "#000000";
+
+        if (param.bVisualizeTable) {
+            NodeList nl = result.getElementsByTagName("head");
+            try {
+                Element headEl = (Element) nl.item(0);
+
+                Element styleEl = result.createElement("style");
+                styleEl.setAttribute("type", "text/css");
+                strRGB = getRGBString(param.tableBorderColor, "#000000");
+                Comment comment = result.createComment("td {border-width: 1px; border-style: dashed; border-color: "
+                        + strRGB + "}");
+                styleEl.appendChild(comment);
+                headEl.appendChild(styleEl);
+
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+
+        Iterator it = nodeInfoList.iterator();
+        while (it.hasNext()) {
+            VisualizationNodeInfo info = (VisualizationNodeInfo) it.next();
+            Node node = info.getNode();
+            Element el = null;
+            if (node.getNodeType() == Node.ELEMENT_NODE) {
+                el = (Element) node;
+            } else if (node.getNodeType() == Node.TEXT_NODE) {
+                /*
+                 * System.out.println( "VisualizeEngine: 709: parent of span: " +
+                 * node.getParentNode().getNodeName());
+                 */
+
+                if (node.getParentNode().getNodeName().equals("textarea")) {
+                    continue;
+                }
+                el = result.createElement("span");
+                node.getParentNode().insertBefore(el, node);
+                if (info.isInvisible()) {
+                    //System.out.println("invisible:"+node);
+                    node.getParentNode().removeChild(node);
+                } else {
+                    el.appendChild(node);
+                }
+                Integer idObj = mapData.getIdOfNode(node);
+                if (idObj != null) {
+                    el.setAttribute("id", "id" + idObj.toString());
+                }
+
+            } else {
+                //error
+                System.out.println("VisualizeEngine: 710: unknown node in the nodeList");
+                continue;
+            }
+
+            if (param.bColorizeTags
+                    && (info.isHeading() | info.isTableHeader() | info.isLabel() | info.isIdRequiredInput())) {
+                if (info.isHeading()) {
+                    strRGB = getRGBString(param.headingTagsColor, "#33CCFF");
+                }
+                if (info.isTableHeader()) {
+                    strRGB = getRGBString(param.tableHeaderColor, "#99FF00");
+                }
+                if (info.isLabel()) {
+                    strRGB = getRGBString(param.labelTagsColor, "#FFFF00");
+                }
+                if (info.isIdRequiredInput()) {
+                    strRGB = getRGBString(param.inputTagsColor, "#FF9900");
+                }
+                el.setAttribute("style", "color: black; background-image: none; background-color:" + strRGB);//+
+                // "}");
+                //} else if (info.getWords() > 0) {
+            } else {
+                int time = info.getTime();
+                if (time == 0) {
+                    switch (param.iLanguage) {
+                    case 1: //japanese
+                        time = calcTimeJp(info.getTotalWords(), info.getTotalLines());
+                        break;
+                    default: //english
+                        time = calcTime(info.getTotalWords(), info.getTotalLines());
+                        break;
+                    }
+                    info.setTime(time);
+                }
+
+                if (param.bVisualizeTime == true) {
+                    el.setAttribute("style", "color: black; background-image: none; background-color: #"
+                            + calcColor(time, param.maxTimeColor, param.iMaxTime));
+
+                } else {
+                    el.setAttribute("style", "color: black; background-image: none; background-color: transparent");
+                }
+            } /*
+               * else { }
+               */
+            /*
+             * el.setAttribute( "comment", info.getPacketId() + "," +
+             * info.getId() + "," + info.getTotalWords() + "," + info.getWords() +
+             * "," + info.getTotalLines() + "," + info.getLines());
+             */
+        }
+    }
+
+    private String calcColor(int time, RGB rgb, int maxTime) {
+
+        double timeD = time;
+        double maxTimeD = maxTime;
+
+        if (time >= maxTime) {
+            java.awt.Color color = new java.awt.Color(rgb.red, rgb.green, rgb.blue);
+            return Integer.toHexString(color.getRGB()).substring(2);
+        } else {
+
+            int colorValueR = (int) (255.0 - (timeD / maxTimeD) * (255.0 - rgb.red));
+            int colorValueG = (int) (255.0 - (timeD / maxTimeD) * (255.0 - rgb.green));
+            int colorValueB = (int) (255.0 - (timeD / maxTimeD) * (255.0 - rgb.blue));
+
+            java.awt.Color color = new java.awt.Color(colorValueR, colorValueG, colorValueB);
+            return Integer.toHexString(color.getRGB()).substring(2);
+        }
+    }
+
+    private String getRGBString(RGB target, String defaultValue) {
+        if (target != null) {
+            return ("rgb(" + target.red + "," + target.green + "," + target.blue + ")");
+        }
+        return (defaultValue);
+    }
+
+    private void initHeadings(){
+        //TODO consider combination of skip nav and Headings
+
+        int headingCount = 0;
+        
+        int curTotalWords = 0;
+        int curTotalLines = 0;
+        int size = nodeInfoList.size();
+        
+        for (int i = 0; i < size; i++) {
+            VisualizationNodeInfo curInfo = (VisualizationNodeInfo) nodeInfoList.get(i);
+
+            if (curInfo.isHeading()) {
+                if(curInfo.getNode().getNodeName().matches("h[1-6]")){
+                    headingCount++;
+                }
+
+                int tmpTotalWords = wordcountForHeading(headingCount);
+                
+                //System.out.println(headingCount+": "+curTotalWords+" "+tmpTotalWords+" "+curInfo.getTotalWords()+" "+curInfo.getWords());
+                if(calcTime(curTotalWords,curTotalLines)>=calcTime(tmpTotalWords,0)){
+                    curTotalWords = tmpTotalWords;
+                    curTotalLines = 0;
+                }
+
+                curInfo.setTotalWords(curTotalWords);
+                curInfo.setTotalLines(curTotalLines);
+                
+                curTotalWords +=  curInfo.getWords();
+                curTotalLines +=  curInfo.getLines();                
+
+            } else {
+                
+                if (calcTime(curInfo.getTotalWords(),curInfo.getTotalLines()) > calcTime(curTotalWords,curTotalLines)) {
+                    curInfo.setTotalWords(curTotalWords);
+                    curInfo.setTotalLines(curTotalLines);
+
+                    curTotalWords +=  curInfo.getWords();
+                    curTotalLines +=  curInfo.getLines();
+                    
+                } else {
+
+                    curTotalWords = curInfo.getTotalWords() + curInfo.getWords();
+                    curTotalLines = curInfo.getTotalLines() + curInfo.getLines();
+                    
+                }
+            }
+        }
+    }    
+
+    private void calcTime(){
+        int size = nodeInfoList.size();
+        for (int i = 0; i < size; i++) {
+            VisualizationNodeInfo curInfo = (VisualizationNodeInfo) nodeInfoList.get(i);
+
+            int time = calcTime(curInfo.getTotalWords(), curInfo.getTotalLines());
+
+            curInfo.setTime(time);
+            if(curInfo.getNode().getNodeName().matches("h[1-6]")){
+                replaceParentInfoTime(curInfo.getNode(),time);
+            }
+        }        
+    }
+    
+    private void calcOrgTime() {
+        int size = nodeInfoList.size();
+        for (int i = 0; i < size; i++) {
+            VisualizationNodeInfo curInfo = (VisualizationNodeInfo) nodeInfoList.get(i);
+
+            int time = calcTime(curInfo.getOrgTotalWords(), curInfo.getOrgTotalLines());
+
+            curInfo.setOrgTime(time);
+        }
+    }
+
+    private void replaceParentInfoTime(Node target, int time) {
+        if (target != null) {
+            Node parent = target.getParentNode();
+            while (parent != null) {
+                if (parent.getFirstChild() == target) {
+                    VisualizationNodeInfo nodeInfo = mapData.getNodeInfo(parent);
+                    if (nodeInfo != null && nodeInfo.getTime() > time) {
+                        nodeInfo.setTime(time);
+                    }
+                    target = parent;
+                    parent = target.getParentNode();
+                } else {
+                    break;
+                }
+            }
+        }
+    }
+
+    private void replaceParentInfoWord(Node target, int word, int line, int newTime) {
+        if (target != null) {
+            Node parent = target.getParentNode();
+            while (parent != null) {
+                if (parent.getFirstChild() == target) {
+                    VisualizationNodeInfo nodeInfo = mapData.getNodeInfo(parent);
+                    if (nodeInfo != null && calcTime(nodeInfo.getTotalWords(),nodeInfo.getTotalLines()) > newTime) {
+                        nodeInfo.setTotalWords(word);
+                        nodeInfo.setTotalLines(line);
+                    }
+
+                    target = parent;
+                    parent = target.getParentNode();
+                } else {
+                    break;
+                }
+            }
+        }
+    }
+
+    private int calcWords() {
+        int countChanged = 0;
+        Set linkSet = linkMap.keySet();
+        Iterator it = linkSet.iterator();
+        while (it.hasNext()) {
+            Node fromNode = (Node) it.next();
+            Node toNode = (Node) linkMap.get(fromNode);
+
+            Integer fromIdInt = mapData.getIdOfNode(fromNode);
+            Integer toIdInt = mapData.getIdOfNode(toNode);
+            if (fromIdInt == null || toIdInt == null) {
+                //toIdInt=null -> Alert is moved to other checker
+                continue;
+            }
+
+            //TODO might be able to use mapData.getNodeInfo(node)
+            int fromId = fromIdInt.intValue();
+            int toId = toIdInt.intValue();
+
+            VisualizationNodeInfo fromInfo = (VisualizationNodeInfo) nodeInfoList.get(fromId);
+            if (fromInfo.getNode() != fromNode) {
+                System.out.println("from node does not exists: " + fromId + " " + fromNode);
+                continue;
+            }
+            VisualizationNodeInfo toInfo = (VisualizationNodeInfo) nodeInfoList.get(toId);
+            if (toInfo.getNode() != toNode) {
+                System.err.println("to node does not exists: " + toId + " " + toNode);
+                continue;
+            }
+
+            VisualizationNodeInfo curInfo = toInfo;
+            int curId = toId;
+            int curTotalWords = fromInfo.getTotalWords() + getWordcountFor2sec();
+            int curTotalLines = fromInfo.getTotalLines();
+            int newTime = calcTime(curTotalWords,curTotalLines);
+
+            while (calcTime(curInfo.getTotalWords(),curInfo.getTotalLines()) > newTime) {
+                countChanged++;
+                curInfo.setTotalWords(curTotalWords);
+                curInfo.setTotalLines(curTotalLines);
+
+                replaceParentInfoWord(curInfo.getNode(), curTotalWords, curTotalLines, newTime);
+
+                //elements after intra page link
+                curId++;
+                if (curId >= nodeInfoList.size()) {
+                    break;
+                }
+
+                curTotalWords = curTotalWords + curInfo.getWords();
+                curTotalLines = curTotalLines + curInfo.getLines();
+                curInfo = (VisualizationNodeInfo) nodeInfoList.get(curId);
+                newTime = calcTime(curTotalWords,curTotalLines);
+            }
+        }
+        return countChanged;
+    }
+
+    private int calcTime(int words, int lines) {
+        switch (param.iLanguage) {
+        case ParamBlind.EN:
+            return calcTimeEn(words, lines);
+        case ParamBlind.JP:
+            return calcTimeJp(words, lines);
+        default:
+            return calcTimeEn(words, lines);
+        }
+    }
+
+    //seconds
+    private int calcTimeEn(int words, int lines) {
+        return (int)((words / (3.0)) +(lines * (0.7)));// 3.0 = 60/180
+    }
+
+    //seconds
+    private int calcTimeJp(int words, int lines) {
+        return (int) ((words * WORD_JP) + (lines * (0.6)));
+    }
+
+    private int wordcountForHeading(int headingNumber){
+        switch (param.iLanguage) {
+        case ParamBlind.EN:
+            return 6*(headingNumber-1)+15;
+        case ParamBlind.JP:
+            return 13*(headingNumber-1)+31;
+        default:
+            return 6*(headingNumber-1)+15;
+        }
+        
+    }
+    
+    private int getWordcountFor2sec(){
+        switch (param.iLanguage) {
+        case ParamBlind.EN:
+            return 6;
+        case ParamBlind.JP:
+            return 13;
+        default:
+            return 6;
+        }        
+    }
+    
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/util/VisualizeMapDataImpl.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/util/VisualizeMapDataImpl.java
new file mode 100644
index 0000000..583bfca
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/util/VisualizeMapDataImpl.java
@@ -0,0 +1,213 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.html.internal.util;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.actf.visualization.engines.blind.html.IVisualizeMapData;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+
+public class VisualizeMapDataImpl implements IVisualizeMapData {
+
+    private Map<Node, Node> orig2resultMap = new HashMap<Node, Node>(1024); //orig node <> result node
+
+    private Map<Node, Node> result2origMap = new HashMap<Node, Node>(1024); //result node <> orig node
+
+    private Map<Node, Integer> orig2idMap = new HashMap<Node, Integer>(1024); //orig node <> result node's id
+
+    private Map<Node, Integer> result2idMap = new HashMap<Node, Integer>(1024); //result node <> result node's id
+
+    private Map<Integer, Integer> accId2id = new HashMap<Integer, Integer>(1024);
+
+    private Map<Integer, Integer> id2accId = new HashMap<Integer, Integer>(1024);
+
+    private Map<Node, VisualizationNodeInfo> node2infoMap = new HashMap<Node, VisualizationNodeInfo>(1024);
+
+    private Map<Node, Node> removedNodeMap = new HashMap<Node, Node>(512);
+
+    private Map<Node, Node> intraPageLinkMap = new HashMap<Node, Node>(256);
+
+    private List<VisualizationNodeInfo> nodeInfoList = new ArrayList<VisualizationNodeInfo>(1024);
+
+    /**
+     *  
+     */
+    public VisualizeMapDataImpl() {
+
+    }
+
+    protected Map getOrig2ResultMap() {
+        return (orig2resultMap);
+    }
+
+    /**
+     * @return Returns the accId2idMap.
+     */
+    protected Map getAccId2IdMap() {
+        return accId2id;
+    }
+
+    /**
+     * @return Returns the id2accIdMap.
+     */
+    public Map getId2AccIdMap() {
+        return id2accId;
+    }
+
+    /* (non-Javadoc)
+	 * @see org.eclipse.actf.visualization.engines.blind.html.IVisualizeMapData#getOrig2idMap()
+	 */
+    public Map getOrig2idMap() {
+        return orig2idMap;
+    }
+
+    /**
+     * @return Returns the result2idMap.
+     */
+    public Map getResult2idMap() {
+        return result2idMap;
+    }
+
+    /**
+     * @return Returns the intraPageLinkMap.
+     */
+    protected Map getIntraPageLinkMap() {
+        return intraPageLinkMap;
+    }
+
+    /**
+     * @return Returns the nodeInfoList.
+     */
+    public List getNodeInfoList() {
+        return nodeInfoList;
+    }
+
+    /**
+     * @return Returns the node2infoMap.
+     */
+    protected Map getNode2infoMap() {
+        return node2infoMap;
+    }
+
+    //
+
+    protected void addOrigResultMapping(Node orig, Node result) {
+        orig2resultMap.put(orig, result);
+        result2origMap.put(result, orig);
+    }
+
+    public void addOrigIdAccIdMapping(Integer orig, Integer acc) {
+        accId2id.put(acc, orig);
+        id2accId.put(orig, acc);
+    }
+
+    /* (non-Javadoc)
+	 * @see org.eclipse.actf.visualization.engines.blind.html.IVisualizeMapData#addReplacedNodeMapping(org.w3c.dom.Node, org.w3c.dom.Node)
+	 */
+    public void addReplacedNodeMapping(Node result, Node replacement) {
+        removedNodeMap.put(result, replacement);
+    }
+
+    protected void addNodeIdMapping(Node result, Integer id) {
+        result2idMap.put(result, id);
+        orig2idMap.put(getOrigNode(result), id);
+    }
+
+    protected void addNodeInfoMapping(Node result, VisualizationNodeInfo nodeInfo) {
+        node2infoMap.put(result, nodeInfo);
+    }
+
+    protected void addNodeInfoIntoList(VisualizationNodeInfo info) {
+        nodeInfoList.add(info);
+    }
+
+    protected void addIntraPageLinkMapping(Node source, Node dest) {
+        intraPageLinkMap.put(source, dest);
+    }
+
+    //
+
+    /* (non-Javadoc)
+	 * @see org.eclipse.actf.visualization.engines.blind.html.IVisualizeMapData#getOrigNode(org.w3c.dom.Node)
+	 */
+    public Node getOrigNode(Node result) {
+        return (Node) result2origMap.get(result);
+    }
+
+    /* (non-Javadoc)
+	 * @see org.eclipse.actf.visualization.engines.blind.html.IVisualizeMapData#getResultNode(org.w3c.dom.Node)
+	 */
+    public Node getResultNode(Node orig) {
+        return (Node) orig2resultMap.get(orig);
+    }
+
+    /* (non-Javadoc)
+	 * @see org.eclipse.actf.visualization.engines.blind.html.IVisualizeMapData#getReplacement(org.w3c.dom.Node)
+	 */
+    public Node getReplacement(Node result) {
+        return (Node) removedNodeMap.get(result);
+    }
+
+    /* (non-Javadoc)
+	 * @see org.eclipse.actf.visualization.engines.blind.html.IVisualizeMapData#getIdOfNode(org.w3c.dom.Node)
+	 */
+    public Integer getIdOfNode(Node result) {
+        return (Integer) result2idMap.get(result);
+    }
+
+    /* (non-Javadoc)
+	 * @see org.eclipse.actf.visualization.engines.blind.html.IVisualizeMapData#getIdOfOrigNode(org.w3c.dom.Node)
+	 */
+    public Integer getIdOfOrigNode(Node orig) {
+        return (Integer) orig2idMap.get(orig);
+    }
+
+    /* (non-Javadoc)
+	 * @see org.eclipse.actf.visualization.engines.blind.html.IVisualizeMapData#getNodeInfo(org.w3c.dom.Node)
+	 */
+    public  VisualizationNodeInfo getNodeInfo(Node result) {
+        return (VisualizationNodeInfo) node2infoMap.get(result);
+    }
+
+    public void makeIdMapping(String targetIdS){
+		Set nodeSet = getResult2idMap().keySet();
+		Iterator it = nodeSet.iterator();
+		while (it.hasNext()) {
+			Node node = (Node) it.next();
+			if (node.getNodeType() == Node.ELEMENT_NODE) {
+				Integer targetId = getIdOfNode(node);
+				Element tmpE = (Element) node;
+				tmpE.setAttribute("id", "id" + (targetId.toString()));
+
+				if (tmpE.hasAttribute(targetIdS)) {
+					try {
+						Integer accId = new Integer(tmpE
+								.getAttribute(targetIdS));
+						addOrigIdAccIdMapping(targetId, accId);
+					} catch (Exception e) {
+					}
+				}
+				DocumentCleaner.removeOnMouse((Element) node);
+			}
+		}
+
+    }
+    
+    
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/util/VisualizeMapUtil.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/util/VisualizeMapUtil.java
new file mode 100644
index 0000000..d0fb8c0
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/util/VisualizeMapUtil.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.html.internal.util;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Stack;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class VisualizeMapUtil {
+
+    // move from VisualizeEngine
+
+    public static void createNode2NodeMap(Document orig, Document dest, VisualizeMapDataImpl mapData) {
+        NodeList bodyNl = dest.getElementsByTagName("body");
+        NodeList origBodyNl = orig.getElementsByTagName("body");
+
+        if (origBodyNl.getLength() > 0) {
+
+            Element bodyEl = (Element) bodyNl.item(0);
+            Element origBodyEl = (Element) origBodyNl.item(0);
+
+            if (origBodyEl.hasChildNodes()) {
+
+                Stack<Node> stack = new Stack<Node>();
+                Stack<Node> origStack = new Stack<Node>();
+
+                stack.push(bodyEl);
+                origStack.push(origBodyEl);
+
+                Node curNode = bodyEl.getFirstChild();
+                Node origCurNode = origBodyEl.getFirstChild();
+
+                while ((origCurNode != null) && (origStack.size() > 0)) {
+                    mapData.addOrigResultMapping(origCurNode, curNode);
+
+                    try {
+
+                        if (origCurNode.hasChildNodes()) {
+                            stack.push(curNode);
+                            origStack.push(origCurNode);
+
+                            curNode = curNode.getFirstChild();
+                            origCurNode = origCurNode.getFirstChild();
+                        } else if (origCurNode.getNextSibling() != null) {
+                            curNode = curNode.getNextSibling();
+                            origCurNode = origCurNode.getNextSibling();
+                        } else {
+                            origCurNode = null;
+                            while ((origCurNode == null) && (origStack.size() > 0)) {
+                                curNode = stack.pop();
+                                origCurNode = origStack.pop();
+
+                                curNode = curNode.getNextSibling();
+                                origCurNode = origCurNode.getNextSibling();
+                            }
+                        }
+                    } catch (NullPointerException npe) {
+                        npe.printStackTrace();
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    public static Map createMapTextMap(Document doc) {
+        Map<String, String> mapTextMap = new HashMap<String, String>();
+        NodeList nl = doc.getElementsByTagName("area");
+        int size = nl.getLength();
+
+        for (int i = 0; i < size; i++) {
+            Node node = nl.item(i);
+            if (node.getParentNode().getNodeName().equals("map")) {
+                String curText = ((Element) node).getAttribute("alt");
+                String mapName = ((Element) node.getParentNode()).getAttribute("name");
+                String mapText = mapTextMap.get(mapName.toLowerCase());
+                if (mapText != null) {
+                    mapTextMap.put(mapName.toLowerCase(), mapText + ". " + curText);
+                } else {
+                    mapTextMap.put(mapName.toLowerCase(), curText);
+                }
+            }
+        }
+        return (mapTextMap);
+    }
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/util/VisualizeViewUtil.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/util/VisualizeViewUtil.java
new file mode 100644
index 0000000..f8c9d38
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/internal/util/VisualizeViewUtil.java
@@ -0,0 +1,486 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.html.internal.util;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.actf.visualization.engines.blind.BlindVizEnginePlugin;
+import org.eclipse.actf.visualization.engines.blind.html.IVisualizeMapData;
+import org.eclipse.actf.visualization.engines.blind.html.VisualizeEngine;
+import org.eclipse.actf.visualization.engines.blind.html.eval.BlindProblem;
+import org.eclipse.actf.visualization.engines.voicebrowser.Packet;
+import org.eclipse.actf.visualization.engines.voicebrowser.PacketCollection;
+import org.eclipse.actf.visualization.eval.problem.HighlightTargetId;
+import org.eclipse.actf.visualization.eval.problem.IProblemItem;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class VisualizeViewUtil {
+
+	// separated from VisualizeEngine
+
+	public static File prepareActions(Document result,
+			VisualizeMapDataImpl mapData, String baseUrl, boolean servletMode) {
+
+		Map linkMap = mapData.getIntraPageLinkMap();
+		List targetElementList = mapData.getNodeInfoList();
+
+		NodeList bodyEl = result.getElementsByTagName("body");
+
+		for (int i = 0; i < bodyEl.getLength(); i++) {
+			Element tmpE = (Element) bodyEl.item(i);
+			DocumentCleaner.removeOnMouse(tmpE);
+			DocumentCleaner.removeOnLoad(tmpE);
+		}
+
+		// TODO move to appropriate place
+		// to handle no body page
+		if (bodyEl.getLength() == 0) {
+			Node tmpN = result.getDocumentElement();
+			if (tmpN != null) {
+				tmpN.appendChild(result.createElement("body"));
+			} else {
+				System.out.println("VisualizeViewUtil: no doc element");
+				// TODO test
+				return null;
+			}
+		}
+
+		// div for arrow
+		Element div = result.createElement("div");
+		div
+				.setAttribute("style",
+						"position:absolute;pixelLeft= 10;pixelTop=10; color:red;font-size=12pt");
+		div.setAttribute("id", "test");
+
+		// bodyEl.item(bodyEl.getLength() - 1).appendChild(div);
+		Node tmpBody = bodyEl.item(0);
+		tmpBody.insertBefore(div, tmpBody.getFirstChild());
+
+		insertLinkIcon(result, linkMap, baseUrl);
+
+		// div for control_pane
+		insertControlPane(result);
+
+		// remove links of "map"
+
+		bodyEl = result.getElementsByTagName("map");
+		if (bodyEl != null) {
+			for (int i = 0; i < bodyEl.getLength(); i++) {
+				Element x = (Element) bodyEl.item(i);
+				x.setAttribute("onClick", "cancelMapLink(event)");
+			}
+		}
+
+		return (createScriptFile(result, targetElementList, baseUrl,
+				servletMode));
+
+	}
+
+	private static void insertLinkIcon(Document doc, Map linkMap, String baseUrl) {
+		Set linkIconSet = linkMap.keySet();
+		Iterator it = linkIconSet.iterator();
+		Set<String> alreadySet = new HashSet<String>();
+		int id = 0;
+		while (it.hasNext()) {
+			Element lel = (Element) it.next();
+			Element ael = (Element) linkMap.get(lel);
+
+			Element imgel1 = doc.createElement("img");
+			String href = lel.getAttribute("href").substring(1);
+			imgel1.setAttribute("alt", "Intra-page link: " + href);
+			imgel1.setAttribute("title", "Intra-page link: " + href);
+			imgel1.setAttribute("src", baseUrl + "img/jump.gif");
+			imgel1.setAttribute("name", "jump" + id);
+
+			if (lel.hasChildNodes()) {
+				lel.insertBefore(imgel1, lel.getFirstChild());
+			} else {
+				lel.appendChild(imgel1);
+			}
+
+			if (!alreadySet.contains(href)) {
+
+				Element imgel2 = doc.createElement("img");
+				imgel2.setAttribute("alt", "Intra-page link destination: "
+						+ href);
+				imgel2.setAttribute("title", "Intra-page link destination: "
+						+ href);
+				imgel2.setAttribute("src", baseUrl + "img/dest.gif");
+				imgel2.setAttribute("name", href);
+
+				if (ael.hasChildNodes()) {
+					ael.insertBefore(imgel2, ael.getFirstChild());
+				} else {
+					ael.appendChild(imgel2);
+				}
+				alreadySet.add(href);
+			}
+			id++;
+		}
+	}
+
+	private static void insertControlPane(Document result) {
+		NodeList bodyEl = result.getElementsByTagName("body");
+		Element div = result.createElement("div");
+		div
+				.setAttribute(
+						"style",
+						"position:absolute;font-size: medium; background-color: #FFFFFF; border-color: #333333 #000000 #000000; padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px; border-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px");
+		div.setAttribute("id", "control_pane");
+
+		Element input1 = result.createElement("input");
+		input1.setAttribute("type", "image");
+		input1.setAttribute("src", "img/stop.gif");
+		input1.setAttribute("alt", "Stop/Move Balloon");
+		input1.setAttribute("onClick", "control_moving()");
+		div.appendChild(input1);
+
+		Element input2 = result.createElement("input");
+		input2.setAttribute("type", "image");
+		input2.setAttribute("src", "img/clear.gif");
+		input2.setAttribute("alt", "Clear Line");
+		input2.setAttribute("onClick", "clean_Line()");
+
+		Element input3 = result.createElement("input");
+		input3.setAttribute("type", "image");
+		input3.setAttribute("src", "img/refresh.gif");
+		input3.setAttribute("alt", "Refresh Line");
+		input3.setAttribute("onClick", "refresh_Jump()");
+
+		Element input4 = result.createElement("input");
+		input4.setAttribute("type", "image");
+		input4.setAttribute("src", "img/draw.gif");
+		input4.setAttribute("alt", "Draw All Line");
+		input4.setAttribute("onClick", "draw_all_Line()");
+
+		div.appendChild(input2);
+		div.appendChild(input3);
+		div.appendChild(input4);
+		// bodyEl.item(bodyEl.getLength() - 1).appendChild(div);
+		Node tmpBody = bodyEl.item(0);
+		tmpBody.insertBefore(div, tmpBody.getFirstChild());
+	}
+
+	private static File createScriptFile(Document result, List elementList,
+			String baseUrl, boolean servletMode) {
+		try {
+			PrintWriter pw;
+
+			File valiantFile = BlindVizEnginePlugin.createTempFile("variant",
+					".js");
+			pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(
+					valiantFile), "UTF-8"));
+
+			StringBuffer sb = new StringBuffer();
+			sb.append("var id2time = new Array();");
+			sb.append("var id2comment = new Array();");
+
+			int size = elementList.size();
+			for (int i = 0; i < size; i++) {
+				VisualizationNodeInfo curInfo = (VisualizationNodeInfo) elementList
+						.get(i);
+
+				//
+				String comment = curInfo.getComment();
+				StringBuffer comment_sb = new StringBuffer();
+				// if (871 == curInfo.getId()) {
+				for (int x = 0; x < comment.length(); x++) {
+					if (comment.charAt(x) == '\"') {
+						comment_sb.append("\\");
+					}
+					if (comment.charAt(x) == '\'') {
+						comment_sb.append('\\');
+					}
+
+					comment_sb.append(comment.charAt(x));
+				}
+
+				sb.append("id2time['id");
+				sb.append(curInfo.getId());
+				sb.append("']=");
+				sb.append(curInfo.getTime());
+				sb.append(";");
+
+				sb.append("id2comment['id");
+				sb.append(curInfo.getId());
+				sb.append("']='");
+				sb.append(comment_sb.toString());
+				sb.append("';");
+
+			}
+
+			String tmpS = sb.toString().replaceAll("\n", "").replaceAll("\r",
+					"");
+			pw.write(tmpS);
+
+			sb = new StringBuffer();
+			sb.append("var baloonSwitch = 1; ");
+			sb.append("var baseUrl = '" + baseUrl + "'; ");
+			sb.append("var acc_imageDir = 'img/'; ");
+			if (servletMode) {
+				sb.append("var servletMode = true; ");
+			} else {
+				sb.append("var servletMode = false; ");
+			}
+
+			// speed up -> sb.append("var isAlert = false; ");
+
+			sb.append("var isAlert = true; ");
+
+			pw.write(sb.toString());
+
+			pw.flush();
+			pw.close();
+
+			NodeList nl = result.getElementsByTagName("head");
+			if (nl.getLength() > 0) {
+				Element el = (Element) nl.item(0);
+				Element script = result.createElement("script");
+				// script.setAttribute("src", "file:///C:/C/highlight.js");
+				script.setAttribute("src", baseUrl + valiantFile.getName());
+				el.appendChild(script);
+
+				Element script2 = result.createElement("script");
+				// script.setAttribute("src", "file:///C:/C/highlight.js");
+				script2.setAttribute("src", baseUrl + "img/highlight.js");
+				el.appendChild(script2);
+			}
+
+			Element div = result.createElement("div");
+			div
+					.setAttribute(
+							"style",
+							"position:absolute;font-size: medium; background-color: #FFFFFF; border-color: #333333 #000000 #000000; padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px; border-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px");
+			div.setAttribute("id", "balloon");
+
+			Element messageDiv = result.createElement("div");
+			messageDiv.setAttribute("id", "message");
+			messageDiv.appendChild(result.createTextNode(""));
+			div.appendChild(messageDiv);
+
+			NodeList bodyNl = result.getElementsByTagName("body");
+			if (bodyNl.getLength() > 0) {
+				Element bodyEl = (Element) bodyNl.item(0);
+				bodyEl.insertBefore(div, bodyEl.getFirstChild());
+			}
+			return valiantFile;
+		} catch (Exception e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+	public static void visualizeError(Document doc, List problems,
+			IVisualizeMapData mapData, String baseUrlS) {
+		int size = problems.size();
+
+		// TODO setNodeId might be duplicated
+		for (int i = 0; i < size; i++) {
+			BlindProblem prob = (BlindProblem) problems.get(i);
+			Node node = prob.getTargetNodeInResultDoc();
+			Integer idObj = mapData.getIdOfNode(node);
+
+			int subType = prob.getProblemSubType();
+			switch (subType) {
+			case BlindProblem.WRONG_ALT_AREA:
+			case BlindProblem.NO_ALT_AREA:
+			case BlindProblem.TOO_LESS_STRUCTURE:
+			case BlindProblem.NO_SKIPTOMAIN_LINK:
+				break;
+			default:
+				if (idObj != null) {
+					int id = idObj.intValue();
+					prob.setNodeId(id);
+				}
+			}
+
+			VisualizationNodeInfo info = mapData.getNodeInfo(node);
+			if (info != null) {
+				info.appendComment(prob.getDescription());
+			} else {
+				if (node != null && node.getNodeType() == Node.ELEMENT_NODE) {
+					try {
+						String id = ((Element) node).getAttribute("id");
+						if (id.startsWith("id")) {
+							id = id.substring(2);
+							// info =
+
+						}
+					} catch (Exception e) {
+						//
+					}
+				}
+			}
+
+			switch (prob.getProblemSubType()) {
+			case BlindProblem.NO_ALT_IMG:
+			case BlindProblem.WRONG_ALT_IMG:
+				Element el = (Element) node;
+				Node replacement = mapData.getReplacement(el);
+				if (replacement != null) {
+					el = (Element) replacement;
+				}
+				Element img = createErrorImageElement(node, prob, idObj,
+						baseUrlS);
+				el.appendChild(img);
+				break;
+			case BlindProblem.REDUNDANT_ALT:
+				int startId = -1;
+				int endId = -1;
+				try {
+					List nl = prob.getNodeList();
+					node = (Node) nl.get(1);
+					Integer endNodeId = mapData.getIdOfNode(node);
+					if (endNodeId != null) {
+						endId = endNodeId.intValue();
+					}
+				} catch (NullPointerException npe) {
+					npe.printStackTrace();
+				}
+
+				if (idObj != null) {
+					startId = idObj.intValue();
+				} else if (endId > -1) {
+					startId = endId;
+				}
+
+				prob.setNodeId(startId);
+
+				prob.addNodeIds(new HighlightTargetId(startId, startId));
+				prob.addNodeIds(new HighlightTargetId(endId, endId));
+
+				break;
+			case BlindProblem.NO_DEST_LINK:
+			case BlindProblem.NO_TEXT_INTRAPAGELINK:
+			case BlindProblem.NO_DEST_SKIP_LINK:
+			case BlindProblem.WRONG_SKIP_LINK_TEXT:
+			case BlindProblem.TOOFAR_SKIPTOMAIN_LINK:
+			case BlindProblem.NO_TEXT_WITH_TITLE_INTRAPAGELINK:
+			case BlindProblem.INVISIBLE_INTRAPAGE_LINK:
+			case BlindProblem.WRONG_SKIP_LINK_TITLE:
+				Element element = (Element) node;
+				Element image = createErrorImageElement(element, prob, idObj,
+						baseUrlS);
+				element.appendChild(image);
+				break;
+			case BlindProblem.WRONG_TEXT:
+				// Node node = prob.getNode();
+				Element image2 = createErrorImageElement(node, prob, idObj,
+						baseUrlS);
+				if (node.getNodeType() == Node.ELEMENT_NODE) {
+					node.appendChild(image2);
+				} else {
+					node.getParentNode().insertBefore(image2, node);
+				}
+				break;
+			case BlindProblem.NO_VALUE_INPUT_BUTTON:
+			case BlindProblem.SEPARATE_DBCS_INPUT_VALUE:
+				Element image3 = createErrorImageElement(node, prob, idObj,
+						baseUrlS);
+				node.getParentNode().insertBefore(image3, node);
+				break;
+
+			default:
+			}
+		}
+	}
+
+	private static Element createErrorImageElement(Node target,
+			IProblemItem prob, Integer idObj, String baseUrlS) {
+		Element img = target.getOwnerDocument().createElement("img");
+		img.setAttribute("alt", "error icon");
+		img.setAttribute("title", prob.getDescription());
+		img.setAttribute("onmouseover", "updateBaloon('id" + idObj + "');");
+		img.setAttribute("src", baseUrlS + "img/"
+				+ VisualizeEngine.ERROR_ICON_NAME);
+		return (img);
+	}
+
+	public static Document returnTextView(Document result,
+			PacketCollection allPc, String baseUrl) {
+		NodeList bodyNl = result.getElementsByTagName("body");
+
+		// TODO remove second Body, script, etc.
+		if (bodyNl.getLength() > 0) {
+			Element bodyEl = (Element) bodyNl.item(0);
+			NodeList nl = bodyEl.getChildNodes();
+			int size = nl.getLength();
+			for (int i = size - 1; i >= 0; i--) {
+				bodyEl.removeChild(nl.item(i));
+			}
+			String str;
+			size = allPc.size();
+			boolean brFlag = false;
+			boolean insideLink = false;
+			for (int i = 0; i < size; i++) {
+				Packet p = (Packet) allPc.get(i);
+
+				if (p.getContext().isLinkTag()) {
+					insideLink = true;
+				}
+				str = p.getText();
+				if (str != null && !str.equals("")) {
+
+					Element spanEl = result.createElement("span");
+					spanEl.appendChild(result.createTextNode(str));
+					bodyEl.appendChild(spanEl);
+
+					if (insideLink)
+						spanEl.setAttribute("style",
+								"text-decoration: underline;");
+					brFlag = false;
+				}
+				if (p.getContext().isLineDelimiter()) {
+					if (brFlag) {
+						/*
+						 * Element spanEl = result.createElement("span");
+						 * spanEl.appendChild( result.createTextNode(" SKIPPED
+						 * ")); bodyEl.appendChild(spanEl);
+						 */
+					} else {
+						Element br = result.createElement("br");
+						bodyEl.appendChild(br);
+						brFlag = true;
+					}
+				}
+				if (!p.getContext().isLinkTag()) {
+					insideLink = false;
+				}
+			}
+		}
+
+		NodeList nl = result.getElementsByTagName("head");
+		if (nl.getLength() > 0) {
+
+			Element el = (Element) nl.item(0);
+			Element script = result.createElement("script");
+			script.setAttribute("src", baseUrl + "img/highlight-dummy.js");
+			el.appendChild(script);
+
+		}
+
+		return result;
+	}
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/actions/BlindOpenIdCssAction.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/actions/BlindOpenIdCssAction.java
new file mode 100644
index 0000000..da1158c
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/actions/BlindOpenIdCssAction.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.html.ui.actions;
+
+import org.eclipse.actf.visualization.engines.blind.BlindVizEnginePlugin;
+import org.eclipse.actf.visualization.engines.blind.html.internal.Messages;
+import org.eclipse.actf.visualization.engines.blind.html.ui.elementViewer.ElementViewerManager;
+import org.eclipse.jface.action.Action;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+
+
+
+public class BlindOpenIdCssAction extends Action {
+
+	public BlindOpenIdCssAction() {
+		setToolTipText(Messages.getString("BlindView.Open_ID"));
+		//TODO
+		setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin(BlindVizEnginePlugin.PLUGIN_ID, "icons/ButtonIdCss.png"));
+		setText("ID/CSS");
+	}
+
+	public void run() {
+        ElementViewerManager.getInstance().openElementViewer();
+	}
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/CSSViewer.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/CSSViewer.java
new file mode 100644
index 0000000..aa3be45
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/CSSViewer.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.html.ui.elementViewer;
+
+import java.util.Iterator;
+import java.util.Set;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.List;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.PlatformUI;
+
+public class CSSViewer {
+	
+    private Composite compositeCss;
+
+    private List cssListCon;
+
+    public CSSViewer(Composite parent) {
+        compositeCss = new Composite(parent, SWT.NULL);
+        compositeCss.setLayoutData(new GridData(GridData.FILL_BOTH));
+        GridLayout gridLayout1 = new GridLayout();
+        gridLayout1.numColumns = 1;
+        compositeCss.setLayout(gridLayout1);
+
+        cssListCon = new List(compositeCss, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
+        GridData gridData = new GridData(GridData.FILL_BOTH);
+        cssListCon.setLayoutData(gridData);
+
+        cssListCon.addMouseListener(new MouseAdapter() {
+            public void mouseUp(MouseEvent arg0) {
+                if (arg0.stateMask == SWT.BUTTON3) {
+                    if (cssListCon.getSelectionIndex() >= 0)
+                        openPopupMenu(cssListCon.getSelectionIndex());
+                }
+            }
+
+            //			public void mouseDoubleClick(MouseEvent arg0) {
+                //				if (cssListCon.getSelectionIndex() >= 0)
+                //					getAndViewFile(cssListCon.getSelectionIndex());
+                //			}
+            });
+    }
+
+    /**
+     * @return
+     */
+    public Composite getCompositeCss() {
+        return compositeCss;
+    }
+
+    public void setCssSet(Set cssSet) {
+        cssListCon.removeAll();
+        if (cssSet != null) {
+            for (Iterator i = cssSet.iterator(); i.hasNext();) {
+                cssListCon.add((String) i.next());
+            }
+        }
+    }
+
+    private void openPopupMenu(int index) {
+        String[] itemName = new String[2];
+        itemName[0] = "&Copy URL";
+        itemName[1] = "&Open";
+        boolean[] enabled = new boolean[2];
+        enabled[0] = true;
+        enabled[1] = true;
+        PopupMenu popupMenu = new PopupMenu(new Shell(), itemName, enabled);
+        String strRet = popupMenu.open();
+        if (strRet.equals(itemName[0])) {
+            Clipboard clipboard = new Clipboard(compositeCss.getDisplay());
+            clipboard.setContents(new Object[] { cssListCon.getItem(index) }, new Transfer[] { TextTransfer
+                    .getInstance() });
+        } else if (strRet.equals(itemName[1])) {
+            getAndViewFile(cssListCon.getSelectionIndex());
+        }
+    }
+
+    private void getAndViewFile(int index) {
+        try {
+        	PlatformUI.getWorkbench().getHelpSystem().displayHelpResource(cssListCon.getItem(index));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/ElementInfoProviderExtension.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/ElementInfoProviderExtension.java
new file mode 100644
index 0000000..f2dffc9
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/ElementInfoProviderExtension.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.html.ui.elementViewer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.actf.util.ui.IElementViewerInfoProvider;
+import org.eclipse.actf.visualization.engines.blind.html.HtmlVizPlugin;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.Platform;
+
+
+
+public class ElementInfoProviderExtension {
+
+    private static final String PROVIDER = "provider";
+
+    private static final String ATTR_CLASS = "class";
+
+    private static ElementInfoProviderExtension[] extensions;
+
+    private static IElementViewerInfoProvider[] providers = null;
+
+    public static IElementViewerInfoProvider[] getProviders() {
+        if (providers != null){
+            return providers;
+        }
+
+        ElementInfoProviderExtension[] tmpExtensions = getExtensions();
+        ArrayList<IElementViewerInfoProvider> tmpList = new ArrayList<IElementViewerInfoProvider>();
+        if (tmpExtensions != null) {
+            for (int i = 0; i < tmpExtensions.length; i++) {
+                IElementViewerInfoProvider tmpProvider = tmpExtensions[i].getElementViewerInfoProvider();
+                if (tmpProvider != null){
+                    tmpList.add(tmpProvider);
+                }
+            }
+        }
+        providers = new IElementViewerInfoProvider[tmpList.size()];
+        tmpList.toArray(providers);
+        return providers;
+    }
+
+    private static ElementInfoProviderExtension[] getExtensions() {
+        if (extensions != null)
+            return extensions;
+
+        IExtension[] tmpExtensions = Platform.getExtensionRegistry().getExtensionPoint(HtmlVizPlugin.PLUGIN_ID,
+                "elementInfoProvider").getExtensions();
+        
+        if(Platform.inDevelopmentMode() || Platform.inDebugMode()){
+            System.out.println("ElementInfo extensions:"+tmpExtensions.length);
+        }
+        List<ElementInfoProviderExtension> l = new ArrayList<ElementInfoProviderExtension>();
+        for (int i = 0; i < tmpExtensions.length; i++) {
+            IConfigurationElement[] configElements = tmpExtensions[i].getConfigurationElements();
+            for (int j = 0; j < configElements.length; j++) {
+                ElementInfoProviderExtension ex = parseExtension(configElements[j]);
+                if (ex != null){
+                    l.add(ex);
+                }
+            }
+        }
+        extensions = l.toArray(new ElementInfoProviderExtension[l.size()]);
+        return extensions;
+    }
+
+    private static ElementInfoProviderExtension parseExtension(IConfigurationElement configElement) {
+        if (!configElement.getName().equals(PROVIDER)){
+            return null;
+        }
+        try {
+            return new ElementInfoProviderExtension(configElement);
+        } catch (Exception e) {
+        }
+        return null;
+    }
+
+    private IElementViewerInfoProvider provider = null;
+
+    private ElementInfoProviderExtension(IConfigurationElement configElement) {
+        try {
+            this.provider = (IElementViewerInfoProvider) configElement.createExecutableExtension(ATTR_CLASS);            
+        } catch (Exception e) {
+        }
+    }
+
+    private IElementViewerInfoProvider getElementViewerInfoProvider() {
+        return this.provider;
+    }
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/ElementLabelAndColorProvider.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/ElementLabelAndColorProvider.java
new file mode 100644
index 0000000..70e1775
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/ElementLabelAndColorProvider.java
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+
+package org.eclipse.actf.visualization.engines.blind.html.ui.elementViewer;
+
+import java.util.Enumeration;
+import java.util.HashSet;
+
+import org.eclipse.actf.util.ui.IElementViewerInfoProvider;
+import org.eclipse.actf.visualization.engines.blind.html.internal.util.VisualizationAttributeInfo;
+import org.eclipse.jface.viewers.IColorProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Display;
+
+
+public class ElementLabelAndColorProvider extends LabelProvider implements ITableLabelProvider, IColorProvider {
+
+    private static String CATEGORY[];
+
+    // TODO more sets
+    private static int[][] BG_COLORS = { { 153, 255, 0 }, { 51, 204, 255 }, { 255, 153, 0 }, { 255, 128, 255 },
+            { 153, 51, 255 }, { 0, 255, 153 } };
+
+    public ElementLabelAndColorProvider() {
+        // if (ParamSystem.isUseInternal()) {
+        IElementViewerInfoProvider[] providers = ElementInfoProviderExtension.getProviders();
+        HashSet<String> tmpS = new HashSet<String>();
+        for (int i = 0; i < providers.length; i++) {
+            Enumeration keys = providers[i].getCategories();
+            while (keys.hasMoreElements()) {
+                tmpS.add((String) keys.nextElement());
+            }
+        }
+        CATEGORY = new String[tmpS.size()];
+        tmpS.toArray(CATEGORY);
+    }
+
+    public Image getColumnImage(Object arg0, int arg1) {
+        return null;
+    }
+
+    public String getColumnText(Object arg0, int arg1) {
+        VisualizationAttributeInfo eleInfo = (VisualizationAttributeInfo) arg0;
+        switch (arg1) {
+        case 0:
+            return eleInfo.getCategory();
+        case 1:
+            return eleInfo.getAttributeValue();
+        case 2:
+            return eleInfo.getTagName();
+        case 3:
+            return eleInfo.getDescription();
+        }
+        return null;
+    }
+
+    public Color getForeground(Object arg0) {
+        return null;
+    }
+
+    public Color getBackground(Object arg0) {
+        VisualizationAttributeInfo eleInfo = (VisualizationAttributeInfo) arg0;
+
+        for (int i = 0; i < CATEGORY.length; i++) {
+            if (eleInfo.getCategory().equals(CATEGORY[i])) {
+                // return Display.getCurrent().getSystemColor(
+                // backColor[i % backColor.length]);
+                // System.out.println(i);
+                return new Color(Display.getCurrent(), new RGB(BG_COLORS[i % BG_COLORS.length][0], BG_COLORS[i
+                        % BG_COLORS.length][1], BG_COLORS[i % BG_COLORS.length][2]));
+            }
+        }
+        return null;
+    }
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/ElementViewerJFace.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/ElementViewerJFace.java
new file mode 100644
index 0000000..87ecf86
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/ElementViewerJFace.java
@@ -0,0 +1,340 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.html.ui.elementViewer;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.actf.model.IModelService;
+import org.eclipse.actf.model.IWebBrowserACTF;
+import org.eclipse.actf.model.ModelServiceUtils;
+import org.eclipse.actf.visualization.engines.blind.html.internal.util.VisualizationAttributeInfo;
+import org.eclipse.actf.visualization.eval.problem.HighlightTargetId;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.ui.PlatformUI;
+
+
+public class ElementViewerJFace {
+
+	private IHighlightElementListener prb;
+
+    private int[] sortModeArray;
+
+    private Composite elementViewerComposite;
+
+    private TableViewer viewer;
+
+    private TableColumn categoryCol;
+
+    private TableColumn descCol;
+
+    private final static String COL_CATEGORY = "Category";
+
+    private final static String COL_ID_STRING = "Value";
+
+    private final static String COL_TAG_NAME = "Tag Name";
+
+    private final static String COL_DESCRIPTION = "Description";
+
+    private String strHelpUrl;
+
+    public ElementViewerJFace(Composite parent, IHighlightElementListener _prb) {
+
+        prb = _prb;
+        elementViewerComposite = new Composite(parent, SWT.NULL);
+        GridLayout gridLayout = new GridLayout();
+        gridLayout.numColumns = 1;
+        elementViewerComposite.setLayout(gridLayout);
+        elementViewerComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
+        final Table table = new Table(elementViewerComposite, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL
+                | SWT.FULL_SELECTION | SWT.BORDER);
+        table.setLayoutData(new GridData(GridData.FILL_BOTH));
+        table.setHeaderVisible(true);
+        table.setLinesVisible(true);
+
+        sortModeArray = new int[4];
+        categoryCol = new TableColumn(table, SWT.LEFT);
+        categoryCol.setText(COL_CATEGORY);
+        sortModeArray[0] = 0;
+        TableColumn idCol = new TableColumn(table, SWT.LEFT);
+        idCol.setText(COL_ID_STRING);
+        idCol.setWidth(150);
+        sortModeArray[1] = 0;
+        TableColumn tagCol = new TableColumn(table, SWT.LEFT);
+        tagCol.setText(COL_TAG_NAME);
+        tagCol.setWidth(100);
+        sortModeArray[2] = 0;
+        descCol = new TableColumn(table, SWT.LEFT);
+        descCol.setText(COL_DESCRIPTION);
+        sortModeArray[3] = 0;
+
+        table.addMouseListener(new MouseAdapter() {
+            public void mouseUp(MouseEvent arg0) {
+                if (arg0.stateMask == SWT.BUTTON3) {
+                    if (table.getSelectionIndex() >= 0)
+                        openPopupMenu();
+                }
+            }
+        });
+        viewer = new TableViewer(table);
+
+        viewer.addSelectionChangedListener(new ISelectionChangedListener() {
+            public void selectionChanged(SelectionChangedEvent arg0) {
+                List list = new ArrayList();
+                for (Iterator i = ((IStructuredSelection) arg0.getSelection()).iterator(); i.hasNext();) {
+                    list.add(i.next());
+                }
+                if (list.size() > 0) {
+                    viewerSelected(list);
+                }
+            }
+        });
+
+        categoryCol.addSelectionListener(new SelectionAdapter() {
+            public void widgetSelected(SelectionEvent event) {
+                toggleCurrentSortMode(0);
+                if (sortModeArray[0] == -2) {
+                    sortByNodeId();
+                } else {
+                    viewer.setSorter(new ViewerSorter() {
+                        public int compare(Viewer iviewer, Object e1, Object e2) {
+                            int iRes;
+                            if (e1 == null) {
+                                iRes = -1;
+                            } else if (e2 == null) {
+                                iRes = 1;
+                            } else {
+                                String str1, str2;
+                                str1 = ((VisualizationAttributeInfo) e1).getCategory();
+                                str2 = ((VisualizationAttributeInfo) e2).getCategory();
+                                if (str1.equals("")) {
+                                    return 1;
+                                } else if (str2.equals("")) {
+                                    return -1;
+                                }
+                                iRes = str1.compareToIgnoreCase(str2);
+                            }
+                            return iRes * sortModeArray[0];
+                        }
+                    });
+                }
+            }
+        });
+
+        idCol.addSelectionListener(new SelectionAdapter() {
+            public void widgetSelected(SelectionEvent event) {
+                toggleCurrentSortMode(1);
+                if (sortModeArray[1] == -2) {
+                    sortByNodeId();
+                } else {
+                    viewer.setSorter(new ViewerSorter() {
+                        public int compare(Viewer iviewer, Object e1, Object e2) {
+                            int iRes;
+                            if (e1 == null) {
+                                iRes = -1;
+                            } else if (e2 == null) {
+                                iRes = 1;
+                            } else {
+                                iRes = ((VisualizationAttributeInfo) e1).getAttributeValue().compareToIgnoreCase(
+                                        ((VisualizationAttributeInfo) e2).getAttributeValue());
+                            }
+                            return iRes * sortModeArray[1];
+                        }
+                    });
+                }
+            }
+        });
+
+        tagCol.addSelectionListener(new SelectionAdapter() {
+            public void widgetSelected(SelectionEvent event) {
+                toggleCurrentSortMode(2);
+                if (sortModeArray[2] == -2) {
+                    sortByNodeId();
+                } else {
+                    viewer.setSorter(new ViewerSorter() {
+                        public int compare(Viewer iviewer, Object e1, Object e2) {
+                            int iRes;
+                            if (e1 == null) {
+                                iRes = -1;
+                            } else if (e2 == null) {
+                                iRes = 1;
+                            } else {
+                                iRes = ((VisualizationAttributeInfo) e1).getTagName().compareToIgnoreCase(
+                                        ((VisualizationAttributeInfo) e2).getTagName());
+                            }
+                            return iRes * sortModeArray[2];
+                        }
+                    });
+                }
+            }
+        });
+
+        descCol.addSelectionListener(new SelectionAdapter() {
+            public void widgetSelected(SelectionEvent event) {
+                toggleCurrentSortMode(3);
+                if (sortModeArray[3] == -2) {
+                    sortByNodeId();
+                } else {
+                    viewer.setSorter(new ViewerSorter() {
+                        public int compare(Viewer iviewer, Object e1, Object e2) {
+                            int iRes;
+                            if (e1 == null) {
+                                iRes = -1;
+                            } else if (e2 == null) {
+                                iRes = 1;
+                            } else {
+                                String str1, str2;
+                                str1 = ((VisualizationAttributeInfo) e1).getDescription();
+                                str2 = ((VisualizationAttributeInfo) e2).getDescription();
+                                if (str1.equals("")) {
+                                    return 1;
+                                } else if (str2.equals("")) {
+                                    return -1;
+                                }
+                                iRes = str1.compareToIgnoreCase(str2);
+                            }
+                            return iRes * sortModeArray[3];
+                        }
+                    });
+                }
+            }
+        });
+
+    }
+
+    private void viewerSelected(List list) {
+        prb.clearHighlight();
+        VisualizationAttributeInfo selected = null;
+
+        Vector<HighlightTargetId> tmpV = new Vector<HighlightTargetId>();
+        
+        for (int i = 0; i < list.size(); i++) {
+            selected = (VisualizationAttributeInfo) list.get(i);
+            tmpV.add(new HighlightTargetId(selected.getNodeId(),selected.getNodeId()));
+            if (i==0){
+                strHelpUrl = selected.getHelpUrl();            	
+            }else if (!strHelpUrl.equals(selected.getHelpUrl())){
+                strHelpUrl = "";
+            }
+        }
+
+        prb.highlight(tmpV);
+        
+        IModelService dataSource =ModelServiceUtils.getActiveModelService();
+        if(dataSource!=null && dataSource instanceof IWebBrowserACTF){
+            ((IWebBrowserACTF)dataSource).hightlightElementByAttribute(selected.getAttribtueName(), selected.getAttributeValue());
+        }
+        
+    }
+
+    private void toggleCurrentSortMode(int sortKind) {
+        switch (sortModeArray[sortKind]) {
+        case -2:
+            sortModeArray[sortKind] = 1;
+            break;
+        case -1:
+            sortModeArray[sortKind] = -2;
+            break;
+        case 0:
+            sortModeArray[sortKind] = 1;
+            break;
+        case 1:
+            sortModeArray[sortKind] = -1;
+            break;
+        }
+    }
+
+    private void sortByNodeId() {
+        viewer.setSorter(new ViewerSorter() {
+            public int compare(Viewer iviewer, Object e1, Object e2) {
+                int iRes;
+                if (e1 == null) {
+                    iRes = -1;
+                } else if (e2 == null) {
+                    iRes = 1;
+                } else {
+                    iRes = ((VisualizationAttributeInfo) e1).getNodeId()
+                            - ((VisualizationAttributeInfo) e2).getNodeId();
+                }
+                return iRes;
+            }
+        });
+    }
+
+    private void openPopupMenu() {
+        String[] itemName = new String[2];
+        itemName[0] = "Select";
+        itemName[1] = "View Help...";
+        boolean[] enabled = new boolean[2];
+        enabled[0] = true;
+        enabled[1] = true;
+        if (strHelpUrl.equals("")){
+            enabled[1] = false;
+        }
+        PopupMenu popupMenu = new PopupMenu(new Shell(), itemName, enabled);
+        String strRet = popupMenu.open();
+       if (strRet.equals(itemName[1])) {
+        	PlatformUI.getWorkbench().getHelpSystem().displayHelpResource(strHelpUrl);
+        }
+    }
+
+    /**
+     * @return
+     */
+    public Composite getComposite() {
+        return elementViewerComposite;
+    }
+
+    public void setContentProvider(IStructuredContentProvider contentProvider) {
+        viewer.setContentProvider(contentProvider);
+    }
+
+    public void setLabelProvider(ITableLabelProvider labelProvider) {
+        viewer.setLabelProvider(labelProvider);
+    }
+
+    public void setElementList(List eleList) {
+        viewer.setInput(eleList);
+    }
+
+    public void setCategoryColWidth(int width) {
+        categoryCol.setWidth(width);
+        if (width == 0)
+            categoryCol.setResizable(false);
+    }
+
+    public void setDescColWidth(int width) {
+        descCol.setWidth(width);
+        if (width == 0)
+            descCol.setResizable(false);
+    }
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/ElementViewerManager.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/ElementViewerManager.java
new file mode 100644
index 0000000..8646c45
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/ElementViewerManager.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.html.ui.elementViewer;
+
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.PlatformUI;
+
+public class ElementViewerManager implements IVisualizeStyleInfoListener {
+	private static ElementViewerManager INSTANCE;
+
+	private IViewerPanel viewerPanel;
+
+	private IHighlightElementListener prb;
+
+	private VisualizeStyleInfo styleInfo;
+
+	private Shell shell;
+
+	public static ElementViewerManager getInstance() {
+		if (INSTANCE == null) {
+			INSTANCE = new ElementViewerManager();
+			VisualizeStyleInfoManager.getInstance().addLisnter(INSTANCE);
+		}
+		return INSTANCE;
+	}
+
+	private ElementViewerManager() {
+		shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
+	}
+
+	public void setPartRightBlind(IHighlightElementListener prb) {
+		this.prb = prb;
+	}
+
+	public void openElementViewer() {
+		if (isExist()) {
+			viewerPanel.forceActive();
+		} else {
+			viewerPanel = new ViewerPanelJFace(shell, styleInfo, prb);
+		}
+	}
+
+	public void activateElementViewer() {
+		if (isExist()) {
+			viewerPanel.forceActive();
+		}
+	}
+
+	public void hideElementViewer() {
+		if (isExist()) {
+			viewerPanel.hide();
+		}
+	}
+
+	public void update(VisualizeStyleInfo styleInfo) {
+		this.styleInfo = styleInfo;
+		if (isExist()) {
+			viewerPanel.asyncUpdateValue(styleInfo);
+		}
+	}
+
+	private boolean isExist() {
+		return ((null != viewerPanel) && (!viewerPanel.isDisposed()));
+	}
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/IHighlightElementListener.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/IHighlightElementListener.java
new file mode 100644
index 0000000..d3b415d
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/IHighlightElementListener.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.blind.html.ui.elementViewer;
+
+import java.util.List;
+
+import org.eclipse.actf.visualization.eval.problem.HighlightTargetId;
+
+public interface IHighlightElementListener {
+	void clearHighlight();
+
+	void highlight(List<HighlightTargetId> targetIdList);
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/IViewerPanel.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/IViewerPanel.java
new file mode 100644
index 0000000..e9ee3d4
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/IViewerPanel.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.html.ui.elementViewer;
+
+import org.eclipse.actf.util.ui.IDialogConstants;
+
+public interface IViewerPanel {
+	final static String TITLE_NAME = "ID/AccessKey/Class/CSS Inspector";
+
+	final static String CLOSE_BUTTON = IDialogConstants.CLOSE;
+
+	final static String ID_TAB_TITLE = "ID";
+
+	final static String ACCESSKEY_TAB_TITLE = "AccessKey";
+
+	final static String CLASS_TAB_TITLE = "Class";
+
+	final static String CSS_TAB_TITLE = "CSS";
+
+	public abstract void asyncUpdateValue(VisualizeStyleInfo styleInfo);
+
+	public abstract void forceActive();
+
+	public abstract void hide();
+
+	public boolean isDisposed();
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/IVisualizeStyleInfoListener.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/IVisualizeStyleInfoListener.java
new file mode 100644
index 0000000..3a95ea3
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/IVisualizeStyleInfoListener.java
@@ -0,0 +1,17 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.html.ui.elementViewer;
+
+
+public interface IVisualizeStyleInfoListener {
+    void update(VisualizeStyleInfo styleInfo);
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/PopupMenu.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/PopupMenu.java
new file mode 100644
index 0000000..facd16b
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/PopupMenu.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.html.ui.elementViewer;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.Shell;
+
+public class PopupMenu {
+	private Shell shell;
+
+	private String returnCode;
+
+	private String[] itemName;
+
+	private boolean[] enableItem;
+
+	// TODO replace
+
+	public PopupMenu(Shell _shell, String[] itemName, boolean[] enable) {
+		shell = new Shell(_shell);
+		shell.setLayout(new GridLayout());
+		this.itemName = itemName;
+		this.enableItem = enable;
+	}
+
+	public String open() {
+		Menu popupMenu = new Menu(shell);
+
+		MenuItem[] item = new MenuItem[itemName.length];
+
+		for (int i = 0; i < itemName.length; i++) {
+			item[i] = new MenuItem(popupMenu, SWT.PUSH);
+			item[i].setText(itemName[i]);
+			item[i].addSelectionListener(new SelectionAdapter() {
+				public void widgetSelected(SelectionEvent event) {
+					MenuItem mItem = (MenuItem) event.getSource();
+					returnCode = mItem.getText();
+					shell.close();
+				}
+			});
+			if (enableItem[i]) {
+				item[i].setEnabled(true);
+			} else {
+				item[i].setEnabled(false);
+			}
+		}
+
+		popupMenu.setVisible(true);
+
+		Display display = shell.getDisplay();
+		while (!shell.isDisposed() || !display.readAndDispatch()) {
+			if (!display.readAndDispatch())
+				display.sleep();
+		}
+
+		return returnCode;
+	}
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/ViewerPanelJFace.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/ViewerPanelJFace.java
new file mode 100644
index 0000000..6760349
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/ViewerPanelJFace.java
@@ -0,0 +1,193 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.html.ui.elementViewer;
+
+import java.util.List;
+
+import org.eclipse.actf.mediator.Mediator;
+import org.eclipse.actf.model.IModelService;
+import org.eclipse.actf.model.IWebBrowserACTF;
+import org.eclipse.actf.visualization.engines.blind.BlindVizEnginePlugin;
+import org.eclipse.jface.viewers.ArrayContentProvider;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.TabItem;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+
+
+public class ViewerPanelJFace implements IViewerPanel {
+    private Shell shell;
+
+    private List idList;
+
+    private IHighlightElementListener prb;
+
+    private ElementViewerJFace idViewer;
+
+    private ElementViewerJFace akeyViewer;
+
+    private ElementViewerJFace classViewer;
+
+    private CSSViewer cssViewer;
+    
+    private boolean isDisposed = false;
+
+    public ViewerPanelJFace(Shell _shell, VisualizeStyleInfo styleInfo, IHighlightElementListener _prb) {
+
+        if (styleInfo == null) {
+            styleInfo = new VisualizeStyleInfo();
+            idList = null;
+        } else {
+            idList = styleInfo.getOrigIdList();
+        }
+        
+        prb = _prb;
+        shell = new Shell(_shell, SWT.MIN | SWT.MAX | SWT.RESIZE | SWT.CLOSE);
+        shell.setLayout(new GridLayout());
+
+        shell.setText(TITLE_NAME);
+        //TODO
+        shell.setImage(AbstractUIPlugin.imageDescriptorFromPlugin(BlindVizEnginePlugin.PLUGIN_ID, "icons/excla_squ.png").createImage());
+
+        shell.setLocation(100, 100);
+
+        Composite composite = new Composite(shell, SWT.NULL);
+        composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+        GridLayout gridLayout1 = new GridLayout();
+        gridLayout1.numColumns = 1;
+        composite.setLayout(gridLayout1);
+
+        TabFolder viewerFolder = new TabFolder(composite, SWT.NULL);
+        GridData gridData = new GridData(GridData.FILL_BOTH);
+        // gridData.heightHint = 300;
+        viewerFolder.setLayoutData(gridData);
+
+        TabItem tabItemEle = new TabItem(viewerFolder, SWT.NULL);
+        tabItemEle.setText(ID_TAB_TITLE);
+        idViewer = new ElementViewerJFace(viewerFolder, prb);
+
+        idViewer.setCategoryColWidth(100);
+        idViewer.setDescColWidth(0);
+        idViewer.setContentProvider(new ArrayContentProvider());
+        idViewer.setLabelProvider(new ElementLabelAndColorProvider());
+        idViewer.setElementList(idList);
+        tabItemEle.setControl(idViewer.getComposite());
+
+        TabItem tabItemAKey = new TabItem(viewerFolder, SWT.NULL);
+        tabItemAKey.setText(ACCESSKEY_TAB_TITLE);
+        akeyViewer = new ElementViewerJFace(viewerFolder, prb);
+        akeyViewer.setCategoryColWidth(0);
+        akeyViewer.setDescColWidth(150);
+        akeyViewer.setContentProvider(new ArrayContentProvider());
+        akeyViewer.setLabelProvider(new ElementLabelAndColorProvider());
+        akeyViewer.setElementList(styleInfo.getAccesskeyList());
+        tabItemAKey.setControl(akeyViewer.getComposite());
+
+        TabItem tabItemClass = new TabItem(viewerFolder, SWT.NULL);
+        tabItemClass.setText(CLASS_TAB_TITLE);
+        classViewer = new ElementViewerJFace(viewerFolder, prb);
+        classViewer.setCategoryColWidth(0);
+        classViewer.setDescColWidth(0);
+        classViewer.setContentProvider(new ArrayContentProvider());
+        classViewer.setLabelProvider(new ElementLabelAndColorProvider());
+        classViewer.setElementList(styleInfo.getClassList());
+        tabItemClass.setControl(classViewer.getComposite());
+
+        TabItem tabItemCss = new TabItem(viewerFolder, SWT.NULL);
+        tabItemCss.setText(CSS_TAB_TITLE);
+        cssViewer = new CSSViewer(viewerFolder);
+        cssViewer.setCssSet(styleInfo.getImportedCssSet());
+        tabItemCss.setControl(cssViewer.getCompositeCss());
+
+        viewerFolder.addSelectionListener(new SelectionAdapter() {
+            public void widgetSelected(SelectionEvent event) {
+                if (idList != null) {
+                    recoveryHighlight();
+                }
+            }
+        });
+
+        Button closeButton = new Button(composite, SWT.NULL);
+        closeButton.setText(CLOSE_BUTTON);
+        gridData = new GridData(GridData.HORIZONTAL_ALIGN_END);
+        closeButton.setLayoutData(gridData);
+        closeButton.addMouseListener(new MouseAdapter() {
+            public void mouseUp(MouseEvent e) {
+                shell.dispose();
+            }
+        });
+
+        //TODO move to manager?
+        shell.addDisposeListener(new DisposeListener() {
+            public void widgetDisposed(DisposeEvent arg0) {
+                if (null != idList) {
+                    recoveryHighlight();
+                }
+                //prb.setViewerPanel(null);
+                isDisposed = true;
+            }
+        });
+
+        shell.setSize(450, 420);
+
+        shell.open();
+
+    }
+    
+    private void recoveryHighlight(){
+        IModelService dataSource = Mediator.getInstance().getActiveModelService();
+        
+        if(dataSource != null &&dataSource instanceof IWebBrowserACTF){
+            ((IWebBrowserACTF)dataSource).recoveryHighlight();
+        }
+        prb.clearHighlight();
+    }
+
+    public void asyncUpdateValue(VisualizeStyleInfo styleInfo) {
+        final VisualizeStyleInfo _styleInfo = styleInfo;
+        shell.getDisplay().asyncExec(new Thread() {
+            public void run() {
+                idList = _styleInfo.getOrigIdList();
+                idViewer.setElementList(idList);
+                akeyViewer.setElementList(_styleInfo.getAccesskeyList());
+                classViewer.setElementList(_styleInfo.getClassList());
+                cssViewer.setCssSet(_styleInfo.getImportedCssSet());
+            }
+        });
+    }
+
+    public void forceActive() {
+        shell.setMinimized(false);
+        shell.setVisible(true);
+        shell.forceActive();
+    }
+
+    public void hide() {
+        shell.setVisible(false);
+    }
+
+    public boolean isDisposed() {
+        return isDisposed;
+    }
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/VisualizeStyleInfo.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/VisualizeStyleInfo.java
new file mode 100644
index 0000000..216ccc1
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/VisualizeStyleInfo.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.html.ui.elementViewer;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.actf.visualization.engines.blind.html.IVisualizeMapData;
+import org.eclipse.actf.visualization.engines.blind.html.internal.util.VisualizationAttributeInfo;
+import org.w3c.dom.Document;
+
+
+public class VisualizeStyleInfo {
+
+    private Set importedCssSet = new HashSet();
+
+    private List origIdList; //original HTML elements' ID
+
+    private List accesskeyList; //accesskey
+
+    private List classList; //class
+
+    public VisualizeStyleInfo() {
+        origIdList = new ArrayList();
+        accesskeyList = new ArrayList();
+        classList = new ArrayList();
+    }
+
+    /**
+     *  
+     */
+    public VisualizeStyleInfo(Document orig, IVisualizeMapData mapData) {
+        origIdList = VisualizationAttributeInfo.listUp(orig, mapData, "id");
+        accesskeyList = VisualizationAttributeInfo.listUp(orig, mapData, "accesskey");
+        classList = VisualizationAttributeInfo.listUp(orig, mapData, "class");
+    }
+
+    /**
+     * @return
+     */
+    public List getOrigIdList() {
+        return origIdList;
+    }
+
+    /**
+     * @return
+     */
+    public List getAccesskeyList() {
+        return accesskeyList;
+    }
+
+    /**
+     * @return
+     */
+    public List getClassList() {
+        return classList;
+    }
+
+    /**
+     * @return Returns the importedCssSet.
+     */
+    public Set getImportedCssSet() {
+        return importedCssSet;
+    }
+
+    /**
+     * @param importedCssSet
+     *            The importedCssSet to set.
+     */
+    public void setImportedCssSet(Set importedCssSet) {
+        this.importedCssSet = importedCssSet;
+    }
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/VisualizeStyleInfoManager.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/VisualizeStyleInfoManager.java
new file mode 100644
index 0000000..8cece55
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/ui/elementViewer/VisualizeStyleInfoManager.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.html.ui.elementViewer;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+
+public class VisualizeStyleInfoManager {
+	private static VisualizeStyleInfoManager INSTANCE;
+
+	private ArrayList<IVisualizeStyleInfoListener> listeners = new ArrayList<IVisualizeStyleInfoListener>();
+
+	public static VisualizeStyleInfoManager getInstance() {
+		if (INSTANCE == null) {
+			INSTANCE = new VisualizeStyleInfoManager();
+		}
+		return INSTANCE;
+	}
+
+	private VisualizeStyleInfoManager() {
+	}
+
+	public void addLisnter(IVisualizeStyleInfoListener listener) {
+		listeners.add(listener);
+	}
+
+	public boolean removeListener(IVisualizeStyleInfoListener listener) {
+		return (listeners.remove(listener));
+	}
+
+	public void fireVisualizeStyleInfoUpdate(VisualizeStyleInfo styleInfo) {
+		for (Iterator i = listeners.iterator(); i.hasNext();) {
+			((IVisualizeStyleInfoListener) i.next()).update(styleInfo);
+		}
+	}
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/util/HandleFramePage.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/util/HandleFramePage.java
new file mode 100644
index 0000000..a07581a
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/util/HandleFramePage.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.html.util;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.net.URL;
+
+import org.eclipse.actf.model.IWebBrowserACTF;
+import org.eclipse.actf.visualization.Constants;
+import org.eclipse.actf.visualization.engines.blind.BlindVizEnginePlugin;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+public class HandleFramePage {
+
+	public static boolean hasFrameset(Document document,
+			IWebBrowserACTF webBrowser) {
+
+		NodeList framesetNl = document.getElementsByTagName("frameset");
+
+		if (framesetNl.getLength() > 0) {
+
+			NodeList frameList = document.getElementsByTagName("frame");
+
+			String sFileName = BlindVizEnginePlugin.getTempDirectory()
+					+ "frameList.html";
+
+			String base = webBrowser.getURL();
+
+			try {
+				URL baseURL = new URL(base);
+
+				NodeList baseNL = document.getElementsByTagName("base");
+				if (baseNL.getLength() > 0) {
+					Element baseE = (Element) baseNL
+							.item(baseNL.getLength() - 1);
+					String baseUrlS = baseE.getAttribute("href");
+					if (baseUrlS.length() > 0) {
+						URL tmpUrl = new URL(baseURL, baseUrlS);
+						base = tmpUrl.toString();
+					}
+				}
+			} catch (Exception e) {
+			}
+
+			PrintWriter fileOutput;
+
+			try {
+				fileOutput = new PrintWriter(new OutputStreamWriter(
+						new FileOutputStream(sFileName), "UTF-8"));
+			} catch (IOException e) {
+				// e.printStackTrace();
+				// TODO
+				return true;
+			}
+
+			fileOutput.write("<html>");
+			// " lang=\""+lang+\">"); //use var
+			fileOutput.write("<head>" + Constants.LINE_SEP);
+			fileOutput
+					.write("<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\" >"
+							+ Constants.LINE_SEP);
+			fileOutput.write("<base href=\"" + base + "\"></head>"
+					+ Constants.LINE_SEP + "<body><P>");
+			fileOutput.write("This page contains of "); // var
+			fileOutput.write(String.valueOf(frameList.getLength()));
+			fileOutput.write(" frames."); // var
+			fileOutput.write("<br>" + Constants.LINE_SEP);
+			fileOutput.write("Please select one of them."); // var
+			fileOutput.write("</P>" + Constants.LINE_SEP + "<ol>"
+					+ Constants.LINE_SEP);
+
+			String strTitle, strName;
+			for (int i = 0; i < frameList.getLength(); i++) {
+				Element frameEl = (Element) frameList.item(i);
+				strTitle = frameEl.getAttribute("title");
+				strName = frameEl.getAttribute("name");
+				if (strTitle.equals(""))
+					strTitle.equals("none");
+				if (strName.equals(""))
+					strName.equals("none");
+				fileOutput.write("<li><a href=\"" + frameEl.getAttribute("src")
+						+ "\">Title: \"" + strTitle + "\".<BR> Name: \""
+						+ strName + "\".<BR> src: \""
+						+ frameEl.getAttribute("src") + "\".</a>"
+						+ Constants.LINE_SEP);
+			}
+			fileOutput.write("</ol></body></html>");
+
+			fileOutput.flush();
+			fileOutput.close();
+
+			webBrowser.navigate(sFileName);
+			return true;
+
+		} else {
+			return false;
+		}
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/util/Id2LineViaAccId.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/util/Id2LineViaAccId.java
new file mode 100644
index 0000000..54f16ca
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/util/Id2LineViaAccId.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.html.util;
+
+import java.util.Map;
+import java.util.Vector;
+
+import org.eclipse.actf.util.html2view.Html2ViewMapData;
+
+
+
+public class Id2LineViaAccId {
+    private Map id2AccId;
+
+    private Vector html2ViewMapDataV;
+
+    //TODO
+    private boolean is1base = true;
+
+    public Id2LineViaAccId(Map id2AccId, Vector html2ViewMapDataV) {
+        this(id2AccId, html2ViewMapDataV, true);
+    }
+
+    public Id2LineViaAccId(Map id2AccId, Vector html2ViewMapDataV, boolean is1base) {
+        this.id2AccId = id2AccId;
+        this.html2ViewMapDataV = html2ViewMapDataV;
+        this.is1base = is1base;
+    }
+
+    public int getLine(int nodeId) {
+        int result = -1;
+        Integer id = new Integer(nodeId);
+
+        if (id2AccId.containsKey(id)) {
+            int accId = ((Integer) id2AccId.get(id)).intValue();
+            if (accId > -1 && accId < html2ViewMapDataV.size()) {
+                Html2ViewMapData tmpData = (Html2ViewMapData) html2ViewMapDataV.get(accId);
+                result = tmpData.getStartLine();//? +1 ?
+            }
+        }
+
+        return (result);
+    }
+
+    public Html2ViewMapData getViewMapData(int nodeId) {
+        return (getViewMapData(new Integer(nodeId)));
+    }
+
+    public Html2ViewMapData getViewMapData(Integer nodeId) {
+        Html2ViewMapData result = null;
+        if (id2AccId.containsKey(nodeId)) {
+            int accId = ((Integer) id2AccId.get(nodeId)).intValue();
+            if (accId > -1 && accId < html2ViewMapDataV.size()) {
+                result = (Html2ViewMapData) html2ViewMapDataV.get(accId);
+            }
+        }
+        return (result);
+    }
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/util/ODFVisualizeViewUtil.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/util/ODFVisualizeViewUtil.java
new file mode 100644
index 0000000..cca8ba7
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/util/ODFVisualizeViewUtil.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Tatsuya ISHIHARA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.html.util;
+
+import java.util.List;
+
+import org.eclipse.actf.util.html2view.Html2ViewMapData;
+import org.eclipse.actf.util.xpath.XPathUtil;
+import org.eclipse.actf.visualization.engines.blind.html.VisualizeEngine;
+import org.eclipse.actf.visualization.eval.problem.IProblemItem;
+import org.eclipse.actf.visualization.eval.problem.ProblemItemImpl;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class ODFVisualizeViewUtil {
+	public static void visualizeError(Document resultDoc, List problems) {
+		final String NO_ALT_IMAGE = "10101";
+
+		int size = problems.size();
+
+		for (int i = 0; i < size; i++) {
+			Object obj = problems.get(i);
+			if (obj instanceof ProblemItemImpl) {
+				ProblemItemImpl prob = (ProblemItemImpl) obj;
+				if (prob.getId().equals("O_" + NO_ALT_IMAGE)) {
+					Element imageElem = (Element) prob.getTargetNode();
+					if (imageElem != null) {
+						Element frameElem = (Element) imageElem.getParentNode();
+						String idS = frameElem
+								.getAttribute(Html2ViewMapData.ACTF_ID);
+						if (idS.length() > 0) {
+							Integer idObj = new Integer(idS);
+							NodeList nl = XPathUtil.evalXPathNodeList(resultDoc
+									.getDocumentElement(), "//*[@"
+									+ Html2ViewMapData.ACTF_ID + "='" + idObj
+									+ "']/span");
+							if ((nl != null) && (nl.getLength() == 1)) {
+								Element frameElemResultDoc = (Element) nl
+										.item(0);
+								Element img = createErrorImageElement(
+										frameElemResultDoc, prob, idObj);
+								frameElemResultDoc.appendChild(img);
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+
+	private static Element createErrorImageElement(Node target,
+			IProblemItem prob, Integer idObj) {
+		Element img = target.getOwnerDocument().createElement("img");
+		img.setAttribute("alt", "error icon");
+		img.setAttribute("title", prob.getDescription());
+		img.setAttribute("onmouseover", "updateBaloon('id" + idObj + "');");
+		img.setAttribute("src", "img/" + VisualizeEngine.ERROR_ICON_NAME);
+		return (img);
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/util/SaveReportBlind.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/util/SaveReportBlind.java
new file mode 100644
index 0000000..c0f3521
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/util/SaveReportBlind.java
@@ -0,0 +1,405 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.html.util;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.util.List;
+
+import org.eclipse.actf.model.dom.html.impl.SHDocument;
+import org.eclipse.actf.model.dom.html.util.HtmlParserUtil;
+import org.eclipse.actf.util.FileUtils;
+import org.eclipse.actf.visualization.Constants;
+import org.eclipse.actf.visualization.engines.blind.BlindVizEnginePlugin;
+import org.eclipse.actf.visualization.engines.blind.eval.PageEvaluation;
+import org.eclipse.actf.visualization.engines.blind.util.BlindVizResourceUtil;
+import org.eclipse.actf.visualization.eval.EvaluationPreferencesUtil;
+import org.eclipse.actf.visualization.eval.IEvaluationItem;
+import org.eclipse.actf.visualization.eval.IEvaluationResult;
+import org.eclipse.actf.visualization.eval.guideline.GuidelineData;
+import org.eclipse.actf.visualization.eval.guideline.GuidelineHolder;
+import org.eclipse.actf.visualization.eval.problem.HighlightTargetId;
+import org.eclipse.actf.visualization.eval.problem.IProblemItem;
+import org.eclipse.actf.visualization.eval.problem.ProblemConst;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+
+public class SaveReportBlind {
+
+	private static final String[] ICON_NAMES = { "Err.png", "Warn.png",
+			"Info.png" };
+
+	// moved from PartRightBlind
+	// TODO renew
+
+	// TODO include only selected guideline/metrics
+
+	public static void saveReport(Document result,
+			IEvaluationResult checkResult, String sFileName,
+			String imageBriefDir, String maxTime, PageEvaluation pageEval,
+			// String strUrl,
+			boolean bAccessory) {
+		String saveDir = sFileName.substring(0, sFileName
+				.lastIndexOf(File.separator) + 1);
+		String imageDir = saveDir + imageBriefDir;
+		File fDir = new File(imageDir);
+		if ((!fDir.isDirectory() || !fDir.canWrite()) && !fDir.mkdirs()) {
+			System.err.println("can't create image dir:" + imageDir);
+		}
+
+		String preName = sFileName.substring(sFileName
+				.lastIndexOf(File.separator) + 1, sFileName.lastIndexOf("."));
+		String scriptVariantName = preName + "_variant.js";
+		String reportImgSaveName = preName + ".png";
+
+		String variantFileS = "variant.js";
+
+		if (bAccessory) {
+			BlindVizResourceUtil.saveImages(imageDir);
+			BlindVizResourceUtil.saveScripts(imageDir);
+
+			File[] assFiles = checkResult.getAssociateFiles();
+
+			for (File target : assFiles) {
+				if (target.getName().startsWith("variant")
+						&& target.getName().endsWith(".js")) {
+					FileUtils.copyFile(target, imageDir + scriptVariantName,
+							true);
+					variantFileS = target.getName();
+				} else {
+					FileUtils.copyFile(target, imageDir + target.getName(),
+							true);
+
+				}
+			}
+
+			PrintWriter pw;
+			try {
+				pw = new PrintWriter(
+						new OutputStreamWriter(new FileOutputStream(imageDir
+								+ scriptVariantName, true), "UTF-8"));
+				pw.write("var acc_imageDir = '" + imageBriefDir + "'; ");
+				pw.flush();
+				pw.close();
+			} catch (IOException e) {
+				// e.printStackTrace();
+			}
+
+			FileUtils.copyFile(new File(BlindVizEnginePlugin.getTempDirectory(),
+					"pagerating.png"), imageDir + reportImgSaveName, true);
+
+		}
+
+		IProblemItem[] problemTableBlindDisplayItemArray = new IProblemItem[0];
+		if (checkResult != null) {
+			List<IProblemItem> tmpList = checkResult.getProblemList();
+			problemTableBlindDisplayItemArray = new IProblemItem[tmpList.size()];
+			try {
+				tmpList.toArray(problemTableBlindDisplayItemArray);
+			} catch (Exception e) {
+			}
+
+		}
+
+		// img/highlight.js -> <imageBriefDir>highlight.js
+		String strAtt;
+		NodeList nl = result.getElementsByTagName("script");
+		for (int i = 0; i < nl.getLength(); i++) {
+			Element el = (Element) nl.item(i);
+			strAtt = el.getAttribute("src");
+			if (strAtt.indexOf("img/") == 0) {
+				el.setAttribute("src", imageBriefDir + strAtt.substring(4));
+				el.getParentNode().removeChild(el);
+			} else if (strAtt.indexOf(variantFileS) >= 0) {
+				el.setAttribute("src", imageBriefDir + scriptVariantName);
+			}
+		}
+
+		// set variable acc_imageDir
+		nl = result.getElementsByTagName("head");
+		if (nl.getLength() > 0) {
+			Element el = (Element) nl.item(0);
+			// Element script = result.createElement("script");
+			// el.appendChild(script);
+			// script.appendChild(result.createTextNode("var acc_imageDir = '"
+			// + imageBriefDir + "'; "));
+
+			Element newEle = result.createElement("script");
+			StringBuffer buffer = new StringBuffer();
+			buffer
+					.append(Constants.LINE_SEP
+							+ "if(navigator.appName.toLowerCase().indexOf(\"microsoft\")>=0){"
+							+ Constants.LINE_SEP);
+			buffer.append("jsFile=\"highlight.js\";" + Constants.LINE_SEP);
+			buffer.append("}else{" + Constants.LINE_SEP);
+			buffer.append("jsFile=\"highlight_moz.js\";" + Constants.LINE_SEP);
+			buffer.append("}" + Constants.LINE_SEP);
+			buffer
+					.append("document.write(\"<script src=\"+acc_imageDir+jsFile+\"></script>\");"
+							+ Constants.LINE_SEP);
+			newEle.appendChild(result.createComment(buffer.toString()));
+			el.appendChild(newEle);
+		}
+
+		// img/<*.gif> -> <imageBriefDir><*.gif>
+		nl = result.getElementsByTagName("img");
+		for (int i = 0; i < nl.getLength(); i++) {
+			Element img = (Element) nl.item(i);
+			strAtt = img.getAttribute("src");
+			if (strAtt.indexOf("img/") == 0)
+				img.setAttribute("src", imageBriefDir + strAtt.substring(4));
+		}
+
+		// img/<*.gif> -> <imageBriefDir><*.gif>
+		nl = result.getElementsByTagName("input");
+		for (int i = 0; i < nl.getLength(); i++) {
+			Element el = (Element) nl.item(i);
+			strAtt = el.getAttribute("src");
+			if (strAtt.indexOf("img/") == 0)
+				el.setAttribute("src", imageBriefDir + strAtt.substring(4));
+		}
+
+		// create problem table
+		NodeList body = result.getElementsByTagName("body");
+		if (body.getLength() > 0) {
+			// Element lastBody = (Element) body.item(body.getLength() - 1);
+			Element lastBody = (Element) body.item(0);
+
+			// report image
+			Element tmpElement = result.createElement("hr");
+			lastBody.insertBefore(tmpElement, lastBody.getFirstChild());
+
+			Element tmpDiv = result.createElement("div");
+			tmpDiv
+					.setAttribute("style",
+							"width: 100%; background-color:white;");
+
+			tmpElement = result.createElement("div");
+			// tmpElement.setAttribute("style", "float: left; width: 45%;");
+
+			// TODO
+			int count = 0;
+			boolean enabledMetrics[] = GuidelineHolder.getInstance()
+					.getMatchedMetrics();
+			for (int i = 0; i < enabledMetrics.length; i++) {
+				if (enabledMetrics[i]) {
+					count++;
+				}
+			}
+			if (count > 2) {
+				Element tmpImg = result.createElement("img");
+				tmpImg.setAttribute("src", imageBriefDir + reportImgSaveName);
+				tmpImg.setAttribute("alt", "");
+				tmpElement.appendChild(tmpImg);
+			}
+			tmpDiv.appendChild(tmpElement);
+
+			tmpElement = result.createElement("div");
+			// tmpElement.setAttribute("style", "float: right; width: 50%;");
+			VisualizeReportUtil.appendRatingTableAndTitle(pageEval,
+					imageBriefDir, result, tmpElement);
+			tmpDiv.appendChild(tmpElement);
+
+			lastBody.insertBefore(tmpDiv, lastBody.getFirstChild());
+
+			tmpElement = result.createElement("hr");
+			lastBody.insertBefore(tmpElement, lastBody.getFirstChild());
+
+			// logo image
+			tmpElement = result.createElement("div");
+			tmpElement.setAttribute("style", "background-color:white;");
+			tmpElement.setAttribute("align", "right");
+			Element tmpImg = result.createElement("img");
+			tmpImg.setAttribute("src", imageBriefDir + "logo.gif");
+			// tmpImg.setAttribute("style", "float:right;");
+			tmpImg.setAttribute("alt", "");
+			tmpElement.appendChild(tmpImg);
+			lastBody.insertBefore(tmpElement, lastBody.getFirstChild());
+
+			Element pElement = result.createElement("p");
+			// pElement.appendChild(result.createTextNode("&nbsp"));
+			lastBody.appendChild(pElement);
+			Element tableElement = result.createElement("table");
+			tableElement.setAttribute("border", "1");
+			tableElement.setAttribute("style", "background-color:white;");
+			lastBody.appendChild(tableElement);
+			Element trElement = result.createElement("tr");
+			tableElement.appendChild(trElement);
+			Element tdElement = result.createElement("th");
+			tdElement.appendChild(result
+					.createTextNode(ProblemConst.TITLE_ICON));
+			trElement.appendChild(tdElement);
+
+			if (EvaluationPreferencesUtil.isOriginalDOM()) {
+				tdElement = result.createElement("th");
+				tdElement.appendChild(result
+						.createTextNode(ProblemConst.TITLE_LINE));
+				trElement.appendChild(tdElement);
+			}
+
+			GuidelineData[] guidelineDataArray = GuidelineHolder
+					.getInstance().getGuidelineData();
+			for (int i = 0; i < guidelineDataArray.length; i++) {
+				GuidelineData data = guidelineDataArray[i];
+				if (data.isMatched()) {
+					tdElement = result.createElement("th");
+					tdElement.appendChild(result.createTextNode(data
+							.getGuidelineName()));
+					trElement.appendChild(tdElement);
+				}
+			}
+
+			tdElement = result.createElement("th");
+			tdElement.appendChild(result
+					.createTextNode(ProblemConst.TITLE_DESCRIPTION));
+			trElement.appendChild(tdElement);
+
+			// int iconId; //TODO
+			IProblemItem current;
+			for (int i = 0; i < problemTableBlindDisplayItemArray.length; i++) {
+
+				current = problemTableBlindDisplayItemArray[i];
+
+				// iconId = current.getIconId();
+
+				// iError[iconId]++;
+
+				trElement = result.createElement("tr");
+
+				// for highlight(kentarou:031113)
+				trElement.setAttribute("onClick",
+						"clearTrHighlight();clearHighlight()");
+				if (current.isCanHighlight()) {
+
+					HighlightTargetId[] targets = current
+							.getHighlightTargetIds();
+					int length = targets.length;
+
+					String strSet = "";
+					if (length == 1) {
+						strSet = "setHighlight(" + targets[0].getStartId()
+								+ "," + targets[0].getEndId() + ");";
+					} else if (length > 1) {
+						StringBuffer strStart = new StringBuffer(2048);
+						StringBuffer strEnd = new StringBuffer(2048);
+						strStart.append(targets[0].getStartId());
+						strEnd.append(targets[0].getEndId());
+						for (int j = 1; j < length; j++) {
+							strStart.append("," + targets[j].getStartId());
+							strEnd.append("," + targets[j].getEndId());
+						}
+						strSet = "setHighlight2(new Array("
+								+ strStart.toString() + "), new Array("
+								+ strEnd.toString() + "));";
+					}
+
+					trElement.setAttribute("onclick",
+							"highlightTr(this);clearHighlight();" + strSet);
+					trElement.setAttribute("STYLE",
+							"COLOR:blue;TEXT-DECORATION:underline");
+					// (
+				}
+
+				tableElement.appendChild(trElement);
+				tdElement = result.createElement("td");
+				trElement.appendChild(tdElement);
+
+				if (current.isCanHighlight()) {
+					Element imgElement = result.createElement("img");
+
+					// TODO
+					String imgName = "star.gif";
+
+					imgElement.setAttribute("src", imageBriefDir + imgName);
+					imgElement.setAttribute("alt", "");// TODO
+					tdElement.appendChild(imgElement);
+				}
+
+				String altS = current.getSeverityStr();
+				String imgName = getIconName(current.getSeverity());
+
+				if (imgName.length() > 0) {
+					Element imgElement = result.createElement("img");
+					imgElement.setAttribute("src", imageBriefDir + imgName);
+					imgElement.setAttribute("alt", altS);
+					tdElement.appendChild(imgElement);
+				}
+
+				if (EvaluationPreferencesUtil.isOriginalDOM()) {
+					tdElement = result.createElement("td");
+					String sTmp = current.getLineStrMulti();
+					if (sTmp != null && !sTmp.equals("")) {
+						tdElement.appendChild(result.createTextNode(sTmp));
+					} else {
+						tdElement.appendChild(result.createTextNode("-"));
+					}
+					trElement.appendChild(tdElement);
+				}
+
+				String[] guidelines = current.getTableDataGuideline();
+
+				for (int j = 0; j < guidelines.length; j++) {
+					if (guidelineDataArray[j].isMatched()) {
+						tdElement = result.createElement("td");
+						String sTmp = guidelines[j];
+						if (sTmp != null && !sTmp.equals(""))
+							tdElement.appendChild(result.createTextNode(sTmp));
+						else
+							tdElement.appendChild(result.createTextNode("-"));
+
+						trElement.appendChild(tdElement);
+					}
+				}
+
+				tdElement = result.createElement("td");
+				String desc = current.getDescription();
+				desc = desc.replaceAll("<", "&lt;");
+				desc = desc.replaceAll(">", "&gt;");
+
+				tdElement.appendChild(result.createTextNode(desc));
+
+				trElement.appendChild(tdElement);
+
+			}
+
+			trElement = result.createElement("tr");
+			body.item(body.getLength() - 1).appendChild(trElement);
+			tdElement = result.createElement("td");
+			tdElement.appendChild(result.createTextNode(maxTime));
+			trElement.appendChild(tdElement);
+		}
+
+		HtmlParserUtil.saveHtmlDocumentAsUTF8((SHDocument) result,
+				BlindVizEnginePlugin.getTempDirectoryString() + "saveResultTmp.html",
+				sFileName);
+
+	}
+
+	private static String getIconName(int id) {
+		switch (id) {
+		case IEvaluationItem.SEV_ERROR:
+			return ICON_NAMES[0];
+		case IEvaluationItem.SEV_WARNING:
+			return ICON_NAMES[1];
+		case IEvaluationItem.SEV_INFO:
+			return ICON_NAMES[2];
+		default:
+			return "";
+		}
+	}
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/util/VisualizeReportUtil.java b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/util/VisualizeReportUtil.java
new file mode 100644
index 0000000..f1d0867
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind.html/src/org/eclipse/actf/visualization/engines/blind/html/util/VisualizeReportUtil.java
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.html.util;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStreamWriter;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.eclipse.actf.visualization.engines.blind.eval.PageEvaluation;
+import org.eclipse.actf.visualization.eval.guideline.GuidelineHolder;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+
+
+public class VisualizeReportUtil {
+
+    // move from VisualizeEngine
+
+    public static void createReport(File targetFile, PageEvaluation pageEval) {
+        try {
+            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+            DocumentBuilder builder = factory.newDocumentBuilder();
+            DOMImplementation domImpl = builder.getDOMImplementation();
+            Document document = domImpl.createDocument("", "html", null);
+
+            Node rootN = document.getDocumentElement();
+
+            Element head = document.createElement("head");
+            Element meta = document.createElement("meta");
+            meta.setAttribute("http-equiv", "Content-type");
+            meta.setAttribute("content", "text/html; charset=UTF-8");
+            head.appendChild(meta);
+            Element title = document.createElement("title");
+            title.appendChild(document.createTextNode("Overall rating"));
+            head.appendChild(title);
+            rootN.appendChild(head);
+
+            Element body = document.createElement("body");
+            rootN.appendChild(body);
+
+            Element div = document.createElement("div");
+            Element starImg = document.createElement("img");
+            starImg.setAttribute("src", "img/" + pageEval.getRatingIcon());
+            starImg.setAttribute("alt", "");
+            div.appendChild(starImg);
+
+            //for not svg util
+            Element b = document.createElement("b");
+            b.appendChild(document.createTextNode(//"Page Rating: " +
+                    " " + pageEval.getOverallRating()));
+            div.appendChild(b);
+            //p.appendChild(document.createElement("br"));
+            body.appendChild(div);
+
+            //TODO temp
+            int count = 0;
+            boolean enabledMetrics[] = GuidelineHolder.getInstance().getMatchedMetrics();
+            for (int i = 0; i < enabledMetrics.length; i++) {
+                if (enabledMetrics[i]) {
+                    count++;
+                }
+            }
+            if (count > 2) {
+                Element img = document.createElement("img");
+                img.setAttribute("src", "./pagerating.png");
+                img.setAttribute("alt", "");
+                body.appendChild(img);
+            }
+
+            body.appendChild(document.createElement("hr"));
+
+            appendRatingTable(pageEval.getAllResult(), document, body);
+
+            TransformerFactory transFactory = TransformerFactory.newInstance();
+            Transformer transformer = transFactory.newTransformer();
+            DOMSource source = new DOMSource(document);
+            FileOutputStream os = new FileOutputStream(targetFile);
+            OutputStreamWriter osw = new OutputStreamWriter(os, "UTF-8");
+            StreamResult result = new StreamResult(osw);
+            transformer.transform(source, result);
+            osw.close();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    public static void appendRatingTableAndTitle(PageEvaluation pageEval, String imageBriefDir, Document document,
+            Node target) {
+
+        String[] ratingStr = pageEval.getAllResult();
+
+        Element p = document.createElement("div");
+        Element img = document.createElement("img");
+        img.setAttribute("src", imageBriefDir + pageEval.getRatingIcon());
+        img.setAttribute("alt", "");
+        p.appendChild(img);
+
+        Element b = document.createElement("b");
+        b.appendChild(document.createTextNode(ratingStr[0] + ": " + ratingStr[1]));
+        p.appendChild(b);
+        target.appendChild(p);
+
+        appendRatingTable(ratingStr, document, target);
+
+    }
+
+    private static void appendRatingTable(String[] ratingStr, Document document, Node target) {
+        Element table = document.createElement("table");
+        table.setAttribute("border", "1");
+        Element tr = document.createElement("tr");
+        Element th = document.createElement("th");
+        th.appendChild(document.createTextNode("evaluation"));
+        tr.appendChild(th);
+        th = document.createElement("th");
+        th.appendChild(document.createTextNode("score"));
+        tr.appendChild(th);
+        table.appendChild(tr);
+
+        int size = ratingStr.length / 2;
+
+        for (int i = 1; i < size; i++) {
+            tr = document.createElement("tr");
+            Element td = document.createElement("td");
+            td.appendChild(document.createTextNode(ratingStr[i * 2]));
+            tr.appendChild(td);
+            td = document.createElement("td");
+            td.appendChild(document.createTextNode(ratingStr[i * 2 + 1]));
+            tr.appendChild(td);
+            table.appendChild(tr);
+        }
+        target.appendChild(table);
+    }
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/.classpath b/plugins/org.eclipse.actf.visualization.engines.blind/.classpath
new file mode 100644
index 0000000..751c8f2
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/.cvsignore b/plugins/org.eclipse.actf.visualization.engines.blind/.cvsignore
new file mode 100644
index 0000000..ba077a4
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/.cvsignore
@@ -0,0 +1 @@
+bin
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/.project b/plugins/org.eclipse.actf.visualization.engines.blind/.project
new file mode 100644
index 0000000..ec2df9c
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.actf.visualization.engines.blind</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/META-INF/MANIFEST.MF b/plugins/org.eclipse.actf.visualization.engines.blind/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..92b2adc
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/META-INF/MANIFEST.MF
@@ -0,0 +1,20 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Eclipse ACTF Blind Visualization Engine Plug-in (Incubation)
+Bundle-SymbolicName: org.eclipse.actf.visualization.engines.blind;singleton:=true
+Bundle-Version: 0.0.1
+Bundle-Activator: org.eclipse.actf.visualization.engines.blind.BlindVizEnginePlugin
+Bundle-Vendor: Eclipse.org
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.actf.common,
+ org.eclipse.actf.model.dom.html,
+ org.eclipse.actf.visualization.eval,
+ org.eclipse.actf.visualization.engines.voicebrowser,
+ org.eclipse.actf.visualization.ui.report
+Eclipse-LazyStart: true
+Export-Package: org.eclipse.actf.visualization.engines.blind,
+ org.eclipse.actf.visualization.engines.blind.eval,
+ org.eclipse.actf.visualization.engines.blind.ui.actions,
+ org.eclipse.actf.visualization.engines.blind.util
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/about.html b/plugins/org.eclipse.actf.visualization.engines.blind/about.html
new file mode 100644
index 0000000..481dbcf
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/about.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>June 5, 2006</p>	
+<h3>License</h3>
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;).  
+Unless otherwise indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;).  A copy of the EPL is available 
+at <a href="http://www.eclipse.org/org/documents/epl-v10.php">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is 
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content.  Check the Redistributor&rsquo;s license 
+that was provided with the Content.  If no such license exists, contact the Redistributor.  Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/build.properties b/plugins/org.eclipse.actf.visualization.engines.blind/build.properties
new file mode 100644
index 0000000..5e8a108
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/build.properties
@@ -0,0 +1,21 @@
+###############################################################################
+# Copyright (c) 2007, 2008 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#     IBM Corporation - initial API and implementation
+###############################################################################
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               about.html,\
+               .,\
+               config/,\
+               vizResources/,\
+               plugin.xml,\
+               plugin_ja.properties,\
+               plugin.properties,\
+               icons/
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/config/altText.properties b/plugins/org.eclipse.actf.visualization.engines.blind/config/altText.properties
new file mode 100644
index 0000000..3966e76
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/config/altText.properties
@@ -0,0 +1,65 @@
+###############################################################################
+# Copyright (c) 2007, 2008 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#     IBM Corporation - initial API and implementation
+###############################################################################
+#
+# inappropriate ALT text list
+#
+blindViz.inappropriateAlt_0 = spacer gif
+blindViz.inappropriateAlt_1 = spacer.gif
+blindViz.inappropriateAlt_2 = spacer
+blindViz.inappropriateAlt_3 = space
+blindViz.inappropriateAlt_4 = blank
+blindViz.inappropriateAlt_5 = click here
+blindViz.inappropriateAlt_6 = clickhere
+blindViz.inappropriateAlt_7 = click here!
+blindViz.inappropriateAlt_8 = null
+blindViz.inappropriateAlt_9 = void
+blindViz.inappropriateAlt_10 = banner
+blindViz.inappropriateAlt_11 = line
+blindViz.inappropriateAlt_12 = dashline
+blindViz.inappropriateAlt_13 = space
+blindViz.inappropriateAlt_14 = image
+blindViz.inappropriateAlt_15 = gif
+blindViz.inappropriateAlt_16 = gif image
+blindViz.inappropriateAlt_17 = jpeg
+blindViz.inappropriateAlt_18 = jpeg image
+blindViz.inappropriateAlt_19 = photo
+blindViz.inappropriateAlt_20 = bullet
+blindViz.inappropriateAlt_21 = icon
+
+#
+# possibly inappropriate ALT text list
+#  To avoide to list "foo's image/photo", we do not include image/photo
+#
+blindViz.possible_inappAlt_0 =spacer
+blindViz.possible_inappAlt_1 =space
+blindViz.possible_inappAlt_2 =blank
+blindViz.possible_inappAlt_3 =null
+blindViz.possible_inappAlt_4 =void
+blindViz.possible_inappAlt_5 =banner
+blindViz.possible_inappAlt_6 =line
+blindViz.possible_inappAlt_7 =dashline
+blindViz.possible_inappAlt_8 =space
+blindViz.possible_inappAlt_9 =gif
+blindViz.possible_inappAlt_10 =jpeg
+blindViz.possible_inappAlt_11 =bullet
+blindViz.possible_inappAlt_12 =shade
+blindViz.possible_inappAlt_13 =star
+blindViz.possible_inappAlt_14 =bar
+blindViz.possible_inappAlt_15 =icon
+  
+blindViz.possible_inappAlt_16 =\u5f71
+blindViz.possible_inappAlt_17 =\u70b9
+blindViz.possible_inappAlt_18 =\u7a7a\u767d
+blindViz.possible_inappAlt_19 =\u7dda
+blindViz.possible_inappAlt_20 =\u753b\u50cf
+blindViz.possible_inappAlt_21 =\u5199\u771f
+blindViz.possible_inappAlt_22 =\u30d0\u30ca\u30fc
+blindViz.possible_inappAlt_23 =\u30a2\u30a4\u30b3\u30f3
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/icons/ButtonIdCss.png b/plugins/org.eclipse.actf.visualization.engines.blind/icons/ButtonIdCss.png
new file mode 100644
index 0000000..10ba184
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/icons/ButtonIdCss.png
Binary files differ
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/icons/ButtonSave.png b/plugins/org.eclipse.actf.visualization.engines.blind/icons/ButtonSave.png
new file mode 100644
index 0000000..0b6a471
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/icons/ButtonSave.png
Binary files differ
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/icons/excla_squ.png b/plugins/org.eclipse.actf.visualization.engines.blind/icons/excla_squ.png
new file mode 100644
index 0000000..b8983c5
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/icons/excla_squ.png
Binary files differ
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/icons/setting.png b/plugins/org.eclipse.actf.visualization.engines.blind/icons/setting.png
new file mode 100644
index 0000000..e493c47
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/icons/setting.png
Binary files differ
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/icons/visualize.png b/plugins/org.eclipse.actf.visualization.engines.blind/icons/visualize.png
new file mode 100644
index 0000000..d2a250b
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/icons/visualize.png
Binary files differ
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/icons/visualize_A.png b/plugins/org.eclipse.actf.visualization.engines.blind/icons/visualize_A.png
new file mode 100644
index 0000000..a09229f
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/icons/visualize_A.png
Binary files differ
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/plugin.properties b/plugins/org.eclipse.actf.visualization.engines.blind/plugin.properties
new file mode 100644
index 0000000..50f1b38
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/plugin.properties
@@ -0,0 +1,11 @@
+###############################################################################
+# Copyright (c) 2007, 2008 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#     IBM Corporation - initial API and implementation
+###############################################################################
+adesigner.preferences.blind.title=Blind Usability Visualization
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/plugin.xml b/plugins/org.eclipse.actf.visualization.engines.blind/plugin.xml
new file mode 100644
index 0000000..0042b3f
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/plugin.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.2"?>
+<plugin>
+  <extension
+        point="org.eclipse.ui.preferencePages">
+     <page
+           class="org.eclipse.actf.visualization.engines.blind.ui.preferences.BlindPreferencePage"
+           id="org.eclipse.actf.visualization.engines.blind.ui.preferences.BlindPreferencePage"
+           name="%adesigner.preferences.blind.title"/>
+  </extension>
+   <extension
+         point="org.eclipse.core.runtime.preferences">
+      <initializer class="org.eclipse.actf.visualization.engines.blind.ui.preferences.PreferenceInitializer"/>
+   </extension>
+</plugin>
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/plugin_ja.properties b/plugins/org.eclipse.actf.visualization.engines.blind/plugin_ja.properties
new file mode 100644
index 0000000..b6955bd
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/plugin_ja.properties
@@ -0,0 +1,11 @@
+###############################################################################
+# Copyright (c) 2007, 2008 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#     IBM Corporation - initial API and implementation
+###############################################################################
+adesigner.preferences.blind.title=\u97f3\u58f0\u30e6\u30fc\u30b6\u30d3\u30ea\u30c6\u30a3\u8996\u899a\u5316
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/BlindVizEnginePlugin.java b/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/BlindVizEnginePlugin.java
new file mode 100644
index 0000000..5ac24b3
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/BlindVizEnginePlugin.java
@@ -0,0 +1,143 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+
+import org.eclipse.actf.util.FileUtils;
+import org.eclipse.actf.visualization.engines.blind.ui.preferences.IBlindPreferenceConstants;
+import org.eclipse.actf.visualization.engines.blind.util.BlindVizResourceUtil;
+import org.eclipse.actf.visualization.engines.blind.util.TextChecker;
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class BlindVizEnginePlugin extends AbstractUIPlugin {
+
+	// The plug-in ID
+	public static final String PLUGIN_ID = "org.eclipse.actf.visualization.engines.blind";
+
+	// The shared instance
+	private static BlindVizEnginePlugin plugin;
+
+	private static File tmpDir = null;
+
+	/**
+	 * The constructor
+	 */
+	public BlindVizEnginePlugin() {
+		plugin = this;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+	 */
+	public void start(BundleContext context) throws Exception {
+		super.start(context);
+		if (!getPluginPreferences().getBoolean(
+				IBlindPreferenceConstants.NOT_FIRST_TIME)) {
+			TextChecker.getInstance();
+		}
+
+		createTempDirectory();
+		String tmpS;
+		if (tmpDir != null) {
+			tmpS = tmpDir.getAbsolutePath() + File.separator + "img";
+			if (FileUtils.isAvailableDirectory(tmpS)) {
+				String tmpS2 = tmpS + File.separator;
+				BlindVizResourceUtil.saveImages(tmpS2);
+				BlindVizResourceUtil.saveScripts(tmpS2);
+			}
+		}
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+	 */
+	public void stop(BundleContext context) throws Exception {
+		getPluginPreferences().setValue(
+				IBlindPreferenceConstants.NOT_FIRST_TIME, true);
+		plugin = null;
+		super.stop(context);
+
+		if (tmpDir != null) {
+			FileUtils.deleteFiles(tmpDir);
+		}
+	}
+
+	/**
+	 * Returns the shared instance
+	 * 
+	 * @return the shared instance
+	 */
+	public static BlindVizEnginePlugin getDefault() {
+		return plugin;
+	}
+
+	public String getConfigDir() {
+		try {
+			URL url = plugin.getBundle().getEntry("config");
+			url = FileLocator.resolve(url);
+			return new Path(url.getPath()).makeAbsolute().toOSString();
+		} catch (IOException ioe) {
+			ioe.printStackTrace();
+			return "";
+		}
+	}
+
+	private static void createTempDirectory() {
+		if (tmpDir == null) {
+			String tmpS = plugin.getStateLocation().toOSString()
+					+ File.separator + "tmp";
+			if (FileUtils.isAvailableDirectory(tmpS)) {
+				tmpDir = new File(tmpS);
+			} else {
+				System.err.println(PLUGIN_ID + " : can't create tmp Directory");
+				tmpDir = new File(System.getProperty("java.io.tmpdir"));
+			}
+		}
+	}
+
+	public static File createTempFile(String prefix, String suffix)
+			throws Exception {
+		createTempDirectory();
+		return (File.createTempFile(prefix, suffix, tmpDir));
+	}
+
+	public static File getTempDirectory() {
+		if (tmpDir == null) {
+			createTempDirectory();
+		}
+		return tmpDir;
+	}
+	
+	// TODO use creteTempFile
+	public static String getTempDirectoryString() {
+		if (getTempDirectory() == null) {
+			createTempDirectory();
+		}
+		return getTempDirectory().getAbsolutePath() + File.separator;
+	}
+	
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/eval/EvaluationResultBlind.java b/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/eval/EvaluationResultBlind.java
new file mode 100644
index 0000000..57cfdae
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/eval/EvaluationResultBlind.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.eval;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.actf.util.xpath.XPathUtil;
+import org.eclipse.actf.visualization.eval.EvaluationResultImpl;
+import org.eclipse.actf.visualization.eval.guideline.GuidelineHolder;
+import org.eclipse.actf.visualization.eval.problem.IProblemItem;
+import org.w3c.dom.NodeList;
+
+
+
+public class EvaluationResultBlind extends EvaluationResultImpl {
+
+    private int count = 0;
+    
+    public void addProblemItems(Collection<IProblemItem> c) {
+        stripProblem(c);
+        super.addProblemItems(c);
+    }
+
+    public void setProblemList(List<IProblemItem> problemList) {
+        count = 0;
+        stripProblem(problemList);
+        super.setProblemList(problemList);
+    }
+
+    private void stripProblem(Collection c){
+        GuidelineHolder holder = GuidelineHolder.getInstance();
+        for (Iterator i = c.iterator(); i.hasNext();) {
+            try {
+                IProblemItem tmpItem = (IProblemItem) i.next();
+                if (holder.isMatchedCheckItem(tmpItem.getEvaluationItem())) {
+                    tmpItem.setSerialNumber(count);
+                    if (tmpItem.isCanHighlight() && tmpItem.getTargetNode() != null) {
+                        NodeList tmpNL = XPathUtil.evalXPathNodeList(tmpItem.getTargetNode(), "ancestor::noscript");
+                        // noframes can highlight
+                        if (tmpNL != null && tmpNL.getLength() > 0) {
+                            tmpItem.setCanHighlight(false);
+                        }
+                    }
+                    count++;
+                } else {
+                    i.remove();
+                }
+            } catch (Exception e) {
+                // e.printStackTrace();
+                i.remove();
+            }
+        }
+    }
+    
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/eval/PageEvaluation.java b/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/eval/PageEvaluation.java
new file mode 100644
index 0000000..f47d078
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/eval/PageEvaluation.java
@@ -0,0 +1,218 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.eval;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.actf.visualization.Constants;
+import org.eclipse.actf.visualization.engines.blind.BlindVizEnginePlugin;
+import org.eclipse.actf.visualization.engines.blind.internal.Messages;
+import org.eclipse.actf.visualization.engines.blind.util.RadarChartNonSVG;
+import org.eclipse.actf.visualization.eval.guideline.GuidelineHolder;
+import org.eclipse.actf.visualization.eval.html.statistics.PageData;
+import org.eclipse.actf.visualization.eval.problem.IProblemItem;
+
+
+public class PageEvaluation {
+
+	private GuidelineHolder guidelineHolder = GuidelineHolder
+			.getInstance();
+
+	private PageData pageData;
+
+	private String[] metrics = guidelineHolder.getMetricsNames();
+
+	private int metricsSize = metrics.length;
+
+	private int[] scores = new int[metricsSize];
+
+	public PageEvaluation(PageData pageData) {
+		this.pageData = pageData;
+		Arrays.fill(scores, 100);
+	}
+
+	public void addProblem(IProblemItem pti) {
+		int[] curScores = pti.getEvaluationItem().getMetricsScores();
+
+		if (curScores.length == metricsSize) {
+			for (int i = 0; i < metricsSize; i++) {
+				scores[i] -= curScores[i];
+			}
+		}
+	}
+
+	private void checkMinus() {
+		for (int i = 0; i < metricsSize; i++) {
+			if (scores[i] < 0) {
+				scores[i] = 0;
+			}
+		}
+
+	}
+
+	public void setInvalidLinkRatio(double ratio) {
+
+		// TODO
+	}
+
+	protected PageData getPageData() {
+		return pageData;
+	}
+
+	protected boolean isHasComplianceError() {
+		for (int i = 0; i < metricsSize; i++) {
+			if (metrics[i].equalsIgnoreCase("compliance")) {
+				return (scores[i] != 100);
+			}
+		}
+		return (false);
+	}
+
+	public String[] getAllResult() {
+		Vector<String> tmpV = new Vector<String>();
+		tmpV.add("Page Rating"); //$NON-NLS-1$
+		tmpV.add(getOverallRating());
+
+		boolean[] enabledMetrics = guidelineHolder.getMatchedMetrics();
+
+		for (int i = 0; i < metricsSize; i++) {
+			if (enabledMetrics[i]) {
+				tmpV.add(metrics[i]);
+				tmpV.add(String.valueOf(scores[i]));
+			}
+		}
+
+		String[] result = new String[tmpV.size()];
+		tmpV.toArray(result);
+		return (result);
+
+	}
+
+	private int getMinScore() {
+		int minValue = 100;
+
+		boolean[] enabled = GuidelineHolder.getInstance()
+				.getMatchedMetrics();
+
+		for (int i = 0; i < metricsSize; i++) {
+			if (enabled[i] && minValue > scores[i]) {
+				minValue = scores[i];
+			}
+		}
+		return (minValue);
+	}
+
+	public String getOverallRating() {
+
+		int minValue = getMinScore();
+
+		String rating = Messages.getString("PageEvaluation.Bad"); //$NON-NLS-1$
+
+		if (!isHasComplianceError()) {
+			if (minValue >= 90) {
+				rating = Messages.getString("PageEvaluation.Excellent"); //$NON-NLS-1$
+			} else if (minValue >= 70) {
+				rating = Messages.getString("PageEvaluation.Good"); //$NON-NLS-1$
+			} else if (minValue >= 60) {
+				rating = Messages.getString("PageEvaluation.Poor"); //$NON-NLS-1$
+			}
+		}
+		return (rating);
+	}
+
+	public String getSummary() {
+		SummaryEvaluation se = new SummaryEvaluation(this);
+		return (se.getOverview());
+	}
+
+	public String getRatingIcon() {
+
+		int minValue = getMinScore();
+
+		String rating = Constants.RATING_BAD; //$NON-NLS-1$
+
+		if (!isHasComplianceError()) {
+			if (minValue >= 90) {
+				rating = Constants.RATING_V_GOOD; //$NON-NLS-1$
+			} else if (minValue >= 80) {
+				rating = Constants.RATING_GOOD; //$NON-NLS-1$
+			} else if (minValue >= 60) {
+				rating = Constants.RATING_POOR; //$NON-NLS-1$
+			}
+		}
+		return (rating);
+	}
+
+	// TODO move to constructor
+	public static PageEvaluation createPageReport(List problems,
+			PageData pageData) {
+		PageEvaluation eval = new PageEvaluation(pageData);
+		return createPageReport(problems, pageData, eval);
+	}
+
+	protected static PageEvaluation createPageReport(List problems,
+			PageData pageData, PageEvaluation eval) {
+		for (Iterator i = problems.iterator(); i.hasNext();) {
+			eval.addProblem((IProblemItem) i.next());
+		}
+
+		eval.setInvalidLinkRatio(pageData.getInvalidLinkRatio());
+
+		eval.checkMinus();
+
+		boolean[] enabled = GuidelineHolder.getInstance()
+				.getMatchedMetrics();
+		String[] metrics = eval.getMetrics();
+		int[] scores = eval.getScores();
+
+		Vector<String> metricsV = new Vector<String>();
+		Vector<Integer> scoresV = new Vector<Integer>();
+
+		for (int i = 0; i < enabled.length; i++) {
+			if (enabled[i]) {
+				metricsV.add(metrics[i]);
+				scoresV.add(new Integer(scores[i]));
+			}
+		}
+		metrics = new String[metricsV.size()];
+		metricsV.toArray(metrics);
+
+		scores = new int[scoresV.size()];
+		for (int i = 0; i < scoresV.size(); i++) {
+			scores[i] = scoresV.get(i).intValue();
+		}
+
+		try {
+			RadarChartNonSVG chart = new RadarChartNonSVG(metrics, scores);
+
+			// TODO use tmp file
+			chart.writeToPNG(new File(BlindVizEnginePlugin.getTempDirectory(),
+					"pagerating.png")); //$NON-NLS-1$
+		} catch (Exception e) {
+			// e.printStackTrace();
+			// TODO create empty png
+		}
+		return (eval);
+	}
+
+	public String[] getMetrics() {
+		return metrics;
+	}
+
+	public int[] getScores() {
+		return scores;
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/eval/SummaryEvaluation.java b/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/eval/SummaryEvaluation.java
new file mode 100644
index 0000000..c4e2592
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/eval/SummaryEvaluation.java
@@ -0,0 +1,270 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.eval;
+
+import org.eclipse.actf.util.ui.HighlightStringListener;
+import org.eclipse.actf.visualization.Constants;
+import org.eclipse.actf.visualization.engines.blind.internal.Messages;
+import org.eclipse.actf.visualization.eval.guideline.GuidelineHolder;
+import org.eclipse.actf.visualization.eval.html.statistics.PageData;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.widgets.Display;
+
+public class SummaryEvaluation {
+
+	public static HighlightStringListener getHighLightStringListener() {
+		HighlightStringListener hlsl = new HighlightStringListener();
+		Color blue = Display.getDefault().getSystemColor(SWT.COLOR_BLUE);
+		Color red = Display.getDefault().getSystemColor(SWT.COLOR_RED);
+
+		hlsl.addTarget(Messages.getString("Eval.excellent"), blue, SWT.BOLD);
+		hlsl.addTarget(Messages.getString("Eval.completely.compliant"), blue,
+				SWT.BOLD);
+		hlsl.addTarget(Messages.getString("Eval.seems.completely.compliant"),
+				blue, SWT.BOLD);
+		hlsl.addTarget(Messages
+				.getString("Eval.completely.compliant.with.some.errors"), red,
+				SWT.BOLD);
+		hlsl.addTarget(Messages.getString("Eval.many.accessibility.issues"),
+				red, SWT.BOLD);
+		hlsl.addTarget(Messages.getString("Eval.some.accessibility.issues"),
+				red, SWT.BOLD);
+
+		hlsl.addTarget(Messages
+				.getString("Eval.easy.for.blind.user.to.navigate"), blue,
+				SWT.BOLD);
+
+		hlsl.addTarget(Messages.getString("Eval.page.has.skiplinks.headings"),
+				red, SWT.BOLD);
+		hlsl.addTarget(Messages
+				.getString("Eval.darkcolored.visualization.view"), red,
+				SWT.BOLD);
+
+		return (hlsl);
+	}
+
+	private PageEvaluation pe;
+
+	private PageData pageData;
+
+	private int noImageAltCount;
+
+	private int wrongImageAltCount;
+
+	private int redundantImageAltCount = 0;
+
+	private GuidelineHolder guidelineHolder = GuidelineHolder
+			.getInstance();
+
+	/**
+	 * 
+	 */
+	public SummaryEvaluation(PageEvaluation pe) {
+		this.pe = pe;
+		this.pageData = pe.getPageData();
+	}
+
+	public String getOverview() {
+		StringBuffer tmpSB = new StringBuffer(512);
+		StringBuffer noGoodMetrics = new StringBuffer();
+
+		boolean hasComp = false;
+		boolean hasNav = false;
+		boolean hasOther = false;
+
+		String[] metrics = pe.getMetrics();
+		int[] scores = pe.getScores();
+
+		int comp = 100;
+		int nav = 100;
+		int other = 100;
+
+		// boolean[] enabledMetrics = guidelineHolder.getMatchedMetrics();
+
+		for (int i = 0; i < metrics.length; i++) {
+			int score = scores[i];
+			if (metrics[i].equalsIgnoreCase("compliance")
+					&& guidelineHolder.isMatchedMetric(metrics[i])) {
+				comp = score;
+				hasComp = true;
+				if (score != 100) {
+					noGoodMetrics.append(metrics[i] + ",");
+				}
+			} else if (metrics[i].equalsIgnoreCase("navigability")
+					&& guidelineHolder.isMatchedMetric(metrics[i])) {
+				nav = score;
+				hasNav = true;
+			} else {
+				hasOther = true;
+				if (other > score) {
+					other = score;
+				}
+				if (score != 100) {
+					noGoodMetrics.append(metrics[i] + ",");
+				}
+			}
+		}
+
+		noImageAltCount = pageData.getMissingAltNum();
+		wrongImageAltCount = pageData.getWrongAltNum();
+		// alertImageAltCount = pageData.get;
+		// redundantImageAltCount = pageData.get;//TODO
+		int totalAltError = noImageAltCount + wrongImageAltCount;// +
+		// redundantImageAltCount;
+		// +alertImageAltCount
+
+		StringBuffer aboutComp = new StringBuffer();
+		StringBuffer aboutNav = new StringBuffer();
+
+		boolean isGood = false;
+
+		if (hasComp) {
+			if (comp >= 80) {
+				if (pe.isHasComplianceError()) {
+					aboutComp
+							.append(Messages
+									.getString("Eval.completely.compliant.with.some.errors")
+									+ Constants.LINE_SEP);
+
+					if (totalAltError > 0) {
+						aboutComp
+								.append(Messages
+										.getString("Eval.confirm.alt.attributes.first"));
+						aboutComp.append(getImageAltStatistics());
+					} else {
+						aboutComp
+								.append(Messages
+										.getString("Eval.confirm.errors.detailed.report"));
+					}
+				} else {
+					if (hasOther && other != 100) {
+						aboutComp.append(Messages.formatResourceString(
+								"Eval.some.errors.on.metrics", new String[] {
+										noGoodMetrics.substring(0,
+												noGoodMetrics.length() - 1),
+										Constants.LINE_SEP }));
+					} else {
+						if (comp == 100) {
+							isGood = true;
+							aboutComp.append(Messages
+									.getString("Eval.completely.compliant"));
+						} else {
+							isGood = true;
+							aboutComp
+									.append(Messages
+											.formatResourceString(
+													"Eval.completely.compliant.with.user.check.items",
+													Constants.LINE_SEP));
+						}
+					}
+				}
+			} else {
+				if (comp > 50) {
+					aboutComp.append(Messages
+							.getString("Eval.some.accessibility.issues")
+							+ Constants.LINE_SEP);
+				} else {
+					aboutComp.append(Messages
+							.getString("Eval.many.accessibility.issues")
+							+ Constants.LINE_SEP);
+				}
+
+				if (totalAltError > 0) {
+					aboutComp.append(Messages
+							.getString("Eval.confirm.alt.attributes.first")
+							+ Constants.LINE_SEP);
+					aboutComp.append(getImageAltStatistics());
+				} else {
+					aboutComp.append(Messages
+							.getString("Eval.confirm.errors.detailed.report"));
+				}
+			}
+		}
+
+		//
+		if (hasNav) {
+			if (nav > 80) {
+				if (pageData.getMaxTime() > 240) {
+					aboutNav.append(Messages.formatResourceString(
+							"Eval.navigability.long.time.error.msg",
+							new String[] { Constants.LINE_SEP,
+									Constants.LINE_SEP, Constants.LINE_SEP,
+									Constants.LINE_SEP })
+							+ Constants.LINE_SEP);
+
+				} else {
+					aboutNav.append(Messages.formatResourceString(
+							"Eval.navigability.good.msg", new String[] {
+									Constants.LINE_SEP, Constants.LINE_SEP })
+							+ Constants.LINE_SEP);
+				}
+			} else {
+				isGood = false;
+				aboutNav.append(Messages.formatResourceString(
+						"Eval.navigability.low.score.error.msg", new String[] {
+								Constants.LINE_SEP, Constants.LINE_SEP,
+								Constants.LINE_SEP, Constants.LINE_SEP })
+						+ Constants.LINE_SEP);
+			}
+		}
+
+		if ((hasComp || hasNav) && isGood) {
+			tmpSB.append(Messages.getString("Eval.excellent")
+					+ Constants.LINE_SEP + Constants.LINE_SEP);
+		}
+		tmpSB.append(aboutNav + Constants.LINE_SEP);
+		tmpSB.append(aboutComp);
+
+		return (tmpSB.toString());
+	}
+
+	private String getImageAltStatistics() {
+		StringBuffer tmpSB = new StringBuffer();
+
+		if (noImageAltCount > 0) {
+			tmpSB.append(" -"
+					+ Messages.formatResourceString(
+							"Eval.no.img.alt.error.msg", Constants.LINE_SEP));
+		}
+		if (wrongImageAltCount > 0) {
+			tmpSB
+					.append(" -"
+							+ Messages.formatResourceString(
+									"Eval.wrong.img.alt.error.msg",
+									Constants.LINE_SEP));
+		}
+		if (redundantImageAltCount > 0) {
+			tmpSB.append(" -"
+					+ Messages.formatResourceString(
+							"Eval.redundant.img.al.error.msg",
+							Constants.LINE_SEP));
+		}
+		tmpSB.append(Constants.LINE_SEP);
+
+		if (noImageAltCount > 0) {
+			tmpSB.append(" " + Messages.getString("Eval.no.img.alt") + " "
+					+ noImageAltCount + Constants.LINE_SEP);
+		}
+		if (wrongImageAltCount > 0) {
+			tmpSB.append(" " + Messages.getString("Eval.wrong.img.alt") + " "
+					+ wrongImageAltCount + Constants.LINE_SEP);
+		}
+		if (redundantImageAltCount > 0) {
+			tmpSB.append(" " + Messages.getString("Eval.redundant.img.alt")
+					+ " " + redundantImageAltCount + Constants.LINE_SEP);
+		}
+
+		return (tmpSB.toString());
+	}
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/internal/Messages.java b/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/internal/Messages.java
new file mode 100644
index 0000000..da5efe1
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/internal/Messages.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.internal;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+import org.eclipse.actf.visualization.engines.blind.BlindVizEnginePlugin;
+
+public class Messages {
+	private static final String BUNDLE_NAME = BlindVizEnginePlugin.PLUGIN_ID+".internal.messages"; //$NON-NLS-1$
+
+	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+			.getBundle(BUNDLE_NAME);
+
+	private Messages() {
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+
+	public static String formatResourceString(String key, Object arg) {
+		Object args[] = { arg };
+		return formatResourceString(key, args);
+	}
+
+	public static String formatResourceString(String key, Object[] args) {
+		return MessageFormat.format(getString(key), args);
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/internal/messages.properties b/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/internal/messages.properties
new file mode 100644
index 0000000..1b53dbd
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/internal/messages.properties
@@ -0,0 +1,67 @@
+###############################################################################
+# Copyright (c) 2006, 2008 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#     IBM Corporation - initial API and implementation
+###############################################################################
+#
+AltDialog.TITLE = Edit Inappropriate Alt List
+AltDialog.Column_Name = Inappropreate ALT WORDS
+AltDialog.MSG_No_String = Please input string.
+AltDialog.MSG_Existed = The Word has existed.
+#
+# PageEvaluation
+#
+PageEvaluation.Bad=Unsatisfactory (needs modification)
+PageEvaluation.Excellent=Excellent
+PageEvaluation.Good=Good
+PageEvaluation.Poor=Passes minimum requirements
+#
+# SummaryEvaluation
+#
+Eval.redundant.img.alt=Redundant ALT attribute:
+Eval.wrong.img.alt=Image with wrong ALT attribute:
+Eval.no.img.alt=Image without ALT attribute:
+Eval.redundant.img.alt.error.msg=If there are alternative text near the image, please use alt="".
+Eval.wrong.img.alt.error.msg=Please do not use unclear ALT, such as "click here" or "image".
+Eval.no.img.alt.error.msg=Please provide alternative text for an image (If the image has no information to read out, please provide alt=""
+Eval.navigability.low.score.error.msg=In visualization view, you can confirm that most part of the page are dark-colored.{0}Blind users have to wait too long to visit these fragments.{1}To improve blind users' navigability, please provide more headings(H1,H2,...) or skip-links.
+Eval.navigability.long.time.error.msg=This page has some skip-links or some headings.{0}"However, you can find some dark fragments in visualization view.{1}Blind users have to wait too long to visit these fragments.{2}"To improve blind users' navigability, please provide more headings(H1,H2,...) or skip-links.
+Eval.navigability.good.msg=This page is well structured and might be easy for blind users to navigate.
+Eval.confirm.errors.detailed.report=Please confirm errors at detailed report tab, then correct them.
+Eval.confirm.alt.attributes.first=At first, please confirm ALT attribute of images.
+Eval.many.accessibility.issues=This page seems to have many accessibility issues.
+Eval.some.accessibility.issues=This page seems to have some accessibility issues.
+Eval.completely.compliant.with.user.check.items=This page seems completely compliant with guidelines.{0}However, there exists some user check items. Please confirm them at detailed report tab.
+Eval.completely.compliant=Congratulations! This page is completely compliant with guidelines.
+Eval.some.errors.on.metrics=This page has some errors on metrics ({0}).{1}  Please confirm them at detailed report tab.
+Eval.completely.compliant.with.some.errors=This page is almost compliant with guidelines, however, there are still some errors.
+Eval.excellent=Excellent!
+Eval.seems.completely.compliant=This page seems completely compliant with guidelines.
+Eval.easy.for.blind.user.to.navigate=This page is well structured and might be easy for blind users to navigate.
+Eval.page.has.skiplinks.headings=This page has some skip-links or some headings.
+Eval.darkcolored.visualization.view=However, you can find some dark fragments in visualization view. In visualization view, you can confirm that most part of the page are dark-colored.
+#
+# PreferencePage
+#
+DialogSettingBlind.NG_Word_/_Wrong_Text_5 = Inappropriate Alt
+DialogSettingBlind.NG_Word/Wrong_Text_Edit..._25 = Edit Inappropriate Alt List
+DialogSettingBlind.Language_4 = Language
+DialogSettingBlind.English_15 = English
+DialogSettingBlind.Japanese_16 = Japanese
+DialogSettingBlind.LayoutModeSetting = Layout Mode Settings
+DialogSettingBlind.Visualization_mode_3 = Visualization mode
+DialogSettingBlind.Voice_browser_output_mode_8 = Voice browser output mode
+DialogSettingBlind.Layout_mode_9 = Layout mode
+DialogSettingBlind.Maximum_time_17 = Maximum time:
+DialogSettingBlind.Color_for_maximum_time_19 = Color for maximum time:
+DialogSettingBlind.Table_headers_20 = Table headers:
+DialogSettingBlind.Heading_tags_21 = Heading tags:
+DialogSettingBlind.Input_tags_22 = Input tags:
+DialogSettingBlind.Label_tags_23 = Label tags:
+DialogSettingBlind.Tabel_border_24 = Tabel border:
+
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/internal/messages_ja.properties b/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/internal/messages_ja.properties
new file mode 100644
index 0000000..2bd2740
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/internal/messages_ja.properties
@@ -0,0 +1,66 @@
+###############################################################################
+# Copyright (c) 2006, 2008 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#     IBM Corporation - initial API and implementation
+###############################################################################
+#
+AltDialog.TITLE = \u4e0d\u9069\u5207\u306aALT\u5c5e\u6027\u3092\u8a2d\u5b9a
+AltDialog.Column_Name = \u4e0d\u9069\u5207\u306aALT\u5c5e\u6027
+AltDialog.MSG_No_String = \u4f55\u3089\u304b\u306e\u6587\u5b57\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044
+AltDialog.MSG_Existed = \u65e2\u306b\u5165\u529b\u3055\u308c\u305f\u5358\u8a9e\u3067\u3059
+#
+# PageEvaluation
+#
+PageEvaluation.Bad=\u8981\u4fee\u6b63
+PageEvaluation.Excellent=\u975e\u5e38\u306b\u826f\u3044
+PageEvaluation.Good=\u826f\u3044
+PageEvaluation.Poor=\u5229\u7528\u56f0\u96e3
+#
+# SummaryEvaluation
+#
+Eval.redundant.img.alt=\u7e70\u308a\u8fd4\u3057\u306b\u306a\u308bALT\u5c5e\u6027\u3092\u6301\u3064\u753b\u50cf\u306e\u6570:
+Eval.wrong.img.alt=\u5224\u308a\u306b\u304f\u3044ALT\u5c5e\u6027\u3092\u6301\u3064\u753b\u50cf\u306e\u6570:
+Eval.no.img.alt=ALT\u5c5e\u6027\u306e\u7121\u3044\u753b\u50cf\u306e\u6570:
+Eval.redundant.img.alt.error.msg=\u3082\u3057\u753b\u50cf\u306e\u3059\u3050\u524d\u5f8c\u306b\uff0c\u305d\u306e\u753b\u50cf\u306e\u610f\u5473\u3092\u8868\u3059\u6587\u5b57\u5217\u306a\u3069\u304c\u5b58\u5728\u3057\u3066\u3044\u308b\u5834\u5408\u306b\u306f\uff0cALT="" \u3068\u3057\u3066\u304f\u3060\u3055\u3044\uff0e{0} \uff08\u97f3\u58f0\u30d6\u30e9\u30a6\u30b6\u3067\u95b2\u89a7\u3057\u305f\u969b\u306b\uff0c\u540c\u3058\u6587\u7ae0\u3092\u7e70\u308a\u8fd4\u3057\u8aad\u307f\u4e0a\u3052\u3066\u3057\u307e\u3044\u307e\u3059\uff0e\uff09
+Eval.wrong.img.alt.error.msg=\u753b\u50cf\u306e\u4ee3\u66ff\u30c6\u30ad\u30b9\u30c8\uff08ALT\u5c5e\u6027\uff09\u306b\u306f\u610f\u5473\u306e\u3042\u308b\u6587\u5b57\u5217\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\uff0e{0}  \uff08\u300c\u30af\u30ea\u30c3\u30af\u300d\u3084\u300cimage\u300d\u7b49\u3067\u306f\uff0c\u97f3\u58f0\u3067\u8aad\u307f\u4e0a\u3052\u305f\u969b\u306b\u753b\u50cf\u306e\u610f\u5473\u3084\u5f79\u5272\u304c\u4f1d\u308f\u308a\u307e\u305b\u3093\uff0e)
+Eval.no.img.alt.error.msg=\u753b\u50cf\uff08IMG\u30bf\u30b0\uff09\u306b\u306f\uff0c\u305d\u306e\u753b\u50cf\u306e\u610f\u5473\u3084\u5f79\u5272\u3092\u8868\u3059\u6587\u5b57\u5217\u3092ALT\u5c5e\u6027\u3068\u3057\u3066\u4ed8\u52a0\u3057\u3066\u304f\u3060\u3055\u3044\uff0e{0}  \uff08\u3082\u3057\uff0c\u7a7a\u767d\u753b\u50cf\u306a\u3069\uff0c\u610f\u5473\u306e\u7121\u3044\u753b\u50cf\u306e\u5834\u5408\u306f ALT="" \u3068\u3057\u3066\u304f\u3060\u3055\u3044)
+Eval.navigability.low.score.error.msg=\u53f3\u4e0a\u306e\u7d50\u679c\u753b\u9762\u3067\u30da\u30fc\u30b8\u306e\u5927\u90e8\u5206\u304c\u6697\u3044\u8272\u306b\u306a\u3063\u3066\u3044\u307e\u305b\u3093\u304b\uff1f{0} \u3053\u306e\u30da\u30fc\u30b8\u306b\u97f3\u58f0\u3067\u30a2\u30af\u30bb\u30b9\u3057\u305f\u5834\u5408\uff0c\u6700\u3082\u6697\u3044\u8272\u306e\u90e8\u5206\u306b\u5230\u9054\u3059\u308b\u306b\u306f90\u79d2\u4ee5\u4e0a\u304b\u304b\u3063\u3066\u3057\u307e\u3044\u307e\u3059\uff0e{1} \u898b\u51fa\u3057\u30bf\u30b0(H1,H2...)\u3084\u30da\u30fc\u30b8\u5185\u30ea\u30f3\u30af\u3092\u63d0\u4f9b\u3057\u3066\uff0c\u30da\u30fc\u30b8\u5185\u306e\u5404\u9805\u76ee\u3078\u306e\u79fb\u52d5\u304c\u7c21\u5358\u306b\u306a\u308b\u3088\u3046\u306b\u3057\u3066\u4e0b\u3055\u3044\uff0e{2} \u7d50\u679c\u753b\u9762\u306e\u4e2d\u3067\u306f\uff0c\u898b\u51fa\u3057\u306f\u6c34\u8272\uff0c\u30da\u30fc\u30b8\u5185\u30ea\u30f3\u30af\u306f\u77e2\u5370\u3067\u8868\u793a\u3055\u308c\u307e\u3059\uff0e{3} \u307e\u305f\uff0c\u3053\u308c\u3089\u306e\u6a5f\u80fd\u3092\u63d0\u4f9b\u3059\u308b\u3053\u3068\u3067\uff0c\u7d50\u679c\u5168\u4f53\u304c\u660e\u308b\u3044\u8272\u306b\u306a\u3063\u3066\u304d\u307e\u3059\u306e\u3067\u78ba\u8a8d\u3057\u3066\u307f\u3066\u304f\u3060\u3055\u3044\uff0e
+Eval.navigability.long.time.error.msg=\u3053\u306e\u30da\u30fc\u30b8\u306b\u306f\uff0c\u97f3\u58f0\u3067\u306e\u30ca\u30d3\u30b2\u30fc\u30b7\u30e7\u30f3\u304c\u96e3\u3057\u3044\u7b87\u6240\u304c\u6b8b\u3063\u3066\u3044\u308b\u3088\u3046\u3067\u3059\uff0e{0} \u53f3\u4e0a\u306e\u7d50\u679c\u753b\u9762\u306e\u4e2d\u3067\u6700\u3082\u6697\u3044\u8272\u306e\u90e8\u5206\u306b\u5230\u9054\u3059\u308b\u306b\u306f90\u79d2\u4ee5\u4e0a\u304b\u304b\u3063\u3066\u3057\u307e\u3044\u307e\u3059\uff0e{1} \u3088\u308a\u591a\u304f\u306e\u898b\u51fa\u3057\u30bf\u30b0(H1,H2...)\u3084\u30da\u30fc\u30b8\u5185\u30ea\u30f3\u30af\u3092\u63d0\u4f9b\u3057\u3066\uff0c\u30da\u30fc\u30b8\u5185\u306e\u5404\u9805\u76ee\u3078\u7c21\u5358\u306b\u79fb\u52d5\u3067\u304d\u308b\u3088\u3046\u306b\u3057\u3066\u304f\u3060\u3055\u3044\uff0e{2} \u7d50\u679c\u753b\u9762\u306e\u4e2d\u3067\u306f\uff0c\u898b\u51fa\u3057\u306f\u6c34\u8272\uff0c\u30da\u30fc\u30b8\u5185\u30ea\u30f3\u30af\u306f\u77e2\u5370\u3067\u8868\u793a\u3055\u308c\u307e\u3059\uff0e{3} \u307e\u305f\uff0c\u3053\u308c\u3089\u306e\u6a5f\u80fd\u3092\u63d0\u4f9b\u3059\u308b\u3053\u3068\u3067\uff0c\u7d50\u679c\u5168\u4f53\u304c\u660e\u308b\u3044\u8272\u306b\u306a\u3063\u3066\u304d\u307e\u3059\u306e\u3067\u78ba\u8a8d\u3057\u3066\u307f\u3066\u304f\u3060\u3055\u3044\uff0e
+Eval.navigability.good.msg=\u3053\u306e\u30da\u30fc\u30b8\u306f\u97f3\u58f0\u30d6\u30e9\u30a6\u30b6\u3067\u3082\u7c21\u5358\u306b\u30ca\u30d3\u30b2\u30fc\u30b7\u30e7\u30f3\u3067\u304d\u308b\u3068\u601d\u308f\u308c\u307e\u3059\uff0e{0} \u53f3\u4e0a\u306e\u7d50\u679c\u753b\u9762\u3067\uff0c\u80cc\u666f\u304c\u6c34\u8272\u306e\u6587\u5b57\u5217\u304c\u898b\u51fa\u3057\u3067\u3042\u308b\u3053\u3068\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\uff0e{1} \u307e\u305f\uff0c\u77e2\u5370\u306e\u30a2\u30a4\u30b3\u30f3\u3092\u62bc\u3057\u3066\uff0c\u30da\u30fc\u30b8\u5185\u30ea\u30f3\u30af\u306e\u30b8\u30e3\u30f3\u30d7\u5148\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\uff0e
+Eval.confirm.errors.detailed.report=\u8a73\u7d30\u30ec\u30dd\u30fc\u30c8\u3067\uff0c\u3069\u306e\u3088\u3046\u306a\u554f\u984c\u304c\u3042\u308b\u304b\u78ba\u8a8d\u3057\u3066\u4fee\u6b63\u3057\u3066\u304f\u3060\u3055\u3044\uff0e
+Eval.confirm.alt.attributes.first=\u307e\u305a\u306f\uff0c\u30da\u30fc\u30b8\u5185\u306e\u753b\u50cf\u306b\u5bfe\u3057\u3066\uff0c\u305d\u306e\u610f\u5473\u30fb\u5f79\u5272\u3092\u8aac\u660e\u3059\u308b\u6587\u5b57\u5217(ALT\u5c5e\u6027)\u304c\u4ed8\u52a0\u3055\u308c\u3066\u3044\u308b\u304b\u78ba\u8a8d\u3057\u3066\u307f\u307e\u3057\u3087\u3046\uff0e
+Eval.many.accessibility.issues=\u3053\u306e\u30da\u30fc\u30b8\u306b\u306f\u30a2\u30af\u30bb\u30b7\u30d3\u30ea\u30c6\u30a3\u306b\u95a2\u3059\u308b\u554f\u984c\u304c\u591a\u6570\u5b58\u5728\u3057\u3066\u3044\u307e\u3059\uff0e
+Eval.some.accessibility.issues=\u3053\u306e\u30da\u30fc\u30b8\u306b\u306f\u3044\u304f\u3064\u304b\u306e\u30a2\u30af\u30bb\u30b7\u30d3\u30ea\u30c6\u30a3\u306b\u95a2\u3059\u308b\u554f\u984c\u304c\u5b58\u5728\u3057\u3066\u3044\u307e\u3059\uff0e
+Eval.completely.compliant.with.user.check.items=\u3053\u306e\u30da\u30fc\u30b8\u306faDesigner\u3067\u30c1\u30a7\u30c3\u30af\u53ef\u80fd\u306a\u30ac\u30a4\u30c9\u30e9\u30a4\u30f3\u306e\u9805\u76ee\u5168\u3066\u306b\u6e96\u62e0\u3057\u3066\u3044\u308b\u69d8\u3067\u3059\uff0e{0}\uff08\u305f\u3060\uff0c\u30e6\u30fc\u30b6\u306b\u3088\u308b\u78ba\u8a8d\u304c\u5fc5\u8981\u306a\u9805\u76ee\u304c\u3044\u304f\u3064\u304b\u3042\u308a\u307e\u3059\uff0c\u8a73\u7d30\u30ec\u30dd\u30fc\u30c8\u3067\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\uff0e\uff09
+Eval.completely.compliant=\u3053\u306e\u30da\u30fc\u30b8\u306faDesigner\u3067\u30c1\u30a7\u30c3\u30af\u53ef\u80fd\u306a\u30ac\u30a4\u30c9\u30e9\u30a4\u30f3\u306e\u9805\u76ee\u5168\u3066\u306b\u6e96\u62e0\u3057\u3066\u3044\u307e\u3059\uff0e
+Eval.some.errors.on.metrics=\u3053\u306e\u30da\u30fc\u30b8\u306f\u8a55\u4fa1\u57fa\u6e96({0})\u306b\u95a2\u3059\u308b\u554f\u984c\u304c\u3042\u308b\u3088\u3046\u3067\u3059\uff0e{1}\uff08\u8a73\u7d30\u30ec\u30dd\u30fc\u30c8\u3067\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\uff0e\uff09
+Eval.completely.compliant.with.some.errors=\u3053\u306e\u30da\u30fc\u30b8\u306f\u30ac\u30a4\u30c9\u30e9\u30a4\u30f3\u306b\u307b\u307c\u6e96\u62e0\u3057\u3066\u3044\u308b\u3088\u3046\u3067\u3059\u304c\uff0c\u307e\u3060\u3044\u304f\u3064\u304b\u306e\u554f\u984c\u304c\u6b8b\u3063\u3066\u3044\u307e\u3059\uff0e
+Eval.excellent=Excellent!
+Eval.seems.completely.compliant=\u3053\u306e\u30da\u30fc\u30b8\u306faDesigner\u3067\u30c1\u30a7\u30c3\u30af\u53ef\u80fd\u306a\u30ac\u30a4\u30c9\u30e9\u30a4\u30f3\u306e\u9805\u76ee\u5168\u3066\u306b\u6e96\u62e0\u3057\u3066\u3044\u308b\u69d8\u3067\u3059\uff0e
+Eval.easy.for.blind.user.to.navigate=\u3053\u306e\u30da\u30fc\u30b8\u306f\u97f3\u58f0\u30d6\u30e9\u30a6\u30b6\u3067\u3082\u7c21\u5358\u306b\u30ca\u30d3\u30b2\u30fc\u30b7\u30e7\u30f3\u3067\u304d\u308b\u3068\u601d\u308f\u308c\u307e\u3059\uff0e
+Eval.page.has.skiplinks.headings=\u3053\u306e\u30da\u30fc\u30b8\u306b\u306f\uff0c\u97f3\u58f0\u3067\u306e\u30ca\u30d3\u30b2\u30fc\u30b7\u30e7\u30f3\u304c\u96e3\u3057\u3044\u7b87\u6240\u304c\u6b8b\u3063\u3066\u3044\u308b\u3088\u3046\u3067\u3059\uff0e
+Eval.darkcolored.visualization.view=\u53f3\u4e0a\u306e\u7d50\u679c\u753b\u9762\u3067\u30da\u30fc\u30b8\u306e\u5927\u90e8\u5206\u304c\u6697\u3044\u8272\u306b\u306a\u3063\u3066\u3044\u307e\u305b\u3093\u304b\uff1f
+#
+# PreferencePage
+#
+DialogSettingBlind.NG_Word_/_Wrong_Text_5 = \u4e0d\u9069\u5207\u306aALT\u5c5e\u6027
+DialogSettingBlind.NG_Word/Wrong_Text_Edit..._25 = \u4e0d\u9069\u5207\u306aALT\u5c5e\u6027\u30ea\u30b9\u30c8\u306e\u7de8\u96c6
+DialogSettingBlind.Language_4 = \u8a00\u8a9e
+DialogSettingBlind.English_15 = \u82f1\u8a9e
+DialogSettingBlind.Japanese_16 = \u65e5\u672c\u8a9e
+DialogSettingBlind.LayoutModeSetting = \u30ec\u30a4\u30a2\u30a6\u30c8\u4fdd\u5b58\u30e2\u30fc\u30c9\u8a2d\u5b9a
+DialogSettingBlind.Visualization_mode_3 = \u97f3\u58f0\u30e6\u30fc\u30b6\u30d3\u30ea\u30c6\u30a3\u8996\u899a\u5316\u30e2\u30fc\u30c9
+DialogSettingBlind.Voice_browser_output_mode_8 = \u97f3\u58f0\u30d6\u30e9\u30a6\u30b6\u51fa\u529b\u30e2\u30fc\u30c9
+DialogSettingBlind.Layout_mode_9 = \u30ec\u30a4\u30a2\u30a6\u30c8\u4fdd\u5b58\u30e2\u30fc\u30c9
+DialogSettingBlind.Maximum_time_17 = \u8a31\u5bb9\u6700\u5927\u5230\u9054\u6642\u9593:
+DialogSettingBlind.Color_for_maximum_time_19 = \u8a31\u5bb9\u6700\u5927\u5230\u9054\u6642\u9593\u306e\u8272:
+DialogSettingBlind.Table_headers_20 = \u30c6\u30fc\u30d6\u30eb\u30d8\u30c3\u30c0\u30bf\u30b0 (TH):
+DialogSettingBlind.Heading_tags_21 = \u898b\u51fa\u3057\u30bf\u30b0 (H1,H2...):
+DialogSettingBlind.Input_tags_22 = \u5165\u529b\u30bf\u30b0 (Input):
+DialogSettingBlind.Label_tags_23 = \u30e9\u30d9\u30eb\u30bf\u30b0 (Label):
+DialogSettingBlind.Tabel_border_24 = \u30c6\u30fc\u30d6\u30eb\u306e\u5883\u754c:
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/ui/actions/BlindSettingAction.java b/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/ui/actions/BlindSettingAction.java
new file mode 100644
index 0000000..f5717b6
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/ui/actions/BlindSettingAction.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.ui.actions;
+
+import org.eclipse.actf.util.ui.Messages;
+import org.eclipse.actf.util.ui.PreferenceUtils;
+import org.eclipse.actf.visualization.engines.blind.BlindVizEnginePlugin;
+import org.eclipse.actf.visualization.engines.blind.ui.preferences.BlindPreferencePage;
+import org.eclipse.jface.action.Action;
+
+public class BlindSettingAction extends Action {
+
+	public BlindSettingAction() {
+		setToolTipText(Messages.getString("Tooltip.Settings")); //$NON-NLS-1$
+		setImageDescriptor(BlindVizEnginePlugin.imageDescriptorFromPlugin(
+				BlindVizEnginePlugin.PLUGIN_ID, "icons/setting.png"));
+		setText(Messages.getString("MenuConst.Settings")); //$NON-NLS-1$
+	}
+
+	public void run() {
+		PreferenceUtils.openPreferenceDialog(BlindPreferencePage.ID);
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/ui/preferences/BlindPreferencePage.java b/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/ui/preferences/BlindPreferencePage.java
new file mode 100644
index 0000000..0b99196
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/ui/preferences/BlindPreferencePage.java
@@ -0,0 +1,187 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.ui.preferences;
+
+import java.util.Locale;
+
+import org.eclipse.actf.util.ui.GroupFieldEditorPreferencePage;
+import org.eclipse.actf.util.ui.ScaleFieldEditorWithValue;
+import org.eclipse.actf.visualization.engines.blind.BlindVizEnginePlugin;
+import org.eclipse.actf.visualization.engines.blind.internal.Messages;
+import org.eclipse.actf.visualization.engines.blind.util.ParamBlind;
+import org.eclipse.jface.preference.ColorFieldEditor;
+import org.eclipse.jface.preference.RadioGroupFieldEditor;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+
+
+public class BlindPreferencePage extends GroupFieldEditorPreferencePage
+		implements IWorkbenchPreferencePage {
+
+	public static final String ID = BlindPreferencePage.class.getName();
+
+	private RadioGroupFieldEditor modeRadio;
+
+	private Group visualizationSetting;
+
+	public BlindPreferencePage() {
+		super();
+		setPreferenceStore(BlindVizEnginePlugin.getDefault().getPreferenceStore());
+	}
+
+	public void init(IWorkbench workbench) {
+	}
+
+	private void createInappropriateAltPart(Composite parent) {
+		Group inAppropriateAltGroup = createFieldGroup(Messages
+				.getString("DialogSettingBlind.NG_Word_/_Wrong_Text_5"));
+
+		Button editListButton = new Button(inAppropriateAltGroup, SWT.PUSH);
+		editListButton.setText(Messages
+				.getString("DialogSettingBlind.NG_Word/Wrong_Text_Edit..._25"));
+		editListButton.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				editNgwordWrongtxt();
+			}
+		});
+	}
+
+	private void createLanguagePart(Composite parent) {
+
+		addField(new RadioGroupFieldEditor(
+				IBlindPreferenceConstants.BLIND_LANG, Messages
+						.getString("DialogSettingBlind.Language_4"), 1,
+				new String[][] {
+						{ Messages.getString("DialogSettingBlind.English_15"),
+								IBlindPreferenceConstants.LANG_EN },
+						{ Messages.getString("DialogSettingBlind.Japanese_16"),
+								IBlindPreferenceConstants.LANG_JA } }, parent));
+	}
+
+	private void editNgwordWrongtxt() {
+		EditNGWordDialog dlg = new EditNGWordDialog(getShell());
+		dlg.open();
+	}
+
+	protected void createFieldEditors() {
+
+		Composite parent = getFieldEditorParent();
+
+		modeRadio = new RadioGroupFieldEditor(
+				IBlindPreferenceConstants.BLIND_MODE,
+				Messages.getString("DialogSettingBlind.Visualization_mode_3"),
+				1,
+				new String[][] {
+						{
+								Messages
+										.getString("DialogSettingBlind.Layout_mode_9"),
+								IBlindPreferenceConstants.BLIND_LAYOUT_MODE },
+						{
+								Messages
+										.getString("DialogSettingBlind.Voice_browser_output_mode_8"),
+								IBlindPreferenceConstants.BLIND_BROWSER_MODE } },
+				parent);
+
+		addField(modeRadio);
+
+		visualizationSetting = createFieldGroup(Messages
+				.getString("DialogSettingBlind.LayoutModeSetting"));
+
+		addField(new ColorFieldEditor(
+				IBlindPreferenceConstants.BLIND_MAX_TIME_COLOR,
+				Messages.getString("DialogSettingBlind.Color_for_maximum_time_19"),
+				visualizationSetting));
+		ScaleFieldEditorWithValue maxTime = new ScaleFieldEditorWithValue(
+				IBlindPreferenceConstants.BLIND_MAX_TIME_SECOND,
+				Messages.getString("DialogSettingBlind.Maximum_time_17"),
+				visualizationSetting, 30, 180, 5, 30);
+		addField(maxTime);
+
+		addField(new ColorFieldEditor(
+				IBlindPreferenceConstants.BLIND_TABLE_BORDER_COLOR,
+				Messages.getString("DialogSettingBlind.Tabel_border_24"),
+				visualizationSetting));
+
+		addField(new ColorFieldEditor(
+				IBlindPreferenceConstants.BLIND_HEADING_TAGS_COLOR,
+				Messages.getString("DialogSettingBlind.Heading_tags_21"),
+				visualizationSetting));
+		addField(new ColorFieldEditor(
+				IBlindPreferenceConstants.BLIND_TABLE_HEADER_COLOR,
+				Messages.getString("DialogSettingBlind.Table_headers_20"),
+				visualizationSetting));
+		addField(new ColorFieldEditor(
+				IBlindPreferenceConstants.BLIND_INPUT_TAGS_COLOR,
+				Messages.getString("DialogSettingBlind.Input_tags_22"),
+				visualizationSetting));
+		addField(new ColorFieldEditor(
+				IBlindPreferenceConstants.BLIND_LABEL_TAGS_COLOR,
+				Messages.getString("DialogSettingBlind.Label_tags_23"),
+				visualizationSetting));
+
+		createInappropriateAltPart(parent);
+
+		if (Locale.getDefault().equals(Locale.JAPAN)) {
+			// TODO automatic encoding detect in visualization
+			createLanguagePart(parent);
+		}
+
+		boolean isLayoutMode = IBlindPreferenceConstants.BLIND_LAYOUT_MODE
+				.equals(getPreferenceStore().getString(
+						IBlindPreferenceConstants.BLIND_MODE));
+		visualizationSetting.setEnabled(isLayoutMode);
+		visualizationSetting.setVisible(isLayoutMode);
+
+	}
+
+	@Override
+	protected void performDefaults() {
+		super.performDefaults();
+
+		boolean isLayoutMode = IBlindPreferenceConstants.BLIND_LAYOUT_MODE
+				.equals(getPreferenceStore().getString(
+						IBlindPreferenceConstants.BLIND_MODE));
+		visualizationSetting.setEnabled(isLayoutMode);
+		visualizationSetting.setVisible(isLayoutMode);
+	}
+
+	@Override
+	public void propertyChange(PropertyChangeEvent event) {
+		super.propertyChange(event);
+
+		if (event.getSource() == modeRadio) {
+			if (!event.getOldValue().equals(event.getNewValue())) {
+				boolean isLayoutMode = IBlindPreferenceConstants.BLIND_LAYOUT_MODE
+						.equals(event.getNewValue());
+				visualizationSetting.setEnabled(isLayoutMode);
+				visualizationSetting.setVisible(isLayoutMode);
+			}
+		}
+	}
+
+	@Override
+	public boolean performOk() {
+		boolean result = super.performOk();
+
+		ParamBlind.refresh();
+
+		return result;
+	}
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/ui/preferences/EditNGWordDialog.java b/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/ui/preferences/EditNGWordDialog.java
new file mode 100644
index 0000000..dba9324
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/ui/preferences/EditNGWordDialog.java
@@ -0,0 +1,210 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.ui.preferences;
+
+import java.util.TreeSet;
+
+import org.eclipse.actf.util.ui.IDialogConstants;
+import org.eclipse.actf.visualization.engines.blind.internal.Messages;
+import org.eclipse.actf.visualization.engines.blind.util.TextChecker;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.MessageBox;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.Text;
+
+public class EditNGWordDialog {
+
+	// TODO use dialog
+
+	private static final String DIALOG_TITLE = Messages
+			.getString("AltDialog.TITLE"); //$NON-NLS-1$
+
+	private Shell shell;
+
+	private int iReturnCode = 0;
+
+	private String strFilter;
+
+	private Table ngWordTable;
+
+	private TextChecker textChecker = TextChecker.getInstance();
+
+	public EditNGWordDialog(Shell _shell) {
+		shell = new Shell(_shell, SWT.DIALOG_TRIM | SWT.PRIMARY_MODAL);
+		shell.setLayout(new GridLayout());
+
+	}
+
+	private boolean setNewValue() {
+		TreeSet<String> newSet = new TreeSet<String>();
+		for (TableItem item : ngWordTable.getItems()) {
+			String tmpS = item.getText();
+			if (tmpS != null && (tmpS = tmpS.trim()).length() > 0) {
+				newSet.add(tmpS);
+			}
+		}
+		textChecker.setNewAltSet(newSet);
+
+		return true;
+	}
+
+	private void createButtonControls() {
+		Composite composite = new Composite(shell, SWT.NULL);
+
+		GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_END
+				| GridData.VERTICAL_ALIGN_END);
+		gridData.heightHint = 50;
+		composite.setLayoutData(gridData);
+
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 2;
+		layout.horizontalSpacing = 20;
+		layout.marginWidth = 20;
+		layout.marginHeight = 20;
+		composite.setLayout(layout);
+
+		Button okButton = new Button(composite, SWT.PUSH);
+		okButton.setText(IDialogConstants.OK); //$NON-NLS-1$
+		okButton.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				if (setNewValue() == false)
+					return;
+				iReturnCode = 1;
+				shell.close();
+			}
+		});
+
+		Button cancelButton = new Button(composite, SWT.PUSH);
+		cancelButton.setText(IDialogConstants.CANCEL); //$NON-NLS-1$
+		cancelButton.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				iReturnCode = 0;
+				shell.close();
+			}
+		});
+
+		shell.setDefaultButton(okButton);
+	}
+
+	private void createSettingControls() {
+		GridLayout gridLayout1;
+
+		Composite composite = new Composite(shell, SWT.NULL);
+		composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		gridLayout1 = new GridLayout();
+		gridLayout1.numColumns = 2;
+		composite.setLayout(gridLayout1);
+
+		ngWordTable = new Table(composite, SWT.BORDER | SWT.FULL_SELECTION
+				| SWT.H_SCROLL | SWT.V_SCROLL);
+
+		GridData gridData1 = new GridData(GridData.FILL_BOTH);
+		gridData1.heightHint = 150;
+		gridData1.horizontalSpan = 2;
+		ngWordTable.setLayoutData(gridData1);
+		ngWordTable.setHeaderVisible(true);
+		ngWordTable.setLinesVisible(true);
+
+		TableColumn col = new TableColumn(ngWordTable, SWT.NONE);
+		col.setText(Messages.getString("AltDialog.Column_Name")); //$NON-NLS-1$
+		col.setWidth(200);
+
+		for (String value : textChecker.getInappropriateALTSet()) {
+			TableItem item = new TableItem(ngWordTable, SWT.NONE);
+			item.setText(value);
+		}
+
+		final Text text = new Text(composite, SWT.BORDER);
+		gridData1 = new GridData(GridData.FILL_HORIZONTAL);
+		gridData1.horizontalSpan = 2;
+		text.setLayoutData(gridData1);
+
+		Button addButton = new Button(composite, SWT.PUSH);
+		addButton.setText(IDialogConstants.ADD);
+		addButton.addSelectionListener(new SelectionAdapter() {
+
+			public void widgetSelected(SelectionEvent arg0) {
+				String str = text.getText().toLowerCase();
+				if (str.equals("")) { //$NON-NLS-1$
+					popupMessage(Messages.getString("AltDialog.MSG_No_String")); //$NON-NLS-1$
+					return;
+				}
+				int count = ngWordTable.getItemCount();
+				for (int i = 0; i < count; i++) {
+					if (ngWordTable.getItem(i).getText().equals(str)) {
+						popupMessage(Messages
+								.getString("AltDialog.MSG_Existed")); //$NON-NLS-1$
+						return;
+					}
+				}
+				TableItem item = new TableItem(ngWordTable, SWT.NONE);
+				item.setText(str);
+			}
+		});
+		Button delButton = new Button(composite, SWT.PUSH);
+		delButton.setText(IDialogConstants.DELETE);
+		delButton.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent arg0) {
+				if (ngWordTable.getSelectionCount() > 0) {
+					ngWordTable.getSelection()[0].dispose();
+				}
+			}
+		});
+
+
+	}
+
+	private void popupMessage(String str) {
+		MessageBox msgBox = new MessageBox(shell, SWT.OK);
+		msgBox.setMessage(str);
+		msgBox.open();
+	}
+
+	public int open() {
+		shell.setText(DIALOG_TITLE);
+		// shell.setSize(400, 300);
+
+		createSettingControls();
+
+		createButtonControls();
+
+		shell.setLocation(200, 200);
+		shell.pack();
+		shell.open();
+
+		Display display = shell.getDisplay();
+		while (!shell.isDisposed() || !display.readAndDispatch()) {
+			if (!display.readAndDispatch())
+				display.sleep();
+		}
+
+		return iReturnCode;
+	}
+
+	/**
+	 * @return
+	 */
+	public String getStrFilter() {
+		return strFilter;
+	}
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/ui/preferences/IBlindPreferenceConstants.java b/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/ui/preferences/IBlindPreferenceConstants.java
new file mode 100644
index 0000000..42b5ef6
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/ui/preferences/IBlindPreferenceConstants.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.ui.preferences;
+
+
+public interface IBlindPreferenceConstants {
+    
+    String NOT_FIRST_TIME = "blindViz.not_first_time";
+    
+    // BLIND Properties
+    String BLIND_LAYOUT_MODE = "layout";
+
+    String BLIND_BROWSER_MODE = "browser";
+
+    String BLIND_MODE = "actf.visualization.blind.mode";
+    
+    String BLIND_LANG = "actf.visualization.blind.lang";
+    
+    String LANG_EN = "en";
+
+    String LANG_JA = "ja";
+
+    String BLIND_MAX_TIME_SECOND = "ADesigner.blind.maxTimeSecond";
+
+    String BLIND_MAX_TIME_COLOR = "ADesigner.blind.maxTimeColor";
+
+    String BLIND_TABLE_HEADER_COLOR = "ADesigner.blind.tableheaderColor";
+
+    String BLIND_HEADING_TAGS_COLOR = "ADesigner.blind.headingTagsColor";
+
+    String BLIND_INPUT_TAGS_COLOR = "ADesigner.blind.inputTagsColor";
+
+    String BLIND_LABEL_TAGS_COLOR = "ADesigner.blind.labelTagsColor";
+
+    String BLIND_TABLE_BORDER_COLOR = "ADesigner.blind.tableBorderColor";
+    
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/ui/preferences/PreferenceInitializer.java b/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/ui/preferences/PreferenceInitializer.java
new file mode 100644
index 0000000..cad30df
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/ui/preferences/PreferenceInitializer.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.ui.preferences;
+
+import java.util.Locale;
+
+import org.eclipse.actf.visualization.engines.blind.BlindVizEnginePlugin;
+import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
+import org.eclipse.jface.preference.IPreferenceStore;
+
+
+
+
+public class PreferenceInitializer extends AbstractPreferenceInitializer {
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences()
+     */
+    public void initializeDefaultPreferences() {
+        IPreferenceStore store = BlindVizEnginePlugin.getDefault().getPreferenceStore();
+                
+        //TODO
+        if(Locale.getDefault().equals(Locale.JAPAN)){
+            store.setDefault(IBlindPreferenceConstants.BLIND_LANG, IBlindPreferenceConstants.LANG_JA);
+        }else{
+            store.setDefault(IBlindPreferenceConstants.BLIND_LANG, IBlindPreferenceConstants.LANG_EN);            
+        }
+                
+        store.setDefault(IBlindPreferenceConstants.BLIND_MODE, IBlindPreferenceConstants.BLIND_LAYOUT_MODE);
+        store.setDefault(IBlindPreferenceConstants.BLIND_MAX_TIME_SECOND, 90);
+        store.setDefault(IBlindPreferenceConstants.BLIND_MAX_TIME_COLOR, "0,64,64");
+        store.setDefault(IBlindPreferenceConstants.BLIND_TABLE_HEADER_COLOR, "153,255,0");
+        store.setDefault(IBlindPreferenceConstants.BLIND_HEADING_TAGS_COLOR, "51,204,255");
+        store.setDefault(IBlindPreferenceConstants.BLIND_INPUT_TAGS_COLOR, "255,153,0");
+        store.setDefault(IBlindPreferenceConstants.BLIND_LABEL_TAGS_COLOR, "255,128,255");
+        store.setDefault(IBlindPreferenceConstants.BLIND_TABLE_BORDER_COLOR, "0,0,0");
+                     
+    }
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/util/BlindVizResourceUtil.java b/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/util/BlindVizResourceUtil.java
new file mode 100644
index 0000000..44a9263
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/util/BlindVizResourceUtil.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.blind.util;
+
+import org.eclipse.actf.util.FileUtils;
+import org.eclipse.actf.visualization.engines.blind.BlindVizEnginePlugin;
+import org.eclipse.actf.visualization.eval.EvaluationPlugin;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.osgi.framework.Bundle;
+
+
+public class BlindVizResourceUtil {
+
+	public static void saveImages(String path) {
+		Bundle bundleChecker = Platform.getBundle(EvaluationPlugin.PLUGIN_ID);
+		
+	    FileUtils.saveToFile(bundleChecker, new Path("icons/Err.png"), false, path
+	            + "Err.png", true);
+	    FileUtils.saveToFile(bundleChecker, new Path("icons/Warn.png"), false, path
+	            + "Warn.png", true);
+	    FileUtils.saveToFile(bundleChecker, new Path("icons/Info.png"), false, path
+	            + "Info.png", true);
+	    FileUtils.saveToFile(bundleChecker, new Path("icons/star.gif"), false, path
+	            + "star.gif", true);
+	
+	    FileUtils.saveToFile(bundleChecker, new Path("icons/rating/Bad.png"), false, path
+	            + "Bad.png", true);
+	    FileUtils.saveToFile(bundleChecker, new Path("icons/rating/Good.png"), false,
+	            path + "Good.png", true);
+	    FileUtils.saveToFile(bundleChecker, new Path("icons/rating/Poor.png"), false,
+	            path + "Poor.png", true);
+	    FileUtils.saveToFile(bundleChecker, new Path("icons/rating/VeryGood.png"), false,
+	            path + "VeryGood.png", true);
+
+	    Bundle bundleBlind = Platform.getBundle(BlindVizEnginePlugin.PLUGIN_ID);
+	    
+	    FileUtils.saveToFile(bundleBlind, new Path("vizResources/images/clear.gif"),
+	            false, path + "clear.gif", true);
+	    FileUtils.saveToFile(bundleBlind, new Path("vizResources/images/dest.gif"), false,
+	            path + "dest.gif", true);
+	    FileUtils.saveToFile(bundleBlind, new Path("vizResources/images/draw.gif"), false,
+	            path + "draw.gif", true);
+	    FileUtils.saveToFile(bundleBlind,
+	            new Path("vizResources/images/exclawhite21.gif"), false, path + "exclawhite21.gif", true);
+	    FileUtils.saveToFile(bundleBlind, new Path("vizResources/images/face-sad.gif"),
+	            false, path + "face-sad.gif", true);
+	    FileUtils.saveToFile(bundleBlind, new Path("vizResources/images/face-smile.gif"),
+	            false, path + "face-smile.gif", true);
+	    FileUtils.saveToFile(bundleBlind, new Path("vizResources/images/face-usual.gif"),
+	            false, path + "face-usual.gif", true);
+	    FileUtils.saveToFile(bundleBlind, new Path("vizResources/images/jump.gif"), false,
+	            path + "jump.gif", true);
+	    FileUtils.saveToFile(bundleBlind, new Path("vizResources/images/line_filled.gif"),
+	            false, path + "line_filled.gif", true);
+	    FileUtils.saveToFile(bundleBlind, new Path("vizResources/images/logo.gif"), false,
+	            path + "logo.gif", true);
+	    FileUtils.saveToFile(bundleBlind, new Path("vizResources/images/move.gif"), false,
+	            path + "move.gif", true);
+	    FileUtils.saveToFile(bundleBlind, new Path("vizResources/images/refresh.gif"),
+	            false, path + "refresh.gif", true);
+	    FileUtils.saveToFile(bundleBlind, new Path("vizResources/images/stop.gif"), false,
+	            path + "stop.gif", true);
+	
+	}
+	
+	public static void saveScripts(String path){
+	    Bundle bundleBlind = Platform.getBundle(BlindVizEnginePlugin.PLUGIN_ID);
+	    FileUtils.saveToFile(bundleBlind, new Path("vizResources/scripts/highlight.js"), false,
+	            path + "highlight.js", true);
+	    FileUtils.saveToFile(bundleBlind, new Path("vizResources/scripts/highlight_moz.js"), false,
+	            path + "highlight_moz.js", true);
+	    FileUtils.saveToFile(bundleBlind, new Path("vizResources/scripts/highlight-dummy.js"), false,
+	            path + "highlight-dummy.js", true);
+		
+	}
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/util/ParamBlind.java b/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/util/ParamBlind.java
new file mode 100644
index 0000000..dac4e32
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/util/ParamBlind.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Hironobu TAKAGI - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.blind.util;
+
+import org.eclipse.actf.visualization.engines.blind.BlindVizEnginePlugin;
+import org.eclipse.actf.visualization.engines.blind.ui.preferences.IBlindPreferenceConstants;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.swt.graphics.RGB;
+
+
+public class ParamBlind {
+
+    public static final int EN = 0;
+
+    public static final int JP = 1;
+    
+    public static String BLIND_LAYOUT_MODE = IBlindPreferenceConstants.BLIND_LAYOUT_MODE;
+
+    public static String BLIND_BROWSER_MODE = IBlindPreferenceConstants.BLIND_BROWSER_MODE;
+
+    private static ParamBlind INSTANCE;
+    
+    public boolean oReplaceImage;
+
+    public boolean oVisualizArrival; // Visualize arrival time (default on)
+
+    public int iLanguage; //
+
+    public String visualizeMode;
+
+    public boolean bVisualizeTime;
+
+    public boolean bColorizeTags;
+
+    public boolean bVisualizeTable;
+
+    public int iMaxTime;
+
+    public RGB maxTimeColor;
+
+    public RGB tableHeaderColor;
+
+    public RGB headingTagsColor;
+
+    public RGB inputTagsColor;
+
+    public RGB labelTagsColor;
+
+    public RGB tableBorderColor;
+
+    public static ParamBlind getInstance() {
+        if (INSTANCE == null) {
+            INSTANCE = new ParamBlind();
+        }
+        return (INSTANCE);
+    }
+
+    public static void refresh(){
+        ParamBlind pb = getInstance();
+        setValues(pb);
+    }
+
+    private static void setValues(ParamBlind pb){
+        IPreferenceStore store = BlindVizEnginePlugin.getDefault().getPreferenceStore();
+
+        if(store.getDefaultString(IBlindPreferenceConstants.BLIND_LANG).equals(IBlindPreferenceConstants.LANG_JA)){
+            pb.iLanguage = JP;
+        }else{
+            pb.iLanguage = EN;
+        }
+
+        pb.visualizeMode = store.getString(IBlindPreferenceConstants.BLIND_MODE);
+        
+        pb.iMaxTime = store.getInt(IBlindPreferenceConstants.BLIND_MAX_TIME_SECOND);
+        pb.maxTimeColor = PreferenceConverter.getColor(store, IBlindPreferenceConstants.BLIND_MAX_TIME_COLOR);
+        pb.tableHeaderColor = PreferenceConverter.getColor(store, IBlindPreferenceConstants.BLIND_TABLE_HEADER_COLOR);
+        pb.headingTagsColor = PreferenceConverter.getColor(store, IBlindPreferenceConstants.BLIND_HEADING_TAGS_COLOR);
+        pb.inputTagsColor = PreferenceConverter.getColor(store, IBlindPreferenceConstants.BLIND_INPUT_TAGS_COLOR);
+        pb.labelTagsColor = PreferenceConverter.getColor(store, IBlindPreferenceConstants.BLIND_LABEL_TAGS_COLOR);
+        pb.tableBorderColor = PreferenceConverter.getColor(store, IBlindPreferenceConstants.BLIND_TABLE_BORDER_COLOR);
+        
+    }
+    
+    private ParamBlind() {
+
+        oReplaceImage = true;
+        oVisualizArrival = true;
+        bVisualizeTime = true;
+        bColorizeTags = true;
+        bVisualizeTable = true;
+    
+        setValues(this);
+    }
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/util/RadarChartNonSVG.java b/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/util/RadarChartNonSVG.java
new file mode 100644
index 0000000..59ae931
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/util/RadarChartNonSVG.java
@@ -0,0 +1,390 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.blind.util;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.Paint;
+import java.awt.Polygon;
+import java.awt.font.FontRenderContext;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.Line2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBufferInt;
+import java.awt.image.WritableRaster;
+import java.io.File;
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+
+public class RadarChartNonSVG {
+	
+	//TODO move to common util
+	
+	// min and max values of items
+	private static final int MIN_VALUE = 0;
+
+	private static final int MAX_VALUE = 100;
+
+	// image's attributes
+	private static final int IMAGE_WIDTH = 260;
+
+	private static final int IMAGE_HEIGHT = 150;
+
+	private static final Color IMAGE_BGCOLOR = Color.WHITE;
+
+	private static final double CIRCLE_CENTER_X = IMAGE_WIDTH / 2.0;
+
+	private static final double CIRCLE_CENTER_Y = IMAGE_HEIGHT / 2.0;
+
+	private static final Point2D CIRCLE_CENTER = new Point2D.Double(
+			CIRCLE_CENTER_X, CIRCLE_CENTER_Y);
+
+	private static final double CIRCLE_RADIUS = 40.0;
+
+	private static final Color CIRCLE_COLOR = Color.BLACK;
+
+	private static final Color BAR_COLOR = Color.BLACK;
+
+	private static final Color POLYGON_COLOR = new Color(102, 102, 255);
+
+	private static final Color NAMES_COLOR = Color.RED;
+
+	private static final Font NAMES_FONT = new Font("Default", Font.PLAIN, 16);
+
+	private static final FontRenderContext NAMES_FONT_RENDER_CONTEXT = new FontRenderContext(
+			null, true, true);
+
+	private static final int NAMES_MARGIN = 5;
+
+	private BufferedImage bufImage;
+
+	private Graphics2D g2d;
+
+	private int numItems;
+
+	private String[] names;
+
+	private int[] values;
+
+	private Point2D[] valueFullPoints;
+
+	private double[] valueTheta;
+
+	private Point2D[] valuePoints;
+
+	private static final int NUM_GRAD = 4; // grad = graduation
+
+	private static final double GRAD_LENGTH = 5.0;
+
+	private boolean smoothing = true; // hidden selection
+
+	public RadarChartNonSVG(String[] _names, int[] _values) throws Exception {
+		names = _names;
+		values = _values;
+		numItems = values.length;
+
+		if (numItems != names.length) {
+			throw new Exception(
+					"The numbers of names and values are different with each other.");
+		}
+		if (numItems < 3) {
+			throw new Exception("At least three items are needed.");
+		}
+		for (int i = 0; i < numItems; i++) {
+			if (isOutOfRange(values[i])) {
+				throw new Exception("The " + i + "-th value is out of range: "
+						+ values[i]);
+			}
+		}
+
+		createChart();
+	}
+
+	private boolean isOutOfRange(int _value) {
+		if (_value < MIN_VALUE || MAX_VALUE < _value) {
+			return (true);
+		} else {
+			return (false);
+		}
+	}
+
+	// general purpose utility
+	// compute new point located at (r, theta) position from the origin(x,y)
+	// be aware that mathmatical coordinate and image coordinate are different
+	private Point2D calcPointPolar(double _x, double _y, double _radius,
+			double _theta) {
+		double x = _x + _radius * Math.cos(_theta);
+		double y = _y - _radius * Math.sin(_theta);
+		return (new Point2D.Double(x, y));
+	}
+
+	private Point2D calcPointPolar(Point2D _p, double _radius, double _theta) {
+		return (calcPointPolar(_p.getX(), _p.getY(), _radius, _theta));
+	}
+
+	private void createChart() {
+		makePoints();
+
+		bufImage = new BufferedImage(IMAGE_WIDTH, IMAGE_HEIGHT,
+				BufferedImage.TYPE_INT_RGB);
+		g2d = bufImage.createGraphics();
+		g2d.setBackground(IMAGE_BGCOLOR);
+
+		if (smoothing) {
+			BufferedImage sandImage = new BufferedImage(
+					bufImage.getWidth() * 2, bufImage.getHeight() * 2,
+					BufferedImage.TYPE_INT_RGB);
+			Graphics2D sandG = sandImage.createGraphics();
+			Point2D[] enlargedValuePoints = new Point2D[numItems];
+			Point2D[] enlargedValueFullPoints = new Point2D[numItems];
+			for (int i = 0; i < numItems; i++) {
+				Point2D curPoint = valuePoints[i];
+				enlargedValuePoints[i] = new Point2D.Double(
+						curPoint.getX() * 2, curPoint.getY() * 2);
+				curPoint = valueFullPoints[i];
+				enlargedValueFullPoints[i] = new Point2D.Double(
+						curPoint.getX() * 2, curPoint.getY() * 2);
+			}
+			Point2D enlargedCircleCenter = new Point2D.Double(
+					CIRCLE_CENTER_X * 2, CIRCLE_CENTER_Y * 2);
+
+			fillBackground(sandImage, sandG, IMAGE_BGCOLOR);
+			drawEllipse(sandG, CIRCLE_COLOR, enlargedCircleCenter,
+					CIRCLE_RADIUS * 2);
+			fillPolygon(sandG, POLYGON_COLOR, BAR_COLOR, enlargedValuePoints);
+			drawBars(sandG, BAR_COLOR, enlargedValueFullPoints,
+					enlargedCircleCenter);
+
+			WritableRaster srcRaster = sandImage.copyData(null);
+			DataBufferInt srcBufInt = (DataBufferInt) (srcRaster
+					.getDataBuffer());
+			int[] srcArray = srcBufInt.getData();
+			WritableRaster destRaster = bufImage.copyData(null);
+			DataBufferInt destBufInt = (DataBufferInt) (destRaster
+					.getDataBuffer());
+			int[] destArray = destBufInt.getData();
+			float[][] fImageR = new float[IMAGE_HEIGHT + 1][IMAGE_WIDTH + 1];
+			float[][] fImageG = new float[IMAGE_HEIGHT + 1][IMAGE_WIDTH + 1];
+			float[][] fImageB = new float[IMAGE_HEIGHT + 1][IMAGE_WIDTH + 1];
+			for (int j = 0; j < IMAGE_HEIGHT; j++) {
+				for (int i = 0; i < IMAGE_WIDTH; i++) {
+					int nwIndex = 4 * j * IMAGE_WIDTH + i * 2;
+					int nw = srcArray[nwIndex];
+					int nwR = (nw >> 16) & 0xff;
+					int nwG = (nw >> 8) & 0xff;
+					int nwB = nw & 0xff;
+					int ne = srcArray[nwIndex + 1];
+					int neR = (ne >> 16) & 0xff;
+					int neG = (ne >> 8) & 0xff;
+					int neB = ne & 0xff;
+					int sw = srcArray[nwIndex + IMAGE_WIDTH * 2];
+					int swR = (sw >> 16) & 0xff;
+					int swG = (sw >> 8) & 0xff;
+					int swB = sw & 0xff;
+					int se = srcArray[nwIndex + IMAGE_WIDTH * 2 + 1];
+					int seR = (se >> 16) & 0xff;
+					int seG = (se >> 8) & 0xff;
+					int seB = se & 0xff;
+					fImageR[j][i] = (float) (nwR + neR + swR + seR) / 4.0f;
+					fImageG[j][i] = (float) (nwG + neG + swG + seG) / 4.0f;
+					fImageB[j][i] = (float) (nwB + neB + swB + seB) / 4.0f;
+				}
+			}
+			int k = 0;
+			for (int j = 0; j < IMAGE_HEIGHT; j++) {
+				for (int i = 0; i < IMAGE_WIDTH; i++) {
+					int newR = Math.round(fImageR[j][i]);
+					if (newR < 0)
+						newR = 0;
+					else if (255 < newR)
+						newR = 255;
+					float errR = fImageR[j][i] - newR;
+					fImageR[j][i + 1] += errR * 0.375f;
+					fImageR[j + 1][i] += errR * 0.375f;
+					fImageR[j + 1][i + 1] += errR * 0.25f;
+
+					int newG = Math.round(fImageG[j][i]);
+					if (newG < 0)
+						newG = 0;
+					else if (255 < newG)
+						newG = 255;
+					float errG = fImageG[j][i] - newG;
+					fImageG[j][i + 1] += errG * 0.375f;
+					fImageG[j + 1][i] += errG * 0.375f;
+					fImageG[j + 1][i + 1] += errG * 0.25f;
+
+					int newB = Math.round(fImageB[j][i]);
+					if (newB < 0)
+						newB = 0;
+					else if (255 < newB)
+						newB = 255;
+					float errB = fImageB[j][i] - newB;
+					fImageB[j][i + 1] += errB * 0.375f;
+					fImageB[j + 1][i] += errB * 0.375f;
+					fImageB[j + 1][i + 1] += errB * 0.25f;
+
+					destArray[k] = newR << 16 | newG << 8 | newB;
+					k++;
+				}
+			}
+			bufImage.setData(destRaster);
+		} else { // no smoothing
+			fillBackground(bufImage, g2d, IMAGE_BGCOLOR);
+			drawEllipse(g2d, CIRCLE_COLOR, CIRCLE_CENTER, CIRCLE_RADIUS);
+			fillPolygon(g2d, POLYGON_COLOR, BAR_COLOR, valuePoints);
+			drawBars(g2d, BAR_COLOR, valueFullPoints, CIRCLE_CENTER);
+		}
+
+		drawNames(g2d, NAMES_COLOR);
+	}
+
+	// preparing valueFullPoints, valueTheta, valuePoints
+	private void makePoints() {
+		valueFullPoints = new Point2D[numItems];
+		valueTheta = new double[numItems];
+		valuePoints = new Point2D[numItems];
+		double theta = 2.0 * Math.PI / numItems;
+		double startTheta = Math.PI / 2.0;
+		for (int i = 0; i < numItems; i++) {
+			valueTheta[i] = startTheta + i * theta;
+			valueFullPoints[i] = calcPointPolar(CIRCLE_CENTER_X,
+					CIRCLE_CENTER_Y, CIRCLE_RADIUS, valueTheta[i]);
+			double ratio = ((double) values[i]) / MAX_VALUE;
+			valuePoints[i] = new Point2D.Double(CIRCLE_CENTER_X * (1 - ratio)
+					+ valueFullPoints[i].getX() * ratio, CIRCLE_CENTER_Y
+					* (1 - ratio) + valueFullPoints[i].getY() * ratio);
+		}
+	}
+
+	private void fillBackground(BufferedImage _bufIm, Graphics2D _g2d, Color _c) {
+		Paint curPaint = _g2d.getPaint();
+		_g2d.setPaint(_c);
+		Rectangle2D r2d = new Rectangle2D.Double(0, 0, _bufIm.getWidth(),
+				_bufIm.getHeight());
+		_g2d.fill(r2d);
+		_g2d.setPaint(curPaint);
+	}
+
+	private void drawEllipse(Graphics2D _g2d, Color _c, Point2D _center,
+			double _r) {
+		Paint curPaint = _g2d.getPaint();
+		_g2d.setPaint(_c);
+		double boundaryX = _center.getX() - _r;
+		double boundaryY = _center.getY() - _r;
+		double boundaryW = _r * 2.0f;
+		Ellipse2D e2d = new Ellipse2D.Double(boundaryX, boundaryY, boundaryW,
+				boundaryW);
+		_g2d.draw(e2d);
+		_g2d.setPaint(curPaint);
+	}
+
+	private void fillPolygon(Graphics2D _g2d, Color _fill, Color _contour,
+			Point2D[] _points) {
+		Paint curPaint = _g2d.getPaint();
+		int[] xpoints = new int[numItems];
+		int[] ypoints = new int[numItems];
+		for (int i = 0; i < numItems; i++) {
+			xpoints[i] = (int) (_points[i].getX());
+			ypoints[i] = (int) (_points[i].getY());
+		}
+		// Polygon has int-precision only
+		Polygon pol = new Polygon(xpoints, ypoints, numItems);
+		_g2d.setPaint(_fill);
+		_g2d.fill(pol);
+
+		// the countour will be drawn in double-precision
+		_g2d.setPaint(_contour);
+		Line2D l2d = new Line2D.Double(_points[numItems - 1], _points[0]);
+		_g2d.draw(l2d);
+		for (int i = 0; i < numItems - 1; i++) {
+			l2d = new Line2D.Double(_points[i], _points[i + 1]);
+			_g2d.draw(l2d);
+		}
+
+		_g2d.setPaint(curPaint);
+	}
+
+	private void drawBars(Graphics2D _g2d, Color _c, Point2D[] _points,
+			Point2D _circleCenter) {
+		double circleCenterX = _circleCenter.getX();
+		double circleCenterY = _circleCenter.getY();
+		Paint curPaint = _g2d.getPaint();
+		_g2d.setPaint(_c);
+		for (int i = 0; i < numItems; i++) {
+			double fullX = _points[i].getX();
+			double fullY = _points[i].getY();
+			Line2D l2d = new Line2D.Double(circleCenterX, circleCenterY, fullX,
+					fullY);
+			_g2d.draw(l2d);
+			for (int j = 1; j < NUM_GRAD; j++) {
+				double ratio = ((double) j) / NUM_GRAD;
+				Point2D gradCenter = new Point2D.Double(circleCenterX
+						* (1 - ratio) + fullX * ratio, circleCenterY
+						* (1 - ratio) + fullY * ratio);
+				Point2D grad0 = calcPointPolar(gradCenter, GRAD_LENGTH,
+						valueTheta[i] + Math.PI / 2.0);
+				Point2D grad1 = calcPointPolar(gradCenter, GRAD_LENGTH,
+						valueTheta[i] - Math.PI / 2.0);
+				l2d = new Line2D.Double(grad0, grad1);
+				_g2d.draw(l2d);
+			}
+		}
+		_g2d.setPaint(curPaint);
+	}
+
+	private void drawNames(Graphics2D _g2d, Color _c) {
+		Paint curPaint = _g2d.getPaint();
+		_g2d.setPaint(_c);
+		_g2d.setFont(NAMES_FONT);
+
+		for (int i = 0; i < numItems; i++) {
+			Rectangle2D boundaryBox = NAMES_FONT.getStringBounds(names[i],
+					NAMES_FONT_RENDER_CONTEXT);
+			double stringWidth = boundaryBox.getWidth();
+			double stringHeight = boundaryBox.getHeight();
+
+			double fullX = valueFullPoints[i].getX();
+			double fullY = valueFullPoints[i].getY();
+			float x = 0.0f;
+			float y = 0.0f;
+			if (fullX < CIRCLE_CENTER_X) {
+				x = (float) (fullX - stringWidth - NAMES_MARGIN);
+				y = (float) (fullY + stringHeight / 2.0);
+			} else if (CIRCLE_CENTER_X < fullX) {
+				x = (float) (fullX + NAMES_MARGIN);
+				y = (float) (fullY + stringHeight / 2.0);
+			} else {
+				x = (float) (fullX - stringWidth / 2.0);
+				if (fullY < CIRCLE_CENTER_Y) {
+					y = (float) (fullY - NAMES_MARGIN);
+				} else {
+					y = (float) (fullY + stringHeight + NAMES_MARGIN);
+				}
+			}
+
+			_g2d.drawString(names[i], x, y);
+		}
+
+		_g2d.setPaint(curPaint);
+	}
+
+	public BufferedImage getBufferedImage() {
+		return (bufImage);
+	}
+
+	public void writeToPNG(File target) throws IOException {
+		ImageIO.write(bufImage, "PNG", target);
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/util/TextChecker.java b/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/util/TextChecker.java
new file mode 100644
index 0000000..6e5edb1
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/src/org/eclipse/actf/visualization/engines/blind/util/TextChecker.java
@@ -0,0 +1,238 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.blind.util;
+
+import java.io.InputStream;
+import java.util.HashSet;
+import java.util.Properties;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.eclipse.actf.visualization.engines.blind.BlindVizEnginePlugin;
+import org.eclipse.actf.visualization.engines.blind.ui.preferences.IBlindPreferenceConstants;
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Preferences;
+
+
+
+public class TextChecker {
+
+    public static String KIGOU = "(\\p{InMathematicalOperators}|\\p{InGeometricShapes}|\\p{InMiscellaneousSymbols}|\\p{InBoxDrawing}|\\p{InGeneralPunctuation}|\\p{InCJKSymbolsandPunctuation}|\\p{InArrows})";
+
+    public static String NIHONGO = "(\\p{InCJKUnifiedIdeographs}|\\p{InHiragana}|\\p{InKatakana})";
+
+    public static String KANJI = "(\\p{InCJKUnifiedIdeographs})";
+
+    private static final String ALT_TEXT_PROPERTIES_FILE = "altText.properties";
+
+    private static String INAPP_ALT = "blindViz.inappropriateAlt_";
+
+    private static String POSSIBLE_INAPP_ALT = "blindViz.possible_inappAlt_";
+
+    private static TextChecker INSTANCE;
+
+    private Set<String> ngwordset = new TreeSet<String>();
+
+    private Set<String> ngwordset2 = new TreeSet<String>();
+
+    private Preferences pref = BlindVizEnginePlugin.getDefault().getPluginPreferences();
+
+    // TODO spell out check
+
+    // separated from VisualizeEngine
+    private TextChecker() {
+
+        if (!pref.getBoolean(IBlindPreferenceConstants.NOT_FIRST_TIME)) {
+
+            Properties prop = new Properties();
+            try {
+                InputStream prefIS = FileLocator.openStream(Platform
+                        .getBundle(BlindVizEnginePlugin.PLUGIN_ID), new Path(
+                        "config/"+ALT_TEXT_PROPERTIES_FILE), false);
+                if (prefIS != null) {
+                    prop.load(prefIS);
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+                       
+            
+            for (Object key : prop.keySet()) {
+                String keyS = (String) key;
+                String value;
+                if (keyS.startsWith(INAPP_ALT)) {
+                    value = prop.getProperty(keyS);
+                    if (value.length() > 0) {
+                        ngwordset.add(value);
+                    }
+                } else if (keyS.startsWith(POSSIBLE_INAPP_ALT)) {
+                    value = prop.getProperty(keyS);
+                    if (value.length() > 0) {
+                        ngwordset2.add(value);
+                    }
+                }
+            }
+
+            resetPreferences();
+
+        } else {
+            for (int i = 0; pref.contains(INAPP_ALT + i); i++) {
+                String value = pref.getString(INAPP_ALT + i);
+                if (value.length() > 0) {
+                    ngwordset.add(value);
+                }
+            }
+            for (int i = 0; pref.contains(POSSIBLE_INAPP_ALT + i); i++) {
+                String value = pref.getString(POSSIBLE_INAPP_ALT + i);
+                if (value.length() > 0) {
+                    ngwordset2.add(value);
+                }
+            }
+        }
+    }
+
+    public static TextChecker getInstance() {
+        if (INSTANCE == null) {
+            INSTANCE = new TextChecker();
+        }
+        return INSTANCE;
+    }
+
+    public boolean isRedundantText(String prevText, String curText) {
+
+        if ((prevText != null) && (prevText.length() > 1) && (curText.length() > 1)) {
+
+            String prevText2 = prevText.replaceAll("\\[|\\]|\\.|\\!|\\>", "");
+            prevText2 = prevText2.trim();
+
+            String curText2 = curText.replaceAll("\\[|\\]|\\.|\\!|\\>", "");
+            curText2 = curText2.trim();
+
+            if (curText2.equalsIgnoreCase(prevText2)) {
+                return true;
+            }
+        }
+        return (false);
+    }
+
+    public boolean isInappropriateAlt(String alt) {
+        String tmpAlt = alt.trim();
+        tmpAlt = tmpAlt.toLowerCase();
+
+        if (ngwordset.contains(tmpAlt) || isEndWithImageExt(tmpAlt)) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    public int isInappropriateAlt2(String alt) {
+        String[] tmpSA = alt.toLowerCase().split("(" + KIGOU + "|\\p{Punct}|\\p{Space})");
+        int count = 0;
+        int all = 0;
+        int charLength = 0;
+        for (int i = 0; i < tmpSA.length; i++) {
+            if (tmpSA[i].length() > 0) {
+                all++;
+            }
+            charLength += tmpSA[i].length();
+            if (ngwordset2.contains(tmpSA[i])) {
+                // System.out.println("alt: "+tmpSA[i]);
+                count++;
+            }
+        }
+
+        int org = alt.length();
+
+        // TODO combination
+        if (org > 0 && alt.matches(".*(\\p{Alpha}\\p{Space}){4,}.*")) {//TODO 4 is appropriate?
+            return 3;
+        }
+
+        // TODO Japanese check
+        if (org > 0 && ((double) charLength / (double) org) < 0.5) {
+            // TODO divide error (use ratio)
+
+        	//spaces 
+            if (!alt.matches("\\p{Space}*")) {
+                return 1;
+            }
+        }
+
+        // System.out.println(count+" "+all+":"+(double)count/(double)all);
+        if ((double) count / (double) all > 0.6) {
+            return 2;
+        } else if ((double) count / (double) all > 0.3) {
+            return 1;
+        }
+        return 0;
+    }
+
+    private boolean isEndWithImageExt(String alt) {
+        String tmpS = alt.trim().toLowerCase();
+        String regexp3 = "\\p{Print}*\\.(jpg|jpeg|gif|png)";
+        return (tmpS.matches(regexp3));
+    }
+
+    public boolean isSeparatedJapaneseChars(String target) {
+        String tmpS = target.trim();
+        tmpS = tmpS.toLowerCase();
+
+        //\u3000 = double byte space
+        String regexp1 = KIGOU + "*(\\p{Space}|\u3000)?(" + NIHONGO + "((\\p{Space}|\u3000)+" + NIHONGO + ")+)"
+                + "(\\p{Space}|\u3000)?" + KIGOU + "*";
+        String regexp2 = ".*" + KANJI + ".*";
+        //TODO rewrite regexp (combination of Japanese and English)
+
+        if ((tmpS.matches(regexp1) && tmpS.matches(regexp2))) {
+            return true;
+        } else {
+            return (false);
+        }
+    }
+
+    public Set<String> getInappropriateALTSet() {
+        Set<String> tmpSet = new HashSet<String>();
+        tmpSet.addAll(ngwordset);
+        return tmpSet;
+    }
+
+    private void resetPreferences() {
+        int i = 0;
+        for (String value : ngwordset) {
+            pref.setValue(INAPP_ALT + i, value);
+            i++;
+        }
+        for (int j = i; pref.contains(INAPP_ALT + j); j++) {
+            pref.setValue(INAPP_ALT + j, "");
+        }
+
+        i = 0;
+        for (String value : ngwordset2) {
+            pref.setValue(POSSIBLE_INAPP_ALT + i, value);
+            i++;
+        }
+        for (int j = i; pref.contains(POSSIBLE_INAPP_ALT + j); j++) {
+            pref.setValue(POSSIBLE_INAPP_ALT + j, "");
+        }
+    }
+
+    public void setNewAltSet(Set<String> inappAltSet) {
+        if (inappAltSet != null) {
+            ngwordset = inappAltSet;
+        }
+        resetPreferences();
+    }
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/clear.gif b/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/clear.gif
new file mode 100644
index 0000000..a4b9b93
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/clear.gif
Binary files differ
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/dest.gif b/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/dest.gif
new file mode 100644
index 0000000..69723b5
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/dest.gif
Binary files differ
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/draw.gif b/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/draw.gif
new file mode 100644
index 0000000..e04d133
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/draw.gif
Binary files differ
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/exclawhite21.gif b/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/exclawhite21.gif
new file mode 100644
index 0000000..f704b8a
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/exclawhite21.gif
Binary files differ
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/face-sad.gif b/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/face-sad.gif
new file mode 100644
index 0000000..f2b398c
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/face-sad.gif
Binary files differ
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/face-smile.gif b/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/face-smile.gif
new file mode 100644
index 0000000..2b9e4fa
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/face-smile.gif
Binary files differ
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/face-usual.gif b/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/face-usual.gif
new file mode 100644
index 0000000..5e31f5a
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/face-usual.gif
Binary files differ
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/jump.gif b/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/jump.gif
new file mode 100644
index 0000000..a28bf55
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/jump.gif
Binary files differ
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/line_filled.gif b/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/line_filled.gif
new file mode 100644
index 0000000..39f63c3
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/line_filled.gif
Binary files differ
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/logo.gif b/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/logo.gif
new file mode 100644
index 0000000..26cf60b
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/logo.gif
Binary files differ
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/move.gif b/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/move.gif
new file mode 100644
index 0000000..a5255c9
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/move.gif
Binary files differ
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/refresh.gif b/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/refresh.gif
new file mode 100644
index 0000000..4cfc43c
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/refresh.gif
Binary files differ
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/stop.gif b/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/stop.gif
new file mode 100644
index 0000000..78e21a1
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/images/stop.gif
Binary files differ
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/scripts/highlight-dummy.js b/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/scripts/highlight-dummy.js
new file mode 100644
index 0000000..3c40ed3
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/scripts/highlight-dummy.js
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation
+ *******************************************************************************/ 
+
+function setHighlight(firstNode, lastNode) {
+ 
+}
+function clearHighlight() {
+}
+
+function _scrollToVisible(node) {
+}
+
+function moveDivTo(div,left,top){
+}
+function getEventPageX(e){
+}
+function getEventPageY(e){
+}
+
+function updateBaloon(curId) {
+}
+
+function stopHandler(){
+}
+
+function turnonHandler(){	
+}
+
+function init(){
+}
+
+function nodeLoop(nodeLoop){
+}
+
+function movingHandler(){
+}
+
+function turnoffHandler(){
+}
+
+function cancelMapLink(event) {
+}
+function cancelLink() {
+}
+
+function search_Jump() {
+} 
+
+function looplink_Jump(nodeImg,z2) {
+}
+
+function writeLine(sx,sy,dx,dy,font,leap,visibile){
+}
+
+function search_Line(Start,End,Line) {
+} 
+function set_panel() {
+} 
+
+function refresh_Jump(){
+}
+function control_moving(){
+}
+function clean_Line() {
+} 
+function draw_all_Line() {
+} 
+
+function highlightTr( _tr ){
+}
+
+function clearTrHighlight(){
+}
+
+
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/scripts/highlight.js b/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/scripts/highlight.js
new file mode 100644
index 0000000..f4784e0
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/scripts/highlight.js
@@ -0,0 +1,711 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation
+ *******************************************************************************/ 
+
+var highlightedNodeArray = new Array();
+var divArray = new Array();
+var highlightedNodeCount = 0;
+var HIGHLIGHT_BORDER_WIDTH = 4;
+
+var x1=0;
+var x2=0;
+var y1=0;
+var y2=0;
+var idNumber=0;
+var idLine=0;
+var alength=30;
+var angleValue=30;
+var font_Size=16;
+var sux;
+var suy;
+var arrayIdex=0;
+arrayLine=new Array();
+arrayPoint=new Array();
+var start_switch =true;
+var est;
+var idNumber_Old=0;
+var refresh=false;
+var HIGHLIGHT_BGCOLOR = "#ffdddd";
+var MAX_PROBLEM_SELECTION = 30;
+
+// call it like: setHighlight2(new Array(43,47,49), new Array(45,47,50));
+function setHighlight2(firstNodeArray, lastNodeArray) {	
+  if(firstNodeArray.length > MAX_PROBLEM_SELECTION) {
+	if (!confirm("Your selection contains many elements. It will take time to highlight all of them. Do you want to continue?")) {
+	  return;
+	}
+  }
+  clearHighlight();	
+  var bScrolled=false;
+  var size = firstNodeArray.length;	
+  for (var i = 0; i < size; i++) {
+	for(var j = firstNodeArray[i]; j <= lastNodeArray[i]; j++) {	
+	  curNode = document.all["id" + j];
+	  if(curNode!=null){				
+		if (curNode != null && !bScrolled) {
+		  _scrollToVisible(curNode);
+		  bScrolled=true;
+		}
+		highlight(curNode);
+	  }
+	}
+  }	
+}
+
+function setHighlight(firstNode, lastNode) {
+  clearHighlight();
+  for(var i = firstNode; i < lastNode + 1; i++) {
+	curNode = document.all["id" + i];
+	if(curNode!=null){					
+	  count =0;
+	  if (curNode != null) {
+		_scrollToVisible(curNode);
+	  }			
+	  highlight(curNode);
+	}
+  }
+}
+
+function highlight(node){
+  if(node == null)
+    return ;
+		
+  if(!divArray[highlightedNodeCount]){
+	var div = divArray[highlightedNodeCount] = document.createElement("div");
+	div.style.display = "none";
+	div.style.position = "absolute";
+	div.style.border = HIGHLIGHT_BORDER_WIDTH+"px solid yellow";
+	document.body.appendChild(div);
+  }
+  highlightedNodeArray[highlightedNodeCount] = node;
+  setDivStyle(node, divArray[highlightedNodeCount]);
+  highlightedNodeCount++;
+}
+
+function setDivStyle(node, div){
+  var left=0, top=0;
+  var width=node.offsetWidth;
+  var height=node.offsetHeight;
+  
+  if ((node.tagName.toLowerCase() == "area") || (node.tagName.toLowerCase() == "map")) return;
+  
+  while( node ){
+	top+=node.offsetTop;
+	left+=node.offsetLeft;
+	node = node.offsetParent;
+  }
+
+  div.style.left = left-HIGHLIGHT_BORDER_WIDTH;
+  div.style.top = top-HIGHLIGHT_BORDER_WIDTH;
+  div.style.width = width;
+  div.style.height = height;
+  div.style.display = "block";
+
+}
+
+function reHighlight(){
+  for(var i=0; i<highlightedNodeCount; i++){
+  	setDivStyle(highlightedNodeArray[i], divArray[i]);
+  }
+}
+
+function clearHighlight() {
+  for(var i = 0; i < highlightedNodeCount; i++){
+	divArray[i].style.display = "none";
+  }
+  highlightedNodeCount = 0;
+}
+
+function _scrollToVisible(node) {
+  var left=0, top=0;
+  var width=node.offsetWidth;
+  var height=node.offsetHeight;
+
+  if ((node.tagName.toLowerCase() == "area") || (node.tagName.toLowerCase() == "map")) return;
+
+  while( node!=document.body )
+	{
+	  top+=node.offsetTop;
+	  left+=node.offsetLeft;
+	  node = node.offsetParent;
+	}
+  var ele;
+  if(document.documentElement.clientHeight==0){	
+	ele=node;		
+  }else{
+	ele=document.documentElement;
+  }
+  if((ele.scrollLeft>left)||(ele.scrollLeft<(left+width-ele.clientWidth))){
+	ele.scrollLeft=left;	
+  }
+  if((ele.scrollTop>top)||(ele.scrollTop<(top+height-ele.clientHeight))){
+	ele.scrollTop=top;					
+  }
+}
+
+
+// popup from here
+
+function moveDivTo(div,left,top){
+  div.style.pixelLeft=left;
+  div.style.pixelTop =top;
+  return;
+}
+function getEventPageX(e){
+  var ele;
+  if(document.documentElement.clientHeight==0){	
+	ele=document.body;		
+  }else{
+	ele=document.documentElement;
+  }
+  return ele.scrollLeft+event.clientX;
+}
+function getEventPageY(e){
+  var ele;
+  if(document.documentElement.clientHeight==0){	
+	ele=document.body;		
+  }else{
+	ele=document.documentElement;
+  }
+  return ele.scrollTop+event.clientY;
+}
+
+var balloonDiv=null; 
+var messageDiv=null; 
+
+function updateBaloon(curId) {
+  if(messageDiv != null){
+	messageDiv.style.visibility = "visible";
+	messageDiv.innerHTML = "<b>&nbsp";
+	messageDiv.innerHTML += id2time[curId];
+	messageDiv.innerHTML += "</b> seconds from top.";
+
+	if (id2time[curId] > 90) {
+	  messageDiv.innerHTML += "<img src='" + baseUrl +acc_imageDir+ "face-sad.gif'>";						
+	} else if (id2time[curId] > 30) { 
+	  messageDiv.innerHTML += "<img src='" + baseUrl +acc_imageDir+ "face-usual.gif'>";
+	} else {
+	  messageDiv.innerHTML += "<img src='" + baseUrl +acc_imageDir+ "face-smile.gif'>";
+	}
+	if (id2comment[curId].length > 0) {
+	  messageDiv.innerHTML += "<br><b>" + id2comment[curId] + "</b>";
+	}
+
+  }
+}
+
+function stopHandler(){
+
+  var e = window.event;
+  set_panel();
+  if (e.srcElement != null) {
+	if ((servletMode == false ) || getEventPageY(e)<document.getElementById('suwen').offsetTop) {
+	  if (id2time[e.srcElement.id] != null) {
+		updateBaloon(e.srcElement.id);
+	  }
+	} 
+  }
+
+}
+
+function turnonHandler(){
+  var e = window.event;
+  document.onmouseup=movingHandler;
+  document.onmousemove=movingHandler;
+  document.onmousedown=turnoffHandler;
+
+  return false;
+}
+
+function init(){
+  if(baloonSwitch == 1){
+	balloonDiv=document.getElementById('balloon');    
+	messageDiv=document.getElementById('message');    
+	if( balloonDiv != null && messageDiv!=null){
+	  document.onmouseup=movingHandler;
+	  document.onmousemove=movingHandler;
+	  document.onmousedown=turnoffHandler;
+	}
+  } 
+  document.onclick=cancelLink;
+}
+
+function movingHandler(){
+
+  var e = window.event;
+  window.event.returnValue = false;
+  set_panel();
+  if((servletMode == false ) || getEventPageY(e)<document.getElementById('suwen').offsetTop){
+	if(start_switch==true){
+	  moveDivTo(balloonDiv,getEventPageX(e)+20,getEventPageY(e));
+	}
+	if (e.srcElement != null) {
+	  if (id2time[e.srcElement.id] != null) {
+		updateBaloon(e.srcElement.id);
+	  }
+	} 
+  }
+
+}
+
+function turnoffHandler(){
+  init();
+  document.onmousemove=stopHandler;
+  document.onmousedown=turnonHandler;
+  return false;
+}
+
+function cancelMapLink(event) {
+  event.returnValue = false;
+  cancelLink();
+}
+function cancelLink() {
+  var e = window.event;
+  var nodes =e.srcElement;
+  set_panel();
+
+  window.event.returnValue = false;
+  while(  nodes != null && nodes.tagName != null){
+	if( nodes.tagName.toLowerCase() == "img") {
+	  if(nodes.getAttribute('src').toLowerCase().indexOf("jump.gif") > 0 
+		 || nodes.getAttribute('src').toLowerCase().indexOf("dest.gif") > 0){
+		alt=nodes.getAttribute('alt');
+		destName=alt.substring(alt.lastIndexOf(":")+2);
+		if(nodes.getAttribute('src').toLowerCase().indexOf("jump.gif") > 0){
+		  sourceName=nodes.getAttribute('name');
+		} else{
+		  sourceName=null;
+		}
+		if(sourceName==null){
+		  for (var i=0;i<arrayLine.length;i++){
+			if(arrayLine[i]["destName"]==destName){
+			  search_Line(arrayLine[i]["Start"],arrayLine[i]["End"],i);
+			}
+		  }
+		  break;
+		} else {
+		  for (var i=0;i<arrayLine.length;i++){
+			if(arrayLine[i]["destName"]==destName && arrayLine[i]["sourceName"]==sourceName){
+			  search_Line(arrayLine[i]["Start"],arrayLine[i]["End"],i);
+			}
+		  }
+		  break;
+		}
+
+
+	  }
+	}
+
+	nodes=nodes.parentNode;
+	if(nodes==null)
+	  break;
+	node_Id=nodes.getAttribute('id');
+	if( node_Id!=null && !isNaN(parseInt(node_Id)) && node_Id>=0 && node_Id<idNumber) {
+	  for (var i=0;i<arrayLine.length;i++){
+		if(arrayLine[i]["Start"]<=node_Id
+		   && arrayLine[i]["End"]>=node_Id){
+		  search_Line(arrayLine[i]["Start"],arrayLine[i]["End"],i);
+		  break;
+		}
+	  }
+	}
+	if(nodes!= null && nodes.firstChild != null){
+	  if( nodes.firstChild.tagName !=null && nodes.firstChild.tagName.toLowerCase() == "img"){
+		if(nodes.firstChild.getAttribute('src').toLowerCase().indexOf("jump.gif") > 0 
+		   || nodes.firstChild.getAttribute('src').toLowerCase().indexOf("dest.gif") > 0){
+		  alt=nodes.firstChild.getAttribute('alt');
+		  destName=alt.substring(alt.lastIndexOf(":")+2);
+		  if(nodes.firstChild.getAttribute('src').toLowerCase().indexOf("jump.gif") > 0){
+			sourceName=nodes.firstChild.getAttribute('name');
+		  } else{
+			sourceName=null;
+		  }
+		  if(sourceName==null){
+			for (var i=0;i<arrayLine.length;i++){
+			  if(arrayLine[i]["destName"]==destName){
+				search_Line(arrayLine[i]["Start"],arrayLine[i]["End"],i);
+			  }
+			}
+			break;
+		  } else {
+			for (var i=0;i<arrayLine.length;i++){
+			  if(arrayLine[i]["destName"]==destName && arrayLine[i]["sourceName"]==sourceName){
+				search_Line(arrayLine[i]["Start"],arrayLine[i]["End"],i);
+			  }
+			}
+			break;
+		  }
+
+		}
+	  }
+	  break;
+
+	}
+
+
+  }
+}
+
+function search_Jump() {
+  var i=0;
+  var dest;
+  var alt;
+  init();
+  est =document.getElementById('test');
+  //	est.style.visibility = "visible";
+  est.style.visibility = "hidden";
+  est.innerHTML = "<img src='" + acc_imageDir+"line_filled.gif'>";
+  var x1=arrayLine.length;
+	
+  if(refresh==true){
+	if(idNumber<1500||confirm("This process may take 30 seconds or more. Would you like to continue it?")==1){
+	  for (var h=0;h<x1;h++){
+		var su=arrayLine[h]["sourceName"];
+		nodelist=document.getElementsByName(su);
+		node=nodelist[0];
+		looplink_Jump(node,arrayLine[h]["destName"]);
+	  }
+	}
+  } else {
+	while(true){
+	  if( document.getElementsByTagName("img")[i]==null){
+		break;
+	  }
+	  if(document.getElementsByTagName("img")[i].getAttribute('src').toLowerCase().indexOf("jump.gif") > 0){
+		alt=document.getElementsByTagName("img")[i].getAttribute('alt');
+		dest=alt.substring(alt.indexOf(":")+2);
+		looplink_Jump(document.getElementsByTagName("img")[i],dest);
+	  }
+	  i=i+1;
+			
+	  if(isAlert==true && idNumber>2000){
+		alert("This page contains too many intra-page links.\nIn this page, aDesigner can visualize some of intra-page links by arrow.");
+		break;
+	  }
+
+	}
+  }
+} 
+
+function looplink_Jump(nodeImg,z2) {
+  x1=0;
+  x2=0;
+  y1=0;
+  y2=0;
+
+  var node=nodeImg;
+
+  //				while( node!=document.body){
+  while( node!=null){
+	if(node.nodeName !=null && node.nodeName!="TR"){
+	  if(!isNaN(node.offsetLeft)){
+		x1 =x1+node.offsetLeft;
+	  }
+	  if(!isNaN(node.offsetTop)){
+		y1 =y1+node.offsetTop;
+	  }
+	}
+	node = node.offsetParent;
+  }
+  nodelist=document.getElementsByName(z2);
+  if(nodelist.length>1){
+	for(var k=0;k<nodelist.length;k++){
+	  if(nodelist[k].firstChild!=null && nodelist[k].firstChild.nodeName !=null && nodelist[k].firstChild.nodeName.toLowerCase()=="img"){
+		node=nodelist[k];
+		break;
+	  }
+	}
+  } else {
+	node=nodelist[0];
+  }
+  //				while( node!=document.body){
+  while( node!=null){
+	if( node.nodeName !=null && node.nodeName!="TR"){
+	  if(!isNaN(node.offsetLeft)){
+		x2 =x2+node.offsetLeft;
+	  } 
+	  if(!isNaN(node.offsetTop)){
+		y2 =y2+node.offsetTop;
+	  }
+	}
+	node = node.offsetParent;
+  }
+
+  var x3=x1-x2;
+
+  var copynode;
+  var lPointx;
+  var lPointy;
+  var rPointx;
+  var rPointy;
+  var angle;
+  if(x2<5 && y2<5){
+	x2=20;
+	y2=20;
+  }
+  if (arrayLine[arrayIdex]==null){
+	arrayLine[arrayIdex]=new Array();
+  }
+  arrayLine[arrayIdex]["sourceName"]=nodeImg.getAttribute('name');
+  arrayLine[arrayIdex]["destName"]=z2;
+
+  arrayLine[arrayIdex]["Start"]=idNumber;
+  if(refresh==false){
+	arrayLine[arrayIdex]["Type"]="hidden";
+  }
+  idLine=0;
+  writeLine(x1+5,y1+5,x2,y2,0,50,arrayLine[arrayIdex]["Type"]);
+  angle_Value=angleValue/57.3;
+  if(y2>y1){
+	angle=Math.atan((y2-y1)/x3);
+	if(angle<0){
+	  angle=angle+180/57.3;
+	}
+	lPointx=x2+Math.cos(angle+angle_Value)*alength;
+	lPointy=y2-Math.sin(angle+angle_Value)*alength;
+	rPointx=x2+Math.cos(angle-angle_Value)*alength;
+	rPointy=y2-Math.sin(angle-angle_Value)*alength;
+	writeLine(lPointx,lPointy,x2,y2,font_Size,5,arrayLine[arrayIdex]["Type"]);
+	writeLine(rPointx,rPointy,x2,y2,font_Size,5,arrayLine[arrayIdex]["Type"]);
+  } else {
+	angle=Math.atan(Math.abs(x3/(y2-y1)));
+
+	if(x2<x1){
+	  lPointy=y2+Math.cos(angle-angle_Value)*alength;
+	  lPointx=x2+Math.sin(angle-angle_Value)*alength;
+	  rPointy=y2+Math.cos(angle+angle_Value)*alength;
+	  rPointx=x2+Math.sin(angle+angle_Value)*alength;
+	} else {
+	  lPointy=y2+Math.cos(angle+angle_Value)*alength;
+	  lPointx=x2-Math.sin(angle+angle_Value)*alength;
+	  rPointy=y2+Math.cos(angle-angle_Value)*alength;
+	  rPointx=x2-Math.sin(angle-angle_Value)*alength;
+	}
+
+	writeLine(lPointx,lPointy,x2,y2,font_Size,5,arrayLine[arrayIdex]["Type"]);
+	writeLine(rPointx,rPointy,x2,y2,font_Size,5,arrayLine[arrayIdex]["Type"]);
+  }
+  arrayLine[arrayIdex]["End"]=idNumber-1;
+  arrayLine[arrayIdex]["Valid"]=idLine;
+  arrayIdex=arrayIdex+1;
+  //				if(refresh==true){
+  //
+  //				}
+
+
+}
+
+function writeLine(sx,sy,dx,dy,font,leap,visibile){
+  var y=dy-sy;
+  var x=dx-sx;
+		
+  var abs_Value;
+  abs_Value=(Math.abs(y)>Math.abs(x))? Math.abs(y):Math.abs(x);
+
+  for(var i=0;i<abs_Value;i=i+leap){
+	if(refresh==false){
+	  if( idNumber<1000 ){
+		copynode=est.cloneNode(true);
+		copynode.setAttribute("id", idNumber);
+		document.body.appendChild(copynode);
+		moveDivTo(copynode,sx+Math.round(x/abs_Value*i),sy+Math.round(i*(y/abs_Value)));
+		idLine+=1;
+
+	  } else {
+		arrayPoint[idNumber]=new Array();
+		arrayPoint[idNumber]["X"]=sx+Math.round(x/abs_Value*i);
+		arrayPoint[idNumber]["Y"]=sy+Math.round(i*(y/abs_Value));
+	  }
+	  idNumber += 1;
+	} else {
+	  if(idNumber<1000){
+		var est2 =document.getElementById(idNumber);
+		est2.style.visibility =visibile;
+		moveDivTo(est2,sx+Math.round(x/abs_Value*i),sy+Math.round(i*(y/abs_Value)));
+		idLine+=1;
+	  } else {
+		arrayPoint[idNumber]=new Array();
+		arrayPoint[idNumber]["X"]=sx+Math.round(x/abs_Value*i);
+		arrayPoint[idNumber]["Y"]=sy+Math.round(i*(y/abs_Value));
+	  }
+	  idNumber += 1;
+	}
+  }
+
+}
+function search_Line(Start,End,Line) {
+  var type;
+  var valid_count;
+  var visable;
+  if(arrayLine[Line]["Type"]=="hidden"){
+	visable= "visible";
+  } else {
+	visable= "hidden";
+  }
+
+  valid_count=arrayLine[Line]["Valid"];
+  if(refresh==true){
+	visable= arrayLine[Line]["Type"];
+  }
+  arrayLine[Line]["Type"]=visable;
+  var valid_start=Start+valid_count;
+  for (var j=Start;j<=End;j++){
+	if(j<valid_start){
+	  est1 =document.getElementById(j);
+	  est1.style.visibility = visable;
+	} else {
+	  copynode=est.cloneNode(true);
+	  copynode.setAttribute("id", j);
+	  copynode.style.visibility = visable;
+	  document.body.appendChild(copynode);
+	  moveDivTo(copynode,arrayPoint[j]["X"],arrayPoint[j]["Y"]);
+	  valid_count+=1;
+	}
+  }
+  arrayLine[Line]["Valid"]=valid_count;
+} 
+
+function set_panel() {
+  if(balloonDiv == null)
+	return;
+  var ele;
+  if(document.documentElement.clientHeight==0){	
+	ele=document.body;		
+  }else{
+	ele=document.documentElement;
+  }
+  var py=ele.scrollTop+ele.clientHeight-150;
+  var by=ele.scrollTop+ele.clientHeight-balloonDiv.offsetHeight-150;
+  if( servletMode == true ){
+	var su_Y=document.getElementById('suwen').offsetTop;
+	if(py>(su_Y-150)){
+	  py=su_Y-150;
+	  by=su_Y-balloonDiv.offsetHeight-150;
+	}
+  }
+  moveDivTo(document.getElementById('control_pane'),ele.scrollLeft+ele.clientWidth-40,py);
+  if(start_switch==false){
+	moveDivTo(balloonDiv,ele.scrollLeft+ele.clientWidth-160,by);
+  }
+} 
+
+function refresh_Jump(){
+  if( idNumber<1500 || confirm("This process may take 30 seconds or more. Would you like to continue it?")==1){
+
+	idNumber_Old=idNumber;
+	idNumber=0;
+	arrayIdex=0;
+	arrayPoint=new Array();
+	refresh=true;
+	for (var i=0;i<arrayLine.length;i++){
+	  var start_value;
+	  var delte_value;
+	  if(arrayLine[i]["End"]>=1000){
+		start_value=arrayLine[i]["Start"];
+		start_value=(start_value>1000)? start_value:1000;
+		delte_value=arrayLine[i]["Start"]+arrayLine[i]["Valid"];
+		for (var k=start_value;k<delte_value;k++){
+		  document.body.removeChild(document.getElementById(k));
+		}
+	  }
+	}
+	search_Jump();
+	for (var i=0;i<arrayLine.length;i++){
+	  if(arrayLine[i]["Type"]=="visible"){
+		search_Line(arrayLine[i]["Start"],arrayLine[i]["End"],i);
+	  }
+	}
+	if(idNumber_Old<1000){
+	  for (var i=idNumber;i<idNumber_Old;i++){
+		var est5 =document.getElementById(i);
+		if(est5 !=null){
+		  est5.style.visibility ="hidden";
+		}
+	  }
+	}
+	refresh=false;
+  }
+}
+function control_moving(){
+  if(start_switch==false){
+	document.getElementById('control_pane').firstChild.src=acc_imageDir+"Stop.gif";
+	start_switch=true;
+  } else {
+	document.getElementById('control_pane').firstChild.src=acc_imageDir+"Move.gif";
+	start_switch=false;
+  }
+}
+function clean_Line() {
+  if( idNumber<1500 || confirm("This process may take 30 seconds or more. Would you like to continue it?")==1){
+
+	for (var i=0;i<arrayLine.length;i++){
+	  if(arrayLine[i]["Type"] != "hidden"){
+		for (var j=arrayLine[i]["Start"];j<=arrayLine[i]["End"];j++){
+		  est1 =document.getElementById(j);
+		  est1.style.visibility ="hidden";
+		} 
+		arrayLine[i]["Type"]= "hidden";
+	  }
+	}
+  }
+
+} 
+function draw_all_Line() {
+  var node;
+  var copynode;
+
+  if( idNumber<1500 || confirm("This process may take 30 seconds or more. Would you like to continue it?")==1){
+	for (var i=0;i<arrayLine.length;i++){
+
+	  if(arrayLine[i]["Type"] == "hidden"){
+		var valid=arrayLine[i]["Valid"];
+		var start_point=arrayLine[i]["Start"];
+		var end_point=arrayLine[i]["End"];
+		var valid_start=start_point+valid;
+		for (var j=start_point;j<=end_point;j++){
+		  if(j<valid_start){
+			node =document.getElementById(j);
+			node.style.visibility ="visible";
+		  } else {
+			copynode=est.cloneNode(true);
+			copynode.setAttribute("id", j);
+			copynode.style.visibility = "visible";
+			document.body.appendChild(copynode);
+			moveDivTo(copynode,arrayPoint[j]["X"],arrayPoint[j]["Y"]);
+			valid+=1;
+		  }
+
+		} 
+		arrayLine[i]["Type"]= "visible";
+		arrayLine[i]["Valid"]=valid;
+	  }
+	}
+  }
+} 
+
+window.onload=search_Jump;
+window.onresize=function(){set_panel();  reHighlight();}
+
+
+function highlightTr( _tr ){
+  clearTrHighlight();
+  _tr.style.backgroundColor = HIGHLIGHT_BGCOLOR;
+}
+
+function clearTrHighlight(){
+  var allTR = document.body.all.tags( "TR" );
+  for(var i=0; i<allTR.length; i++ ){
+    if( allTR[i].style.backgroundColor == HIGHLIGHT_BGCOLOR ){
+      allTR[i].style.backgroundColor = "transparent";
+    }
+  }
+}
+
+
diff --git a/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/scripts/highlight_moz.js b/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/scripts/highlight_moz.js
new file mode 100644
index 0000000..f7aa402
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.blind/vizResources/scripts/highlight_moz.js
@@ -0,0 +1,821 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation
+ *******************************************************************************/ 
+
+prevNodeArray = new Array();
+prevBorderWidthArray = new Array();
+prevBorderColorArray = new Array();
+prevBorderStyleArray = new Array();
+prevBackgroundColorArray = new Array();
+prevColorArray = new Array();
+prevFilterArray = new Array();
+var x1=0;
+var x2=0;
+var y1=0;
+var y2=0;
+var idNumber=0;
+var idLine=0;
+var alength=30;
+var angleValue=30;
+var font_Size=16;
+var sux;
+var suy;
+var arrayIdex=0;
+arrayLine=new Array();
+arrayPoint=new Array();
+var start_switch =true;
+var est;
+var idNumber_Old=0;
+var refresh=false;
+//var HIGHLIGHT_BGCOLOR = "#ffdddd";
+var HIGHLIGHT_BGCOLOR = "rgb(255, 221, 221)";
+var MAX_PROBLEM_SELECTION = 30;
+
+// call it like: setHighlight2(new Array(43,47,49), new Array(45,47,50));
+function setHighlight2(firstNodeArray, lastNodeArray) {	
+	if(firstNodeArray.length > MAX_PROBLEM_SELECTION) {
+		if (!confirm("You selected more than " + MAX_PROBLEM_SELECTION + " problems. It will take time to highlight all of them. Do you want to continue?")) {
+			return;
+		}
+	}
+	//document.body.scrollTop=0;
+	//document.body.scrollLeft=0;
+	clearHighlight();	
+	var bScrolled=false;
+	var size = firstNodeArray.length;	
+	for (var i = 0; i < size; i++) {
+		for(var j = firstNodeArray[i]; j <= lastNodeArray[i]; j++) {	
+			//curNode = document.all["id" + j];
+			curNode=document.getElementById("id"+j);
+			if(curNode!=null){				
+				if (curNode != null && !bScrolled) {
+					_scrollToVisible(curNode);
+					bScrolled=true;
+				}
+				recursiveHighlight2(curNode,1);
+			}
+		}
+	}	
+}
+
+function isHighLighted(nodeId){
+	var preSize=prevNodeArray.length;
+	for(var i=0;i<preSize;i++){
+		curNode = prevNodeArray[i];
+		if(curNode.getAttribute('id')==nodeId){
+			return true;
+		}
+	}
+	return false;
+}
+
+function recursiveHighlight2(curNode, start){
+	if (curNode != null) {
+		if (curNode.nodeType == 1) {
+			var nodeid=curNode.getAttribute('id');
+			if((nodeid != "") && !isHighLighted(nodeid)){
+				prevNodeArray.push(curNode);
+				prevBorderWidthArray.push(curNode.style.borderWidth);
+				prevBorderColorArray.push(curNode.style.borderColor);
+				prevBorderStyleArray.push(curNode.style.borderStyle);
+				prevBackgroundColorArray.push(curNode.style.backgroundColor);
+				prevColorArray.push(curNode.style.color);
+				if (curNode.nodeName.match(/IMG/i) != null) {
+					prevFilterArray.push(curNode.style.filter);
+				}
+	
+				curNode.style.borderWidth = "1px";
+				curNode.style.borderColor = "red";
+				curNode.style.borderStyle = "dotted";
+				curNode.style.backgroundColor = "yellow";
+				curNode.style.color = "black";
+				if (curNode.nodeName.match(/IMG/i) != null) {
+					curNode.style.filter = "invert()";
+				}
+			}
+		}
+
+		var curChild = curNode.firstChild;
+		while(curChild != null) {
+			recursiveHighlight2(curChild, 0);			
+			curChild = curChild.nextSibling;
+		}
+	}
+}
+
+function setHighlight(firstNode, lastNode) {
+	//document.body.scrollTop=0;
+	//document.body.scrollLeft=0;
+	clearHighlight();
+	for(var i = firstNode; i < lastNode + 1; i++) {
+		//curNode = document.all["id" + i];
+		curNode=document.getElementById("id"+i);		
+		if(curNode!=null){					
+			if (curNode != null) {
+				_scrollToVisible(curNode);
+			}			
+			recursiveHighlight(curNode, 1);	
+		}
+	}
+}
+
+function recursiveHighlight(curNode, start){
+	if (curNode != null) {
+		if (curNode.nodeType == 1) {
+			var nodeid=curNode.getAttribute('id');
+			if((nodeid != "") && !isHighLighted(nodeid)){	
+				prevNodeArray.push(curNode);
+				prevBorderWidthArray.push(curNode.style.borderWidth);
+				prevBorderColorArray.push(curNode.style.borderColor);
+				prevBorderStyleArray.push(curNode.style.borderStyle);
+				prevBackgroundColorArray.push(curNode.style.backgroundColor);
+				prevColorArray.push(curNode.style.color);
+				if (curNode.nodeName.match(/IMG/i) != null) {
+					prevFilterArray.push(curNode.style.filter);
+				}
+				
+				curNode.style.borderWidth = "1px";
+				curNode.style.borderColor = "red";
+				curNode.style.borderStyle = "dotted";
+				curNode.style.backgroundColor = "yellow";
+				curNode.style.color = "black";
+				if (curNode.nodeName.match(/IMG/i) != null) {
+					curNode.style.filter = "invert()";
+				}
+			}
+		}
+		
+		var curChild = curNode.firstChild;
+		while(curChild != null) {
+			recursiveHighlight(curChild, 0);			
+			curChild = curChild.nextSibling;
+		}
+	}
+}
+
+function clearHighlight() {
+	var size = prevNodeArray.length;
+	for (var i = 0; i < size; i++) {
+		curNode = prevNodeArray[i];
+		curNode.style.borderWidth = prevBorderWidthArray[i];
+		curNode.style.borderColor = prevBorderColorArray[i];
+		curNode.style.borderStyle = prevBorderStyleArray[i];
+		curNode.style.backgroundColor = prevBackgroundColorArray[i];
+		curNode.style.color = prevColorArray[i];
+		if (curNode.nodeName.match(/IMG/i) != null) {
+			curNode.style.filter = prevFilterArray[i];
+		}
+	}
+	prevNodeArray = new Array();
+	prevBorderWidthArray = new Array();
+	prevBorderColorArray = new Array();
+	prevBorderStyleArray = new Array();
+	prevBackgroundColorArray = new Array();
+	prevColorArray = new Array();
+	prevFilterArray = new Array();
+}
+
+function _scrollToVisible(node) {
+	var left=0, top=0;
+	var width=node.offsetWidth;
+	var height=node.offsetHeight;
+
+	if ((node.tagName.toLowerCase() == "area") || (node.tagName.toLowerCase() == "map")) return;
+
+	while( node!=document.body )
+		{
+			top+=node.offsetTop;
+			left+=node.offsetLeft;
+			node = node.offsetParent;
+		}
+	if((node.scrollLeft>left)||(node.scrollLeft<(left+width-node.clientWidth))){
+		node.scrollLeft=left;	
+	}
+	if((node.scrollTop>top)||(node.scrollTop<(top+height-node.clientHeight))){
+		node.scrollTop=top;
+	}
+}
+
+
+
+// popup from here
+
+function moveDivTo(div,left,top){
+	//div.style.pixelLeft=left;
+	div.style.left=left+'px';
+	//div.style.pixelTop =top;
+	div.style.top =top+'px';
+	return;
+}
+function getEventPageX(e){
+	//return document.body.scrollLeft+event.clientX;
+	if(document.body.scrollLeft>document.documentElement.scrollLeft){
+		return document.body.scrollLeft+e.clientX;
+	}else{
+		return document.documentElement.scrollLeft+e.clientX;
+	}
+}
+function getEventPageY(e){
+	//return document.body.scrollTop+event.clientY;
+	if(document.body.scrollTop>document.documentElement.scrollTop){
+		return document.body.scrollTop+e.clientY;
+	}else{
+		return document.documentElement.scrollTop+e.clientY;
+	}
+}
+
+var balloonDiv=null; 
+var messageDiv=null; 
+
+function updateBaloon(curId) {
+	if(messageDiv != null){
+		messageDiv.style.visibility = "visible";
+		messageDiv.innerHTML = "<b>&nbsp";
+		messageDiv.innerHTML += id2time[curId];
+		messageDiv.innerHTML += "</b> seconds from top.";
+
+		if (id2time[curId] > 90) {
+			messageDiv.innerHTML += "<img src='" + baseUrl +acc_imageDir+ "face-sad.gif'>";						
+		} else if (id2time[curId] > 30) { 
+			messageDiv.innerHTML += "<img src='" + baseUrl +acc_imageDir+ "face-usual.gif'>";
+		} else {
+			messageDiv.innerHTML += "<img src='" + baseUrl +acc_imageDir+ "face-smile.gif'>";
+		}
+		if (id2comment[curId].length > 0) {
+			messageDiv.innerHTML += "<br><b>" + id2comment[curId] + "</b>";
+		}
+	}
+}
+
+function stopHandler(e){
+
+	//var e = window.event;
+	set_panel();
+		if (e.target != null) {
+			if ((servletMode == false ) || getEventPageY(e)<document.getElementById('suwen').offsetTop) {
+				if (id2time[e.target.id] != null) {
+					updateBaloon(e.target.id);
+				}
+			} 
+	}
+
+}
+
+function turnonHandler(){
+	var e = window.event;
+	document.onmouseup=movingHandler;
+	document.onmousemove=movingHandler;
+	document.onmousedown=turnoffHandler;
+
+	return false;
+}
+
+function init(){
+	if(baloonSwitch == 1){
+		balloonDiv=document.getElementById('balloon');    
+		messageDiv=document.getElementById('message');    
+		if( balloonDiv != null && messageDiv!=null){
+			document.onmouseup=movingHandler;
+			document.onmousemove=movingHandler;
+			document.onmousedown=turnoffHandler;			
+			//window.onmousemove=movingHandler;
+		}
+	} 
+	document.onclick=cancelLink;
+}
+
+function movingHandler(e){
+	//var e = window.event;
+	//window.event.returnValue = false;
+	set_panel();
+	if(servletMode == false ){	
+		if (e.target != null) {
+			//alert(id2time[e.target.id]);
+			if (id2time[e.target.id] != null) {
+				updateBaloon(e.target.id);
+			}
+		} 	
+
+		if(start_switch==true){
+			if(balloonDiv.style.width<52)
+			{
+				balloonDiv.style.width=52;
+			}
+			moveDivTo(balloonDiv,getEventPageX(e)+20,getEventPageY(e));
+		}
+	}
+}
+
+function turnoffHandler(){
+	init();
+	document.onmousemove=stopHandler;
+	document.onmousedown=turnonHandler;
+	return false;
+}
+
+function cancelMapLink(event) {
+	event.returnValue = false;
+	cancelLink(event);
+}
+function cancelLink(e) {
+	//var e = window.event;
+	var nodes =e.target;
+	set_panel();
+	//window.event.returnValue = false;
+	while(  nodes != null && nodes.tagName != null){
+			if( nodes.tagName.toLowerCase() == "img") {
+				if(nodes.getAttribute('src').toLowerCase().indexOf("jump.gif") > 0 
+					|| nodes.getAttribute('src').toLowerCase().indexOf("dest.gif") > 0){
+					alt=nodes.getAttribute('alt');
+					destName=alt.substring(alt.lastIndexOf(":")+2);
+					if(nodes.getAttribute('src').toLowerCase().indexOf("jump.gif") > 0){
+						sourceName=nodes.getAttribute('name');
+					} else{
+						sourceName=null;
+					}
+					if(sourceName==null){
+						for (var i=0;i<arrayLine.length;i++){
+							if(arrayLine[i]["destName"]==destName){
+								search_Line(arrayLine[i]["Start"],arrayLine[i]["End"],i);
+							}
+						}
+						break;
+					} else {
+						for (var i=0;i<arrayLine.length;i++){
+							if(arrayLine[i]["destName"]==destName && arrayLine[i]["sourceName"]==sourceName){					
+								search_Line(arrayLine[i]["Start"],arrayLine[i]["End"],i);
+							}
+						}
+						break;
+					}
+
+
+				}
+			}
+
+			nodes=nodes.parentNode;
+			node_Id=nodes.getAttribute('id');
+			if( node_Id!=null && !isNaN(parseInt(node_Id)) && node_Id>=0 && node_Id<idNumber) {
+				for (var i=0;i<arrayLine.length;i++){
+					if(arrayLine[i]["Start"]<=node_Id
+						&& arrayLine[i]["End"]>=node_Id){
+						search_Line(arrayLine[i]["Start"],arrayLine[i]["End"],i);
+						break;
+					}
+				}
+			}
+			if(nodes!= null && nodes.firstChild != null){
+				if( nodes.firstChild.tagName !=null && nodes.firstChild.tagName.toLowerCase() == "img"){
+					if(nodes.firstChild.getAttribute('src').toLowerCase().indexOf("jump.gif") > 0 
+						|| nodes.firstChild.getAttribute('src').toLowerCase().indexOf("dest.gif") > 0){
+						alt=nodes.firstChild.getAttribute('alt');
+						destName=alt.substring(alt.lastIndexOf(":")+2);
+						if(nodes.firstChild.getAttribute('src').toLowerCase().indexOf("jump.gif") > 0){
+							sourceName=nodes.firstChild.getAttribute('name');
+						} else{
+							sourceName=null;
+						}
+						if(sourceName==null){
+							for (var i=0;i<arrayLine.length;i++){
+								if(arrayLine[i]["destName"]==destName){
+									search_Line(arrayLine[i]["Start"],arrayLine[i]["End"],i);
+								}
+							}
+							break;
+						} else {
+							for (var i=0;i<arrayLine.length;i++){
+								if(arrayLine[i]["destName"]==destName && arrayLine[i]["sourceName"]==sourceName){
+									search_Line(arrayLine[i]["Start"],arrayLine[i]["End"],i);
+								}
+							}
+							break;
+						}
+
+					}
+				}
+				break;
+
+			}
+
+
+	}
+}
+
+function search_Jump() {
+	var i=0;
+	var dest;
+	var alt;
+	init();
+	est =document.getElementById('test');
+//	est.style.visibility = "visible";
+	est.style.visibility = "hidden";
+	est.innerHTML = "<img src='" + acc_imageDir+"line_filled.gif'>";
+	var x1=arrayLine.length;
+
+	if(refresh==true){
+		if(idNumber<1500||confirm("This process may take 30 seconds or more. Would you like to continue it?")==1){
+			for (var h=0;h<x1;h++){
+				var su=arrayLine[h]["sourceName"];
+				nodelist=document.getElementsByName(su);
+				node=nodelist[0];
+				looplink_Jump(node,arrayLine[h]["destName"]);
+			}
+		}
+	} else {
+		while(true){
+			if( document.getElementsByTagName("img")[i]==null){
+				break;
+			}
+
+			if(document.getElementsByTagName("img")[i].getAttribute('src').toLowerCase().indexOf("jump.gif") > 0){
+				alt=document.getElementsByTagName("img")[i].getAttribute('alt');
+				dest=alt.substring(alt.indexOf(":")+2);
+				looplink_Jump(document.getElementsByTagName("img")[i],dest);
+			}
+			i=i+1;
+			
+			if(isAlert==true && idNumber>2000){
+				alert("This page contains too many intra-page links.\nIn this page, aDesigner can visualize some of intra-page links by arrow.");
+				break;
+			}
+
+		}
+	}
+} 
+
+function looplink_Jump(nodeImg,z2) {
+				x1=0;
+				x2=0;
+				y1=0;
+				y2=0;
+
+				var node=nodeImg;
+
+//				while( node!=document.body){
+				while( node!=null){
+					if(node.nodeName !=null && node.nodeName!="TR"){
+						if(!isNaN(node.offsetLeft)){
+							x1 =x1+node.offsetLeft;
+						}
+						if(!isNaN(node.offsetTop)){
+							y1 =y1+node.offsetTop;
+						}
+					}
+					node = node.offsetParent;
+				}
+
+				nodelist=document.getElementsByName(z2);
+				if(nodelist.length>1){
+					var finded=false;					
+					for(var k=0;k<nodelist.length;k++){
+						var cur=nodelist[k].firstChild;
+						while(cur!=null){
+							if(cur.nodeName.toLowerCase()=="img"){
+								node=nodelist[k];
+								finded=true;
+								break;
+							}
+							cur=cur.nextSibling;
+						}
+					
+						if(finded==true){
+							break;
+						}
+					}
+				} else {
+					node=nodelist[0];
+				}
+//				while( node!=document.body){
+				while( node!=null){
+					if( node.nodeName !=null && node.nodeName!="TR"){
+						if(!isNaN(node.offsetLeft)){
+							x2 =x2+node.offsetLeft;
+						} 
+						if(!isNaN(node.offsetTop)){
+							y2 =y2+node.offsetTop;
+						}
+					}
+					node = node.offsetParent;
+				}
+				//alert(x1+","+y1);
+				//alert(x2+","+y2);
+
+				var x3=x1-x2;
+
+				var copynode;
+				var lPointx;
+				var lPointy;
+				var rPointx;
+				var rPointy;
+				var angle;
+				if(x2<5 && y2<5){
+					x2=20;
+					y2=20;
+				}
+				if (arrayLine[arrayIdex]==null){
+					arrayLine[arrayIdex]=new Array();
+				}
+				arrayLine[arrayIdex]["sourceName"]=nodeImg.getAttribute('name');
+				arrayLine[arrayIdex]["destName"]=z2;
+
+				arrayLine[arrayIdex]["Start"]=idNumber;
+				if(refresh==false){
+					arrayLine[arrayIdex]["Type"]="hidden";
+				}
+				idLine=0;
+				writeLine(x1+5,y1+5,x2,y2,0,50,arrayLine[arrayIdex]["Type"]);
+				angle_Value=angleValue/57.3;
+				if(y2>y1){
+					angle=Math.atan((y2-y1)/x3);
+					if(angle<0){
+						angle=angle+180/57.3;
+					}
+					lPointx=x2+Math.cos(angle+angle_Value)*alength;
+					lPointy=y2-Math.sin(angle+angle_Value)*alength;
+					rPointx=x2+Math.cos(angle-angle_Value)*alength;
+					rPointy=y2-Math.sin(angle-angle_Value)*alength;
+					writeLine(lPointx,lPointy,x2,y2,font_Size,5,arrayLine[arrayIdex]["Type"]);
+					writeLine(rPointx,rPointy,x2,y2,font_Size,5,arrayLine[arrayIdex]["Type"]);
+				} else {
+					angle=Math.atan(Math.abs(x3/(y2-y1)));
+
+					if(x2<x1){
+						lPointy=y2+Math.cos(angle-angle_Value)*alength;
+						lPointx=x2+Math.sin(angle-angle_Value)*alength;
+						rPointy=y2+Math.cos(angle+angle_Value)*alength;
+						rPointx=x2+Math.sin(angle+angle_Value)*alength;
+					} else {
+						lPointy=y2+Math.cos(angle+angle_Value)*alength;
+						lPointx=x2-Math.sin(angle+angle_Value)*alength;
+						rPointy=y2+Math.cos(angle-angle_Value)*alength;
+						rPointx=x2-Math.sin(angle-angle_Value)*alength;
+					}
+
+					writeLine(lPointx,lPointy,x2,y2,font_Size,5,arrayLine[arrayIdex]["Type"]);
+					writeLine(rPointx,rPointy,x2,y2,font_Size,5,arrayLine[arrayIdex]["Type"]);
+				}
+				arrayLine[arrayIdex]["End"]=idNumber-1;
+				arrayLine[arrayIdex]["Valid"]=idLine;
+				arrayIdex=arrayIdex+1;
+//				if(refresh==true){
+//
+//				}
+
+
+}
+
+function writeLine(sx,sy,dx,dy,font,leap,visibile){
+		var y=dy-sy;
+		var x=dx-sx;
+		
+		var abs_Value;
+		abs_Value=(Math.abs(y)>Math.abs(x))? Math.abs(y):Math.abs(x);
+
+		for(var i=0;i<abs_Value;i=i+leap){
+			if(refresh==false){
+				if( idNumber<1000 ){
+					copynode=est.cloneNode(true);
+					copynode.setAttribute("id", idNumber);
+					document.body.appendChild(copynode);
+					moveDivTo(copynode,sx+Math.round(x/abs_Value*i),sy+Math.round(i*(y/abs_Value)));					
+					idLine+=1;
+							
+				} else {
+					arrayPoint[idNumber]=new Array();
+					arrayPoint[idNumber]["X"]=sx+Math.round(x/abs_Value*i);
+					arrayPoint[idNumber]["Y"]=sy+Math.round(i*(y/abs_Value));
+				}
+				idNumber += 1;
+			} else {
+				if(idNumber<1000){
+					var est2 =document.getElementById(idNumber);
+					est2.style.visibility =visibile;
+					moveDivTo(est2,sx+Math.round(x/abs_Value*i),sy+Math.round(i*(y/abs_Value)));
+					idLine+=1;
+				} else {
+					arrayPoint[idNumber]=new Array();
+					arrayPoint[idNumber]["X"]=sx+Math.round(x/abs_Value*i);
+					arrayPoint[idNumber]["Y"]=sy+Math.round(i*(y/abs_Value));
+				}
+				idNumber += 1;
+			}
+		}
+
+}
+function search_Line(Start,End,Line) {
+		var type;
+		var valid_count;
+		var visable;
+		if(arrayLine[Line]["Type"]=="hidden"){
+			visable= "visible";
+		} else {
+			visable= "hidden";
+		}
+
+		valid_count=arrayLine[Line]["Valid"];
+		if(refresh==true){
+			visable= arrayLine[Line]["Type"];
+		}
+		arrayLine[Line]["Type"]=visable;
+		var valid_start=Start+valid_count;
+		for (var j=Start;j<=End;j++){
+			if(j<valid_start){
+				est1 =document.getElementById(j);
+				est1.style.visibility = visable;
+			} else {
+				copynode=est.cloneNode(true);
+				copynode.setAttribute("id", j);
+				copynode.style.visibility = visable;
+				document.body.appendChild(copynode);
+				moveDivTo(copynode,arrayPoint[j]["X"],arrayPoint[j]["Y"]);
+				valid_count+=1;
+			}
+		}
+		arrayLine[Line]["Valid"]=valid_count;
+} 
+
+function set_panel() {
+		if(balloonDiv == null)
+			return;
+		//var py=document.body.scrollTop+document.body.clientHeight-150;
+		//var by=document.body.scrollTop+document.body.clientHeight-balloonDiv.offsetHeight-150;
+		var px,bx,py,by;
+		var bodyHeight=document.body.scrollTop+document.body.clientHeight;
+		var eleHeight=document.documentElement.scrollTop+document.documentElement.clientHeight;
+		
+		if(document.body.scrollTop>document.documentElement.scrollTop){
+			px=document.body.scrollLeft+document.body.clientWidth-40;
+			bx=document.body.scrollLeft+document.body.clientWidth-160;
+			py=bodyHeight-150;
+			by=bodyHeight-balloonDiv.offsetHeight-150;
+		}else if(document.body.scrollTop<document.documentElement.scrollTop){
+			px=document.documentElement.scrollLeft+document.documentElement.clientWidth-40;
+			bx=document.documentElement.scrollLeft+document.documentElement.clientWidth-160;
+			py=eleHeight-150;
+			by=eleHeight-balloonDiv.offsetHeight-150;
+		}else{		
+			if(eleHeight<bodyHeight && eleHeight!=0){
+				px=document.documentElement.scrollLeft+document.documentElement.clientWidth-40;
+				bx=document.documentElement.scrollLeft+document.documentElement.clientWidth-160;
+				py=eleHeight-150;
+				by=eleHeight-balloonDiv.offsetHeight-150;
+			}else{
+				px=document.body.scrollLeft+document.body.clientWidth-40;
+				bx=document.body.scrollLeft+document.body.clientWidth-160;
+				py=bodyHeight-150;
+				by=bodyHeight-balloonDiv.offsetHeight-150;
+			}
+
+		}
+		
+		if( servletMode == true ){
+			var su_Y=document.getElementById('suwen').offsetTop;
+			if(py>(su_Y-150)){
+				py=su_Y-150;
+				by=su_Y-balloonDiv.offsetHeight-150;
+			}
+		}
+		var div=document.getElementById('control_pane');
+		if(div.style.width<29){
+			div.style.width=29;
+		}
+		moveDivTo(div,document.body.scrollLeft+document.body.clientWidth-40,py);		
+		if(start_switch==false){
+			moveDivTo(balloonDiv,document.body.scrollLeft+document.body.clientWidth-160,by);
+		}
+} 
+
+function refresh_Jump(){
+		if( idNumber<1500 || confirm("This process may take 30 seconds or more. Would you like to continue it?")==1){
+
+			idNumber_Old=idNumber;
+			idNumber=0;
+			arrayIdex=0;
+			arrayPoint=new Array();
+			refresh=true;
+			for (var i=0;i<arrayLine.length;i++){
+				var start_value;
+				var delte_value;
+				if(arrayLine[i]["End"]>=1000){
+					start_value=arrayLine[i]["Start"];
+					start_value=(start_value>1000)? start_value:1000;
+					delte_value=arrayLine[i]["Start"]+arrayLine[i]["Valid"];
+					for (var k=start_value;k<delte_value;k++){
+						document.body.removeChild(document.getElementById(k));
+					}
+				}
+			}
+			search_Jump();
+			for (var i=0;i<arrayLine.length;i++){
+				if(arrayLine[i]["Type"]=="visible"){
+					search_Line(arrayLine[i]["Start"],arrayLine[i]["End"],i);
+				}
+			}
+			if(idNumber_Old<1000){
+				for (var i=idNumber;i<idNumber_Old;i++){
+					var est5 =document.getElementById(i);
+					if(est5 !=null){
+						est5.style.visibility ="hidden";
+					}
+				}
+			}
+			refresh=false;
+		}
+}
+function control_moving(){
+	var node =document.getElementById('control_pane').firstChild;
+
+	if(start_switch==false){
+		while(node!=null){		
+			if(node.src!=null && node.src.indexOf("move.gif")>=0){
+				node.src=acc_imageDir+"stop.gif";
+				start_switch=true;
+				break;
+			}
+			node=node.nextSibling;
+		}
+	} else {
+		while(node!=null){
+			if(node.src!=null && node.src.indexOf("stop.gif")>=0){
+				node.src=acc_imageDir+"move.gif";
+				start_switch=false;
+				break;
+			}
+			node=node.nextSibling;
+		}
+	}
+}
+function clean_Line() {
+	if( idNumber<1500 || confirm("This process may take 30 seconds or more. Would you like to continue it?")==1){
+
+		for (var i=0;i<arrayLine.length;i++){
+			if(arrayLine[i]["Type"] != "hidden"){
+				for (var j=arrayLine[i]["Start"];j<=arrayLine[i]["End"];j++){
+					est1 =document.getElementById(j);
+					est1.style.visibility ="hidden";
+				} 
+			arrayLine[i]["Type"]= "hidden";
+			}
+		}
+	}
+
+} 
+function draw_all_Line() {
+		var node;
+		var copynode;
+
+		if( idNumber<1500 || confirm("This process may take 30 seconds or more. Would you like to continue it?")==1){
+			for (var i=0;i<arrayLine.length;i++){
+
+				if(arrayLine[i]["Type"] == "hidden"){
+					var valid=arrayLine[i]["Valid"];
+					var start_point=arrayLine[i]["Start"];
+					var end_point=arrayLine[i]["End"];
+					var valid_start=start_point+valid;
+					for (var j=start_point;j<=end_point;j++){
+						if(j<valid_start){
+							node =document.getElementById(j);
+							node.style.visibility ="visible";
+						} else {
+							copynode=est.cloneNode(true);
+							copynode.setAttribute("id", j);
+							copynode.style.visibility = "visible";
+							document.body.appendChild(copynode);
+							moveDivTo(copynode,arrayPoint[j]["X"],arrayPoint[j]["Y"]);
+							valid+=1;
+						}
+
+					} 
+					arrayLine[i]["Type"]= "visible";
+					arrayLine[i]["Valid"]=valid;
+				}
+			}
+		}
+} 
+
+window.onload=search_Jump;
+window.onresize=set_panel;
+
+
+function highlightTr( _tr ){
+  clearTrHighlight();
+  _tr.style.backgroundColor = HIGHLIGHT_BGCOLOR;
+}
+
+function clearTrHighlight(){
+  //var allTR = document.body.all.tags( "TR" );
+  allTR=document.getElementsByTagName("tr");
+  for(var i=0; i<allTR.length; i++ ){
+  if(allTR[i].style.backgroundColor!="rgb(255, 255, 255)"&&allTR[i].style.backgroundColor!="")
+    if( allTR[i].style.backgroundColor == HIGHLIGHT_BGCOLOR ){
+      allTR[i].style.backgroundColor = "transparent";
+    }
+  }
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/.classpath b/plugins/org.eclipse.actf.visualization.engines.lowvision/.classpath
new file mode 100644
index 0000000..751c8f2
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/.cvsignore b/plugins/org.eclipse.actf.visualization.engines.lowvision/.cvsignore
new file mode 100644
index 0000000..ba077a4
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/.cvsignore
@@ -0,0 +1 @@
+bin
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/.project b/plugins/org.eclipse.actf.visualization.engines.lowvision/.project
new file mode 100644
index 0000000..70298d1
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.actf.visualization.engines.lowvision</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/META-INF/MANIFEST.MF b/plugins/org.eclipse.actf.visualization.engines.lowvision/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..bc2933d
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/META-INF/MANIFEST.MF
@@ -0,0 +1,18 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Eclipse ACTF Lowvision Engine Plug-in (Incubation)
+Bundle-SymbolicName: org.eclipse.actf.visualization.engines.lowvision
+Bundle-Version: 0.0.1
+Bundle-Vendor: Eclipse.org
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.actf.common,
+ org.eclipse.actf.visualization.eval
+Export-Package: org.eclipse.actf.visualization.engines.lowvision,
+ org.eclipse.actf.visualization.engines.lowvision.color,
+ org.eclipse.actf.visualization.engines.lowvision.image,
+ org.eclipse.actf.visualization.engines.lowvision.io,
+ org.eclipse.actf.visualization.engines.lowvision.operator
+Bundle-Activator: org.eclipse.actf.visualization.engines.lowvision.LowVisionPlugin
+Eclipse-LazyStart: true
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/about.html b/plugins/org.eclipse.actf.visualization.engines.lowvision/about.html
new file mode 100644
index 0000000..481dbcf
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/about.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>June 5, 2006</p>	
+<h3>License</h3>
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;).  
+Unless otherwise indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;).  A copy of the EPL is available 
+at <a href="http://www.eclipse.org/org/documents/epl-v10.php">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is 
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content.  Check the Redistributor&rsquo;s license 
+that was provided with the Content.  If no such license exists, contact the Redistributor.  Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/build.properties b/plugins/org.eclipse.actf.visualization.engines.lowvision/build.properties
new file mode 100644
index 0000000..750d4a7
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/build.properties
@@ -0,0 +1,15 @@
+###############################################################################
+# Copyright (c) 2007, 2008 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#     IBM Corporation - initial API and implementation
+###############################################################################
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               about.html
\ No newline at end of file
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/LowVisionCommon.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/LowVisionCommon.java
new file mode 100644
index 0000000..e5ef699
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/LowVisionCommon.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision;
+
+public interface LowVisionCommon {
+
+	//IE fontsize
+	static final String IE_LARGEST_FONT = "16pt";
+	static final double IE_EM_SCALING = 1.33; // "1em" in largest (experimental)
+	static final double IE_LARGER_SCALING = 1.67; // "larger" in largest (experimental)
+	static final double IE_SMALLER_SCALING = 1.00; // "smaller" in largest (experimental)
+
+	// scroll bar
+	int SURROUNDINGS_WIDTH = 2; 
+	int SCROLL_BAR_WIDTH = 20;
+	boolean REMOVE_SURROUNDINGS = true;
+	boolean REMOVE_SCROLL_BAR_AT_RIGHT = false;
+	boolean REMOVE_SCROLL_BAR_AT_BOTTOM = false;
+	
+	// TODO relative value?
+	// the color which have only small portions in image is not handled as text candidate
+	int THRESHOLD_MIN_OCCURRENCES = 300;
+
+	// thresholds for char check
+	double THRESHOLD_MIN_CHAR_RATIO = 0.1;
+	double THRESHOLD_MAX_CHAR_RATIO = 10.0;
+	double THRESHOLD_MIN_CONTAINER_DENSITY = 0.4;
+	double THRESHOLD_MAX_CHARACTER_DENSITY = 0.75;
+	double THRESHOLD_MIN_THINNING_RATIO = 0.25; // 
+	double THRESHOLD_MIN_UNDERLINE_POSITION = 0.85;
+	double THRESHOLD_MIN_UNDERLINE_WIDTH_RATIO = 0.95;
+	double THRESHOLD_MIN_UNDERLINE_RATIO = 3.0;
+
+	int THRESHOLD_MIN_CHAR_WIDTH = 5;
+	int THRESHOLD_MAX_CHAR_WIDTH = 72;
+	int THRESHOLD_MIN_CHAR_HEIGHT = 5; 
+	int THRESHOLD_MAX_CHAR_HEIGHT = 100;
+
+	int THRESHOLD_MAX_THINNED_BRANCHES = 8;
+	int THRESHOLD_MAX_THINNED_CROSSES = 8;
+
+	int THRESHOLD_MIN_MSCHAR_WIDTH = 10;
+	int THRESHOLD_MIN_MSCHAR_HEIGHT = 10;
+	int THRESHOLD_MAX_MSCHAR_HEIGHT = 100;
+
+	int THRESHOLD_MIN_SMCHAR_WIDTH = 10;
+	int THRESHOLD_MIN_SMCHAR_HEIGHT = 10;
+	int THRESHOLD_MAX_SMCHAR_HEIGHT = 100;
+
+	// color combination check (text)
+	float MIN_ENOUGH_DELTA_L_FOR_TEXT = 20.0f; // enough L (L*a*b*)
+	float MAX_ENOUGH_DELTA_L_FOR_TEXT = 40.0f; // (L*a*b*)
+	float ENOUGH_DELTA_E_FOR_TEXT = 100.0f; // (L*a*b*)
+	float ENOUGH_DELTA_H_FOR_TEXT = 100.0f; // (L*a*b*)
+	float RECOMMENDED_DELTA_L_FOR_TEXT = MAX_ENOUGH_DELTA_L_FOR_TEXT + 5.0f;
+	float MID_L = 50.0f;
+
+	// color combination check (image)
+	float ENOUGH_DELTA_E_FOR_IMAGE = 40.0f;
+
+	/* 
+	 * Extract method for SM char is not perfect. 
+	 * (e.g., extract chars with shadow, etc...)
+	 * So, set strict threshold. 
+	 */
+	double THRESHOLD_MIN_SM_COLOR_PROBLEM_RATIO = 0.8; 
+	
+
+	// check color combination (image)
+	// See InteriorImage.java
+	double THRESHOLD_MIN_IMAGE_COLOR_PROBLEM_PROBABILITY = 0.2;
+
+	// check fg/bg color
+	double THRESHOLD_FOREGROUND_RATIO = 0.25;
+	// error margin
+	double THRESHOLD_FOREGROUND_ERROR_MARGIN = 1.5;
+	
+	float THRESHOLD_LIMIT_BLURRED_WIDTH_RATIO = 3.0f;
+	float THRESHOLD_LIMIT_BLURRED_HEIGHT_RATIO = 3.0f;
+
+	//// InteriorImage
+	// minimum pixels/occupation to be considered as LargeComponent
+	int THRESHOLD_MIN_LARGE_COMPONENT_PIXELS = 100;
+	double THRESHOLD_MIN_LARGE_COMPONENT_OCCUPATION = 0.0005;
+	
+	// Problem grouping
+	int THRESHOLD_MAX_CHARACTER_SPACE = 7; // word
+	int THRESHOLD_MAX_REGION_ELEMENT_SPACE = 80;
+	int THRESHOLD_MAX_GROUPED_CONTAINER_WIDTH = 300; 
+	int THRESHOLD_MAX_GROUPED_CONTAINER_HEIGHT = 300;
+	
+	//severity for fixed size font (0-1)
+	double SEVERITY_FIXED_SIZE_FONT = 0.25;
+	double SEVERITY_SMALL_FONT = 0.25;
+	double SEVERITY_FIXED_SMALL_FONT = SEVERITY_FIXED_SIZE_FONT + SEVERITY_SMALL_FONT;
+
+	// severity for color problems 
+	double SEVERITY_PROHIBITED_FOREGROUND_COLOR = 0.5;
+	double SEVERITY_PROHIBITED_BACKGROUND_COLOR = 0.5;
+	double SEVERITY_PROHIBITED_BOTH_COLORS = SEVERITY_PROHIBITED_FOREGROUND_COLOR + SEVERITY_PROHIBITED_BACKGROUND_COLOR;
+	
+	// severity/color mapping
+	double SCORE_ORANGE = 0.5; 
+	double SCORE_RED = 1.0; 
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/LowVisionException.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/LowVisionException.java
new file mode 100644
index 0000000..6ed299c
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/LowVisionException.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision;
+
+public class LowVisionException extends Exception {
+	public LowVisionException() {
+		super();
+	}
+
+	public LowVisionException(String _s) {
+		super(_s);
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/LowVisionPlugin.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/LowVisionPlugin.java
new file mode 100644
index 0000000..b29526e
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/LowVisionPlugin.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision;
+
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class LowVisionPlugin extends AbstractUIPlugin {
+
+	// The shared instance.
+	private static LowVisionPlugin plugin;
+
+	/**
+	 * The constructor.
+	 */
+	public LowVisionPlugin() {
+		plugin = this;
+	}
+
+	/**
+	 * This method is called upon plug-in activation
+	 */
+	public void start(BundleContext context) throws Exception {
+		super.start(context);
+	}
+
+	/**
+	 * This method is called when the plug-in is stopped
+	 */
+	public void stop(BundleContext context) throws Exception {
+		super.stop(context);
+		plugin = null;
+	}
+
+	/**
+	 * Returns the shared instance.
+	 */
+	public static LowVisionPlugin getDefault() {
+		return plugin;
+	}
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/LowVisionType.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/LowVisionType.java
new file mode 100644
index 0000000..79e29b8
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/LowVisionType.java
@@ -0,0 +1,418 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision;
+
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.StringTokenizer;
+
+import org.eclipse.actf.visualization.engines.lowvision.operator.CVDOp;
+import org.eclipse.actf.visualization.engines.lowvision.operator.ColorFilterOp;
+import org.eclipse.actf.visualization.engines.lowvision.operator.GlareOp;
+
+/*
+ * Define lowvision simulation type
+ */
+public class LowVisionType {
+
+	public static final String COLOR_FILTER_STR = "senior_color";
+
+	public static final String CVD_STR = "color";
+
+	public static final String EYESIGHT_STR = "focus";
+
+	public static final String GLARE_STR = "glare";
+
+	// private static final String FIELD_STR = "field";
+
+	private static final double EYESIGHT_DEGREE_MARGIN = 0.1;
+
+	private final int DISPLAY_RESOLUTION = 1024; // Y
+
+	private final double DISPLAY_HEIGHT = 20.8; // 14.1 inches
+
+	// public static final double DISPLAY_HEIGHT = 26.5; // 19 inches
+	private final double EYE_DISPLAY_DISTANCE = 30.0;
+
+	private boolean eyesight = false;
+
+	private float eyesightDegree;
+
+	// radius of blur array (exclude center, 3x3 -> 1)
+	private int eyesightRadius;
+
+	// undistinguishable pixel size for the target person
+	private double eyesightPixel;
+
+	// undistinguishable length(mm) for thetarget person
+	private double eyesightLength;
+
+	// color vision deficiency
+	private boolean CVD = false;
+
+	private int CVDType;
+
+	// color filter
+	private boolean colorFilter = false;
+
+	private float colorFilterR; // [0.0, 1.0]
+
+	private float colorFilterG; // [0.0, 1.0]
+
+	private float colorFilterB; // [0.0, 1.0]
+
+	// glare
+	private boolean glare = false;
+
+	private float glareDegree = 0.0f;
+
+	private int displayResolution = DISPLAY_RESOLUTION;
+
+	private double displayHeight = DISPLAY_HEIGHT;
+
+	private double eyeDisplayDistance = EYE_DISPLAY_DISTANCE;
+
+	public LowVisionType() {
+	}
+
+	public LowVisionType(String _fileName) throws LowVisionException {
+		BufferedReader br = null;
+		try {
+			br = new BufferedReader(new FileReader(_fileName));
+		} catch (FileNotFoundException fne) {
+			fne.printStackTrace();
+			throw new LowVisionException("File not found.");
+		}
+		read(br);
+	}
+
+	public LowVisionType(BufferedReader _br) throws LowVisionException {
+		read(_br);
+	}
+
+	public boolean getEyesight() {
+		return (eyesight);
+	}
+
+	public void setEyesight(boolean _b) {
+		eyesight = _b;
+	}
+
+	public float getEyesightDegree() {
+		return (eyesightDegree);
+	}
+
+	public void setEyesightDegree(float _deg) throws LowVisionException {
+		if (_deg <= 0.0) {
+			throw new LowVisionException("Eyesight degree must be positive.");
+		}
+		eyesightDegree = _deg;
+		eyesightPixel = calcUndistinguishablePixel(eyesightDegree);
+		eyesightRadius = calcRadius(eyesightPixel);
+		eyesightLength = calcUndistinguishableLength(eyesightDegree);
+	}
+
+	public double getEyesightPixel() {
+		return (eyesightPixel);
+	}
+
+	public int getEyesightRadius() {
+		return (eyesightRadius);
+	}
+
+	public double getEyesightLength() {
+		return (eyesightLength);
+	}
+
+	private double calcUndistinguishablePixel(double _degree) {
+		double degree = _degree + EYESIGHT_DEGREE_MARGIN;
+		double thetaD = 1.0 / degree; // distinguishable degree (arcmin)
+		double thetaR = thetaD * Math.PI / 10800.0; // distinguishable degree(radian)
+		return (2.0 * Math.tan(thetaR / 2.0) * displayResolution
+				* eyeDisplayDistance / displayHeight);
+	}
+
+	private int calcRadius(double _pixel) {
+		return ((int) (Math.ceil(_pixel)));
+	}
+
+	private double calcUndistinguishableLength(double _degree) {
+		double degree = _degree + EYESIGHT_DEGREE_MARGIN;
+		double thetaD = 1.0 / degree;
+		double thetaR = thetaD * Math.PI / 10800.0;
+		return (20.0 * Math.tan(thetaR / 2.0) * eyeDisplayDistance);
+		/*
+		 * 20.0 = 10.0*2.0 2.0 equals in calcPixel() 10.0-> cm to mm
+		 */
+	}
+
+	public boolean getCVD() {
+		return (CVD);
+	}
+
+	public void setCVD(boolean _b) {
+		CVD = _b;
+	}
+
+	public int getCVDType() {
+		return (CVDType);
+	}
+
+	public void setCVDType(int _i) throws LowVisionException {
+		if (_i != 1 && _i != 2 && _i != 3) {
+			throw new LowVisionException("CVD type must be 1,2, or 3");
+		}
+		CVDType = _i;
+	}
+
+	public boolean getColorFilter() {
+		return (colorFilter);
+	}
+
+	public void setColorFilter(boolean _b) {
+		colorFilter = _b;
+	}
+
+	public float[] getColorFilterRGB() {
+		float[] rgb = { colorFilterR, colorFilterG, colorFilterB };
+		return (rgb);
+	}
+
+	public void setColorFilterRGB(float _r, float _g, float _b)
+			throws LowVisionException {
+		if (_r < 0.0 || 1.0 < _r)
+			throw new LowVisionException("Value of R(" + _r
+					+ ") is out of range.");
+		colorFilterR = _r;
+		if (_g < 0.0 || 1.0 < _g)
+			throw new LowVisionException("Value of G(" + _g
+					+ ") is out of range.");
+		colorFilterG = _g;
+		if (_b < 0.0 || 1.0 < _b)
+			throw new LowVisionException("Value of B(" + _b
+					+ ") is out of range.");
+		colorFilterB = _b;
+	}
+
+	public void setColorFilterRGB(float[] rgb) throws LowVisionException {
+		if (rgb.length != 3) {
+			throw new LowVisionException("The parameter's length must be 3.");
+		}
+		setColorFilterRGB(rgb[0], rgb[1], rgb[2]);
+	}
+
+
+	public void setColorFilterDegree(float _degree) throws LowVisionException {
+		// TODO check color filter values
+		float bDegree = _degree;
+		// float bDegree = 1.0f-(1.0f-_degree)*0.9f;
+		float rgDegree = 1 - (1 - bDegree) / 2.0f;
+		setColorFilterRGB(rgDegree, rgDegree, bDegree);
+	}
+
+	public boolean getGlare() {
+		return (glare);
+	}
+
+	public void setGlare(boolean _g) {
+		glare = _g;
+	}
+
+	public float getGlareDegree() {
+		return (glareDegree);
+	}
+
+	public void setGlareDegree(float _deg) {
+		glareDegree = _deg;
+	}
+
+	//read simulation type from config file
+	public void read(BufferedReader _br) throws LowVisionException {
+		String oneLine = null;
+		try {
+			while ((oneLine = _br.readLine()) != null) {
+				StringTokenizer st = new StringTokenizer(oneLine);
+				String typeName = st.nextToken().toLowerCase();
+				if (typeName.equals(COLOR_FILTER_STR)) {
+					readColorFilter(st);
+				} else if (typeName.equals(CVD_STR)) {
+					readCVD(st);
+				} else if (typeName.equals(EYESIGHT_STR)) {
+					readEyesight(st);
+				} else if (typeName.equals(GLARE_STR)) {
+					readGlare(st);
+				} else {
+					throw new LowVisionException("Unknown type: " + typeName);
+				}
+			}
+		} catch (IOException e) {
+			e.printStackTrace();
+			throw new LowVisionException("IO Error occurred while reading.");
+		}
+	}
+
+	private void readColorFilter(StringTokenizer _st) throws LowVisionException {
+		if (_st.countTokens() != 3) {
+			throw new LowVisionException("Color filter needs three parameters.");
+		}
+		float tmpR = Float.parseFloat(_st.nextToken());
+		float tmpG = Float.parseFloat(_st.nextToken());
+		float tmpB = Float.parseFloat(_st.nextToken());
+		setColorFilterRGB(tmpR, tmpG, tmpB);
+		colorFilter = true;
+	}
+
+	private void readCVD(StringTokenizer _st) throws LowVisionException {
+		if (_st.countTokens() != 1) {
+			throw new LowVisionException("CVD needs only one parameter(type).");
+		}
+		int type = Integer.parseInt(_st.nextToken());
+		setCVDType(type); 
+		CVD = true;
+	}
+
+	private void readEyesight(StringTokenizer _st) throws LowVisionException {
+		if (_st.countTokens() != 1) {
+			throw new LowVisionException(
+					"Eyesight needs only one parameter(degree).");
+		}
+		float tmp = Float.parseFloat(_st.nextToken());
+		setEyesightDegree(tmp);
+		eyesight = true;
+	}
+
+	private void readGlare(StringTokenizer _st) throws LowVisionException {
+		if (_st.countTokens() != 1) {
+			throw new LowVisionException(
+					"Glare needs only one parameter(degree).");
+		}
+		float tmp = Float.parseFloat(_st.nextToken());
+		setGlareDegree(tmp);
+		glare = true;
+	}
+
+	public int countTypes() {
+		int num = 0;
+
+		if (eyesight)
+			num++;
+		if (CVD)
+			num++;
+		if (colorFilter)
+			num++;
+		if (glare)
+			num++;
+
+		return (num);
+	}
+
+	public boolean doBlur() {
+		return (eyesight);
+	}
+
+	public boolean doChangeColors() {
+		return (CVD || colorFilter || glare);
+	}
+
+	// need to use same order as in the LowVisionFilter
+	public int convertColor(int _src) throws LowVisionException {
+		int dest = _src;
+		if (colorFilter) {
+			dest = ColorFilterOp.convertColor(dest, colorFilterR, colorFilterG,
+					colorFilterB);
+		}
+		if (glare) {
+			dest = GlareOp.convertColor(dest, glareDegree);
+		}
+		if (CVD) {
+			dest = CVDOp.convertColor(dest, CVDType);
+		}
+		return (dest);
+	}
+
+	public static int convertColor(int _src, LowVisionType _lvt)
+			throws LowVisionException {
+		return (_lvt.convertColor(_src));
+	}
+
+	public LowVisionType extractColorTypes() {
+		if (!doChangeColors()) {
+			return (null);
+		}
+		LowVisionType lv = null;
+		try {
+			lv = new LowVisionType();
+			if (this.colorFilter) {
+				lv.setColorFilter(true);
+				lv.setColorFilterRGB(this.getColorFilterRGB());
+			}
+			if (this.CVD) {
+				lv.setCVD(true);
+				lv.setCVDType(this.getCVDType());
+			}
+			if (this.glare) {
+				lv.setGlare(true);
+				lv.setGlareDegree(this.glareDegree);
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		return (lv);
+	}
+
+	public String toString() {
+		StringBuffer sb = new StringBuffer();
+		if (eyesight) {
+			sb.append("Eyesight:on Degree=");
+			sb.append("" + eyesightDegree);
+		} else {
+			sb.append("Eyesight:off,");
+		}
+		if (CVD) {
+			sb.append("  CVD:on Type=" + CVDType + ",");
+		} else {
+			sb.append("  CVD: off,");
+		}
+		if (colorFilter) {
+			sb.append("  ColorFilter:on Degree=" + colorFilterB);
+		} else {
+			sb.append("  ColorFilter:off");
+		}
+		return (sb.toString());
+	}
+
+	public double getDisplayHeight() {
+		return displayHeight;
+	}
+
+	public int getDisplayResolution() {
+		return displayResolution;
+	}
+
+	public double getEyeDisplayDistance() {
+		return eyeDisplayDistance;
+	}
+
+	public void setDisplayHeight(double displayHeight) {
+		this.displayHeight = displayHeight;
+	}
+
+	public void setDisplayResolution(int displayResolution) {
+		this.displayResolution = displayResolution;
+	}
+
+	public void setEyeDisplayDistance(double eyeDisplayDistance) {
+		this.eyeDisplayDistance = eyeDisplayDistance;
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/PageElement.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/PageElement.java
new file mode 100644
index 0000000..88da478
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/PageElement.java
@@ -0,0 +1,842 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision;
+
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import org.eclipse.actf.model.ui.editor.browser.CurrentStyles;
+import org.eclipse.actf.visualization.engines.lowvision.checker.W3CColorChecker;
+import org.eclipse.actf.visualization.engines.lowvision.color.ColorCSS;
+import org.eclipse.actf.visualization.engines.lowvision.color.ColorException;
+import org.eclipse.actf.visualization.engines.lowvision.color.ColorIRGB;
+import org.eclipse.actf.visualization.engines.lowvision.image.ImageException;
+import org.eclipse.actf.visualization.engines.lowvision.internal.util.DebugUtil;
+import org.eclipse.actf.visualization.engines.lowvision.problem.ColorProblem;
+import org.eclipse.actf.visualization.engines.lowvision.problem.FixedSizeFontProblem;
+import org.eclipse.actf.visualization.engines.lowvision.problem.FixedSmallFontProblem;
+import org.eclipse.actf.visualization.engines.lowvision.problem.LowVisionProblem;
+import org.eclipse.actf.visualization.engines.lowvision.problem.LowVisionProblemException;
+import org.eclipse.actf.visualization.engines.lowvision.problem.ProhibitedBackgroundColorProblem;
+import org.eclipse.actf.visualization.engines.lowvision.problem.ProhibitedBothColorsProblem;
+import org.eclipse.actf.visualization.engines.lowvision.problem.ProhibitedForegroundColorProblem;
+import org.eclipse.actf.visualization.engines.lowvision.problem.SmallFontProblem;
+import org.eclipse.actf.visualization.engines.lowvision.util.LengthUtil;
+
+/*
+ * informations from HTML DOM
+ */
+public class PageElement {
+
+	private static final String DELIM = "/";
+
+	// text check
+	private static final String[] nonTextTagNames = { "area", "base",
+			"basefont", "br", "col", "colgroup", "frame", "frameset", "head",
+			"html", "hr", "img", "input", "isindex", "link", "meta",
+			"optgroup", "option", "param", "script", "select", "style",
+			"textarea", "title" };
+
+	// tags that change font size when that succeeded pt from <body>
+	private static final String[] fontSizeChangeTags = { "big", "code", "h1",
+			"h2", "h3", "h5", "h6", "kbd", "pre", "samp", "small", "sub",
+			"sup", "tt" };
+
+	/*
+	 * tags that usually uses same font size (can change by using %,em,ex)
+	 */
+	private static final String[] alwaysFixedFontSizeTags = { "button",
+			"option", "textarea" };
+
+	public static final int UNSET_POSITION = -1;
+
+	public static final int UNSET_COLOR = -1;
+
+	private String id = null; // eclipse-actf-id
+
+	private CurrentStyles style = null;
+
+	private String tagName = null;
+
+	// position in the image
+	private int x = UNSET_POSITION;
+
+	private int y = UNSET_POSITION;
+
+	private int width = UNSET_POSITION;
+
+	private int height = UNSET_POSITION;
+
+	private int foregroundColor = UNSET_COLOR;
+
+	private int backgroundColor = UNSET_COLOR;
+
+	public PageElement(String _key, CurrentStyles _cs) throws ImageException {
+		id = _key;
+		style = _cs;
+
+		tagName = style.getTagName().toLowerCase();
+		setDimension();
+		setColors();
+	}
+
+	private void setDimension() {
+		x = Integer.parseInt(style.getOffsetLeft());
+		y = Integer.parseInt(style.getOffsetTop());
+		width = Integer.parseInt(style.getOffsetWidth());
+		height = Integer.parseInt(style.getOffsetHeight());
+	}
+
+	private void setColors() throws ImageException {
+		if (!isTextTag()) {
+			return;
+		}
+
+		String fgStr = style.getColor();
+		String bgStr = style.getBackgroundColor();
+		try {
+			foregroundColor = (new ColorCSS(fgStr)).toInt();
+			backgroundColor = (new ColorCSS(bgStr)).toInt();
+		} catch (ColorException e) {
+			e.printStackTrace();
+			throw new ImageException("Could not interpret colors.");
+		}
+	}
+
+	public int getX() {
+		return (x);
+	}
+
+	public int getY() {
+		return (y);
+	}
+
+	public int getWidth() {
+		return (width);
+	}
+
+	public int getHeight() {
+		return (height);
+	}
+
+	public String getTagName() {
+		return (tagName);
+	}
+
+	public int getForegroundColor() {
+		return (foregroundColor);
+	}
+
+	public int getBackgroundColor() {
+		return (backgroundColor);
+	}
+
+	// _lvType: for LowVision error check
+	// _targetPage: for guideline check
+	public LowVisionProblem[] check(LowVisionType _lvType,
+			TargetPage _targetPage) {
+		Vector<LowVisionProblem> problemVec = new Vector<LowVisionProblem>();
+
+		// ignore elements not in the rendered area
+		if (x < 0 || y < 0) {
+			return (new LowVisionProblem[0]);
+		}
+
+		ColorProblem cp = null;
+		try {
+			cp = checkColors(_lvType);
+		} catch (LowVisionException e) {
+			DebugUtil.errMsg(this, "Error occurred in checking colors: id = "
+					+ this.id);
+			e.printStackTrace();
+		}
+		if (cp != null) {
+			problemVec.addElement(cp);
+		}
+
+		FixedSizeFontProblem fsfp = null;
+		try {
+			fsfp = checkFixedSizeFont(_lvType);
+		} catch (LowVisionException e) {
+			DebugUtil.errMsg(this,
+					"Error occurred in checking fixed-size font: id = "
+							+ this.id);
+			e.printStackTrace();
+		}
+
+		SmallFontProblem sfp = null;
+		try {
+			sfp = checkSmallFont(_lvType);
+		} catch (LowVisionException e) {
+			DebugUtil.errMsg(this,
+					"Error occurred in checking small font: id = " + this.id);
+			e.printStackTrace();
+		}
+
+		if (fsfp != null && sfp != null) {
+			// // calc severity
+			// double proba = Math.max( fsfp.getProbability(),
+			// sfp.getProbability() );
+
+			// use fixed severity
+			double proba = LowVisionCommon.SEVERITY_FIXED_SMALL_FONT;
+			FixedSmallFontProblem newProblem = null;
+			try {
+				newProblem = new FixedSmallFontProblem(this, _lvType, proba);
+				problemVec.addElement(newProblem);
+			} catch (LowVisionProblemException e) {
+				e.printStackTrace();
+			}
+		} else if (fsfp != null) {
+			problemVec.addElement(fsfp);
+		} else if (sfp != null) {
+			problemVec.addElement(sfp);
+		}
+
+		String[] allowedForegroundColors = _targetPage
+				.getAllowedForegroundColors();
+		String[] allowedBackgroundColors = _targetPage
+				.getAllowedBackgroundColors();
+		ProhibitedForegroundColorProblem pfcp = null;
+		ProhibitedBackgroundColorProblem pbcp = null;
+
+		if (allowedForegroundColors != null
+				&& allowedForegroundColors.length > 0) {
+			try {
+				pfcp = checkAllowedForegroundColors(_lvType,
+						allowedForegroundColors);
+			} catch (LowVisionException lve) {
+				lve.printStackTrace();
+			}
+		}
+		if (allowedBackgroundColors != null
+				&& allowedBackgroundColors.length > 0) {
+			try {
+				pbcp = checkAllowedBackgroundColors(_lvType,
+						allowedBackgroundColors);
+			} catch (LowVisionException lve) {
+				lve.printStackTrace();
+			}
+		}
+		if ((pfcp != null) && (pbcp != null)) {// fg/bg
+			try {
+				problemVec.addElement(new ProhibitedBothColorsProblem(this,
+						_lvType,
+						LowVisionCommon.SEVERITY_PROHIBITED_BOTH_COLORS));
+			} catch (LowVisionProblemException lvpe) {
+				lvpe.printStackTrace();
+			}
+			pfcp = null;
+			pbcp = null;
+		} else if (pfcp != null) { // fg
+			problemVec.addElement(pfcp);
+		} else if (pbcp != null) { // bg
+			problemVec.addElement(pbcp);
+		}
+
+		int size = problemVec.size();
+		LowVisionProblem[] problemArray = new LowVisionProblem[size];
+		for (int i = 0; i < size; i++) {
+			problemArray[i] = (LowVisionProblem) (problemVec.elementAt(i));
+		}
+		return (problemArray);
+	}
+
+	public ColorProblem checkColors(LowVisionType _lvType)
+			throws LowVisionException {
+		if (!(_lvType.doChangeColors())) {
+			return (null);
+		}
+		if (!isTextTag()) {
+			return (null);
+		}
+
+		ColorIRGB fgSim = null;
+		ColorIRGB bgSim = null;
+		try {
+			fgSim = new ColorIRGB(_lvType.convertColor(foregroundColor));
+			bgSim = new ColorIRGB(_lvType.convertColor(backgroundColor));
+		} catch (LowVisionException e) {
+			e.printStackTrace();
+			throw new LowVisionException("Could not convert colors.");
+		}
+
+		W3CColorChecker w3c = new W3CColorChecker(fgSim, bgSim);
+		double severity = w3c.calcSeverity();
+		if (severity <= 0.0) {
+			return (null);
+		} else {
+			try {
+				return (new ColorProblem(this, _lvType, severity));
+			} catch (LowVisionProblemException e) {
+				e.printStackTrace();
+				return (null);
+			}
+		}
+	}
+
+	/*
+	 * fixed size font check experimental result (in IE6) (1)mm,cm,in,pt,pc,px ->
+	 * fixed (2)larger,smaller, xx-small to xx-large -> variable (3)em,ex,% ->
+	 * same with parent (if not specified in ancestor -> variable)
+	 * 
+	 * if <BODY> uses "pt" -> consider IE added this configuration
+	 * 
+	 * private static final Pattern regexFontSequence =
+	 * Pattern.compile("^(([^\\/]+\\/)*([^\\/]+))$" );
+	 * 
+	 */
+	private static final short FONT_SIZE_UNKNOWN = 0;
+
+	private static final short FONT_SIZE_FIXED = 1; // in, cm, mm, pc, px
+
+	private static final short FONT_SIZE_PT = 2; // pt
+
+	private static final short FONT_SIZE_RELATIVE = 3; // smaller, larger
+
+	// xx-small,..., xx-large
+	private static final short FONT_SIZE_ABSOLUTE = 4;
+
+	private static final short FONT_SIZE_PERCENT = 5; // %
+
+	private static final short FONT_SIZE_EM = 6; // em, ex
+
+	public FixedSizeFontProblem checkFixedSizeFont(LowVisionType _lvType)
+			throws LowVisionException {
+		if (!(_lvType.doBlur())) {
+			return (null);
+		}
+
+		if (!isTextTag()) {
+			return (null);
+		}
+
+		// difficult to change font size
+		if (isAlwaysFixedSizeFontTag(tagName)) {
+			return (null);
+		}
+
+		String fontStr = style.getFontSize().toLowerCase();
+
+		// directly under the <BODY>
+		if (fontStr.indexOf(DELIM) == -1) {
+			fontStr = digitToFontSetting(fontStr);
+			short type = fontSizeType(fontStr);
+			if (type == FONT_SIZE_FIXED) { // not include "pt"
+				try {
+					return (new FixedSizeFontProblem(this, _lvType,
+							LowVisionCommon.SEVERITY_FIXED_SIZE_FONT));
+				} catch (LowVisionProblemException e) {
+					e.printStackTrace();
+					return (null);
+				}
+			} else {
+				return (null);
+			}
+		}
+
+		boolean fixedFlag = false;
+		StringTokenizer st = new StringTokenizer(fontStr, DELIM);
+		int tokenCount = st.countTokens();
+		String myFont = digitToFontSetting(st.nextToken());
+		short myType = fontSizeType(myFont);
+		if (myType == FONT_SIZE_FIXED) {
+			fixedFlag = true;
+		} else if (myType == FONT_SIZE_RELATIVE || myType == FONT_SIZE_ABSOLUTE) {
+			// fixedFlag = false;
+		} else { // "pt", "em", "ex", "%"
+			String[] fontSequence = new String[tokenCount];
+			fontSequence[tokenCount - 1] = myFont;
+			for (int i = tokenCount - 2; i >= 0; i--) {
+				fontSequence[i] = digitToFontSetting(st.nextToken());
+			}
+			StringTokenizer stTag = new StringTokenizer(tagName, DELIM);
+			if (stTag.countTokens() != tokenCount) {
+				throw new LowVisionException(
+						"# of tagNames and fontSizes did not match.");
+			}
+			String[] tagNameSequence = new String[tokenCount];
+			for (int i = tokenCount - 1; i >= 0; i--) {
+				tagNameSequence[i] = stTag.nextToken();
+			}
+
+			// fixedFlag = false;
+			String curFont = fontSequence[0]; // <BODY>
+			short curType = fontSizeType(curFont);
+			boolean firstPtFlag = true;
+
+			// if( curType == FONT_SIZE_PARENT ){
+			// firstPtFlag = false;
+			// }else if( curType == FONT_SIZE_FIXED ){
+			// fixedFlag = true;
+			// }
+			if (curType != FONT_SIZE_PT) {
+				firstPtFlag = false;
+			}
+			if (curType == FONT_SIZE_FIXED) {
+				fixedFlag = true;
+			}
+
+			for (int i = 1; i < tokenCount; i++) {
+				String tmpFont = fontSequence[i];
+				String tmpTag = tagNameSequence[i];
+				// <TD>,<TH> -> same initialization at <BODY>
+				if (tmpTag.equals("td") || tmpTag.equals("th")) {
+					firstPtFlag = true;
+					if (curType != FONT_SIZE_PT) {
+						firstPtFlag = false;
+					}
+					if (curType == FONT_SIZE_FIXED) {
+						fixedFlag = true;
+					}
+				} else {
+					if (curFont.equals(tmpFont)) { // not defined by user
+						continue;
+					} else {
+						short tmpType = fontSizeType(tmpFont);
+						if (tmpType == FONT_SIZE_FIXED) {
+							fixedFlag = true;
+							firstPtFlag = true;
+						} else if (tmpType == FONT_SIZE_RELATIVE
+								|| tmpType == FONT_SIZE_ABSOLUTE) {
+							fixedFlag = false;
+							firstPtFlag = true;
+						} else if (tmpType == FONT_SIZE_PT) {
+							if (!firstPtFlag) {
+								firstPtFlag = true;
+								fixedFlag = false; // need check
+							} else if (curType != FONT_SIZE_PT
+									|| fixedFlag == true
+									|| !isFontSizeChangeTag(tmpTag)) {
+								fixedFlag = true;
+							}
+							// else{
+							// // "pt" & parent "pt" & variable & <PRE> etc. ->
+							// variable
+							// }
+						}
+						// else{
+						// // "em", "ex", "%"-> same as parent
+						// }
+						curFont = tmpFont;
+						curType = tmpType;
+					}
+				}
+			}
+		}
+
+		if (fixedFlag) {
+			try {
+				return (new FixedSizeFontProblem(this, _lvType,
+						LowVisionCommon.SEVERITY_FIXED_SIZE_FONT));
+			} catch (LowVisionProblemException e) {
+				e.printStackTrace();
+				return (null);
+			}
+		} else {
+			return (null);
+		}
+	}
+
+	private short fontSizeType(String _fontSize) {
+		String s = _fontSize.toLowerCase();
+
+		if (s.endsWith("mm") || s.endsWith("cm") || s.endsWith("in") ||
+		// s.endsWith("pt") || // pt is special
+				s.endsWith("pc") || s.endsWith("px")) {
+			return (FONT_SIZE_FIXED);
+		} else if (s.endsWith("pt")) {
+			return (FONT_SIZE_PT);
+		} else if (s.endsWith("%")) {
+			return (FONT_SIZE_PERCENT);
+		} else if (s.endsWith("em") || s.endsWith("ex")) {
+			return (FONT_SIZE_EM);
+		} else if (s.equals("smaller") || s.equals("larger")) {
+			return (FONT_SIZE_RELATIVE);
+		} else {
+			return (FONT_SIZE_ABSOLUTE);
+		}
+	}
+
+	private String digitToFontSetting(String _fontStr)
+			throws LowVisionException {
+
+		if (_fontStr.length() == 1) {
+			if (_fontStr.equals("1")) {
+				return ("xx-small");
+			} else if (_fontStr.equals("2")) {
+				return ("x-small");
+			} else if (_fontStr.equals("3")) {
+				return ("small");
+			} else if (_fontStr.equals("4")) {
+				return ("medium");
+			} else if (_fontStr.equals("5")) {
+				return ("large");
+			} else if (_fontStr.equals("6")) {
+				return ("x-large");
+			} else if (_fontStr.equals("7")) {
+				return ("xx-large");
+			} else {
+				throw new LowVisionException("Invalid font size setting: "
+						+ _fontStr);
+			}
+		} else if (_fontStr.startsWith("+")) {
+			if (_fontStr.equals("+1")) {
+				return ("120%");
+			} else if (_fontStr.equals("+2")) {
+				return ("144%");
+			} else if (_fontStr.equals("+3")) {
+				return ("173%");
+			} else if (_fontStr.equals("+4")) {
+				return ("207%");
+			} else if (_fontStr.equals("+5")) {
+				return ("249%");
+			} else if (_fontStr.equals("+6")) {
+				return ("299%");
+			} else if (_fontStr.equals("+0")) {
+				// used in some pages
+				return ("100%");
+			} else {
+				throw new LowVisionException("Invalid font size setting: "
+						+ _fontStr);
+			}
+		} else if (_fontStr.startsWith("-")) {
+			if (_fontStr.equals("-1")) {
+				return ("83%");
+			} else if (_fontStr.equals("-2")) {
+				return ("69%");
+			} else if (_fontStr.equals("-3")) {
+				return ("58%");
+			} else if (_fontStr.equals("-4")) {
+				return ("48%");
+			} else if (_fontStr.equals("-5")) {
+				return ("40%");
+			} else if (_fontStr.equals("-6")) {
+				return ("33%");
+			} else if (_fontStr.equals("-0")) {
+				return ("100%");
+			} else {
+				throw new LowVisionException("Invalid font size setting: "
+						+ _fontStr);
+			}
+		} else {
+			return (_fontStr);
+		}
+	}
+
+	private boolean isFontSizeChangeTag(String _st) {
+		int len = fontSizeChangeTags.length;
+		String s = _st.toLowerCase();
+		for (int i = 0; i < len; i++) {
+			if (s.equals(fontSizeChangeTags[i])) {
+				return (true);
+			}
+		}
+		return (false);
+	}
+
+	private boolean isAlwaysFixedSizeFontTag(String _st) {
+		String s = _st.toLowerCase();
+		int index = s.indexOf(DELIM);
+		if (index > -1) {
+			s = s.substring(0, index);
+		}
+		int len = alwaysFixedFontSizeTags.length;
+		for (int i = 0; i < len; i++) {
+			if (s.equals(alwaysFixedFontSizeTags[i])) {
+				return (true);
+			}
+		}
+		return (false);
+	}
+
+	/*
+	 * note: reset at td/th is experimental behaviour in IE6
+	 */
+	public SmallFontProblem checkSmallFont(LowVisionType _lvType)
+			throws LowVisionException {
+		if (!(_lvType.doBlur())) {
+			return (null);
+		}
+
+		double eyesightLength = _lvType.getEyesightLength();
+
+		if (!isTextTag()) {
+			return (null);
+		}
+
+		/*
+		 * TODO <OPTION>: offsetWidth, offsetHeight = 0 -> can't highlight
+		 * target
+		 * 
+		 * need to select parent <SELECT>
+		 */
+		if (tagName.startsWith("option")) {
+			return (null);
+		}
+
+		String fontStr = style.getFontSize().toLowerCase();
+
+		// reset at TD/TH
+		StringTokenizer fontSt = new StringTokenizer(fontStr, DELIM);
+		Vector<String> fontSequence = new Vector<String>();
+		StringTokenizer tagSt = new StringTokenizer(tagName, DELIM);
+		String curFont = fontSt.nextToken();
+		String curTag = tagSt.nextToken();
+		fontSequence.addElement(curFont);
+		while (fontSt.hasMoreTokens()) {
+			String tmpFont = fontSt.nextToken();
+			curTag = tagSt.nextToken();
+			if (curTag.equals("td") || curTag.equals("th")) {
+				if (!(tmpFont.equals(curFont))) {
+					fontSequence.addElement(tmpFont);
+				}
+				break;
+			} else {
+				if (!(tmpFont.equals(curFont))) {
+					fontSequence.addElement(tmpFont);
+				}
+			}
+			curFont = tmpFont;
+		}
+
+		int numFontSizeSettings = fontSequence.size();
+		String[] fontSizeSettings = new String[numFontSizeSettings];
+		for (int i = 0; i < numFontSizeSettings; i++) {
+			String tmpSetting = (String) (fontSequence.elementAt(i));
+			fontSizeSettings[i] = digitToFontSetting(tmpSetting);
+		}
+		fontSequence = null;
+
+		/*
+		 * if last value is "pt"-> consider the automatic setting by IE
+		 * 
+		 * define LARGEST as default to check the small size font in the LARGEST
+		 * setting
+		 * 
+		 */
+		String curFontSize = fontSizeSettings[numFontSizeSettings - 1];
+		if (fontSizeType(curFontSize) == FONT_SIZE_PT) {
+			fontSizeSettings[numFontSizeSettings - 1] = LowVisionCommon.IE_LARGEST_FONT;
+			for (int i = numFontSizeSettings - 2; i >= 0; i--) {
+				if (fontSizeSettings[i].equals(curFontSize)) {
+					fontSizeSettings[i] = LowVisionCommon.IE_LARGEST_FONT;
+				} else {
+					break;
+				}
+			}
+		}
+
+		float scaling = 1.0f; // smaller, larger, em, ex, %
+		short curType = FONT_SIZE_UNKNOWN;
+		for (int i = 0; i < numFontSizeSettings; i++) {
+			curFontSize = fontSizeSettings[i];
+			curType = fontSizeType(curFontSize);
+			if (curType == FONT_SIZE_FIXED || curType == FONT_SIZE_PT) {
+				break;
+			} else if (curType == FONT_SIZE_ABSOLUTE) {
+				if (curFontSize.equals("xx-large")) {
+					curFontSize = "48pt";
+				} else if (curFontSize.equals("x-large")) {
+					curFontSize = "32pt";
+				} else if (curFontSize.equals("large")) {
+					curFontSize = "24pt";
+				} else if (curFontSize.equals("medium")) {
+					curFontSize = "18pt";
+				} else if (curFontSize.equals("small")) {
+					curFontSize = "16pt";
+				} else if (curFontSize.equals("x-small")) {
+					curFontSize = "14pt";
+				} else if (curFontSize.equals("xx-small")) {
+					curFontSize = "12pt";
+				}
+				break;
+			} else if (curType == FONT_SIZE_PERCENT) {
+				double value = Double.parseDouble(curFontSize.substring(0,
+						curFontSize.length() - 1));
+				scaling *= (value / 100.0);
+			} else if (curType == FONT_SIZE_EM) {
+				double value = 0.0;
+				value = Double.parseDouble(curFontSize.substring(0, curFontSize
+						.length() - 2));
+				if (curFontSize.endsWith("ex")) {
+					value /= 2.0;
+				}
+				scaling *= (value * LowVisionCommon.IE_EM_SCALING);
+			} else if (curFontSize.equals("larger")) {
+				scaling *= LowVisionCommon.IE_LARGER_SCALING;
+			} else if (curFontSize.equals("smaller")) {
+				scaling *= LowVisionCommon.IE_SMALLER_SCALING;
+			} else {
+				throw new LowVisionException("unknown font size setting: "
+						+ curFontSize);
+			}
+		}
+		if (curType != FONT_SIZE_FIXED && curType != FONT_SIZE_PT
+				&& curType != FONT_SIZE_ABSOLUTE) {
+			curFontSize = LowVisionCommon.IE_LARGEST_FONT;
+		}
+
+		float value = Float.parseFloat(curFontSize.substring(0, curFontSize
+				.length() - 2));
+		float sizeInMm = 0.0f;
+		if (curFontSize.endsWith("in")) {
+			sizeInMm = LengthUtil.in2mm(value);
+		} else if (curFontSize.endsWith("cm")) {
+			sizeInMm = LengthUtil.cm2mm(value);
+		} else if (curFontSize.endsWith("mm")) {
+			sizeInMm = value;
+		} else if (curFontSize.endsWith("pt")) {
+			sizeInMm = LengthUtil.pt2mm(value);
+		} else if (curFontSize.endsWith("pc")) {
+			sizeInMm = LengthUtil.pc2mm(value);
+		} else if (curFontSize.endsWith("px")) {
+			sizeInMm = LengthUtil.px2mm(value);
+		} else {
+			throw new LowVisionException("unknown font size unit: "
+					+ curFontSize);
+		}
+		sizeInMm *= scaling;
+
+		// can distinguish "c" and "o"?
+		// size of "c" is about half of char size
+		// disconnected part of "c" is about 1/5 of "c"
+		double severity = 2.0 - sizeInMm / (10.0 * eyesightLength);
+		if (severity > 1.0)
+			severity = 1.0;
+		else if (severity < 0.0)
+			severity = 0.0;
+
+		if (severity > 0.0) {
+			try {
+				// fixed severity
+				return (new SmallFontProblem(this, _lvType,
+						LowVisionCommon.SEVERITY_SMALL_FONT));
+			} catch (LowVisionProblemException e) {
+				e.printStackTrace();
+				return (null);
+			}
+		} else {
+			return (null);
+		}
+	}
+
+	public ProhibitedForegroundColorProblem checkAllowedForegroundColors(
+			LowVisionType _lvType, String[] _allowedColors)
+			throws LowVisionException {
+		if (_allowedColors == null) {
+			return (null);
+		}
+		int len = _allowedColors.length;
+		if (len == 0) {
+			return (null);
+		}
+
+		if (!isTextTag()) {
+			return (null);
+		}
+
+		// TODO check link color?
+		if (tagName.startsWith("a/")) {
+			return (null);
+		}
+
+		// use "black" as default
+		// TODO use system color
+		if (foregroundColor == ColorCSS.DEFAULT_COLOR_INT) {
+			return (null);
+		}
+
+		for (int i = 0; i < len; i++) {
+			String curColorString = _allowedColors[i];
+			ColorIRGB templateColor = null;
+			try {
+				templateColor = new ColorIRGB(curColorString);
+			} catch (ColorException ce) {
+				ce.printStackTrace();
+				throw new LowVisionException(
+						"ColorException occurs while converting String \""
+								+ curColorString + "\" to a color.");
+			}
+			if (templateColor.equals(foregroundColor)) {
+				return (null);
+			}
+		}
+
+		try {
+			return (new ProhibitedForegroundColorProblem(this, _lvType,
+					LowVisionCommon.SEVERITY_PROHIBITED_FOREGROUND_COLOR));
+		} catch (LowVisionProblemException lvpe) {
+			lvpe.printStackTrace();
+			return (null);
+		}
+	}
+
+	public ProhibitedBackgroundColorProblem checkAllowedBackgroundColors(
+			LowVisionType _lvType, String[] _allowedColors)
+			throws LowVisionException {
+		if (_allowedColors == null) {
+			return (null);
+		}
+		int len = _allowedColors.length;
+		if (len == 0) {
+			return (null);
+		}
+
+		if (!isTextTag()) {
+			return (null);
+		}
+
+		// use transparent as defaul background-color
+		if (backgroundColor == ColorCSS.DEFAULT_BACKGROUND_COLOR_INT) {
+			return (null);
+		}
+
+		for (int i = 0; i < len; i++) {
+			String curColorString = _allowedColors[i];
+			ColorIRGB templateColor = null;
+			try {
+				templateColor = new ColorIRGB(curColorString);
+			} catch (ColorException ce) {
+				ce.printStackTrace();
+				throw new LowVisionException(
+						"ColorException occurs while converting String \""
+								+ curColorString + "\" to a color.");
+			}
+			if (templateColor.equals(backgroundColor)) {
+				return (null);
+			}
+		}
+		try {
+			return (new ProhibitedBackgroundColorProblem(this, _lvType,
+					LowVisionCommon.SEVERITY_PROHIBITED_BACKGROUND_COLOR));
+		} catch (LowVisionProblemException lvpe) {
+			lvpe.printStackTrace();
+			return (null);
+		}
+	}
+
+	private boolean isTextTag() {
+		String tagName = style.getTagName().toLowerCase();
+		int len = nonTextTagNames.length;
+		for (int i = 0; i < len; i++) {
+			if (tagName.startsWith(nonTextTagNames[i] /* +"/" */)) {
+				return (false);
+			}
+			// if( tagName.equals( nonTextTagNames[i] ) ){
+			// return( false );
+			// }
+		}
+		return (true);
+	}
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/TargetPage.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/TargetPage.java
new file mode 100644
index 0000000..564023f
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/TargetPage.java
@@ -0,0 +1,451 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.actf.model.ui.editor.ImagePositionInfo;
+import org.eclipse.actf.model.ui.editor.browser.CurrentStyles;
+import org.eclipse.actf.visualization.engines.lowvision.image.ImageException;
+import org.eclipse.actf.visualization.engines.lowvision.image.Int2D;
+import org.eclipse.actf.visualization.engines.lowvision.image.PageImage;
+import org.eclipse.actf.visualization.engines.lowvision.image.SimulatedPageImage;
+import org.eclipse.actf.visualization.engines.lowvision.internal.util.DebugUtil;
+import org.eclipse.actf.visualization.engines.lowvision.internal.util.LowVisionProblemConverter;
+import org.eclipse.actf.visualization.engines.lowvision.internal.util.ScoreUtil;
+import org.eclipse.actf.visualization.engines.lowvision.io.ImageWriter;
+import org.eclipse.actf.visualization.engines.lowvision.io.LowVisionIOException;
+import org.eclipse.actf.visualization.engines.lowvision.problem.LowVisionProblem;
+import org.eclipse.actf.visualization.engines.lowvision.problem.LowVisionProblemException;
+import org.eclipse.actf.visualization.engines.lowvision.problem.LowVisionProblemGroup;
+import org.eclipse.actf.visualization.engines.lowvision.util.DecisionMaker;
+import org.eclipse.actf.visualization.eval.problem.IProblemItem;
+import org.eclipse.actf.visualization.eval.problem.ProblemItemLV;
+
+
+public class TargetPage {
+	private static final int UNSET = -1;
+
+	private PageImage pageImage = null; // rendered image in browser
+
+	private ImagePositionInfo[] tmpInteriorImagePositions = null;
+
+	private PageElement[] pageElements = null; // HTML Element info from DOM
+
+	private String[] allowedForegroundColors = null;
+
+	private String[] allowedBackgroundColors = null;
+
+	private int pageWidth = UNSET;
+
+	private int pageHeight = UNSET;
+
+	private String overallRatingString = "";
+
+	private String overallRatingImageString = "";
+
+	public TargetPage() {
+	}
+
+	public void disposePageImage() {
+		pageImage.disposeInt2D();
+	}
+
+	public PageImage getPageImage() {
+		return (pageImage);
+	}
+
+	public void setPageImage(PageImage _pi) {
+		pageImage = _pi;
+		if (pageImage != null) {
+			if (pageImage.isInteriorImageArraySet()) {
+				try {
+					pageImage.extractCharacters();
+				} catch (ImageException e) {
+					e.printStackTrace();
+				}
+			} else if (tmpInteriorImagePositions != null) {
+				pageImage.setInteriorImagePosition(tmpInteriorImagePositions);
+				this.tmpInteriorImagePositions = null;
+				try {
+					pageImage.extractCharacters();
+				} catch (ImageException e) {
+					e.printStackTrace();
+				}
+			}
+			pageWidth = pageImage.getWidth();
+			pageHeight = pageImage.getHeight();
+		}
+	}
+
+	public ImagePositionInfo[] getInteriorImagePosition() {
+		if (pageImage == null) {
+			return (null);
+		}
+		return (pageImage.getInteriorImagePosition());
+	}
+
+	public void setInteriorImagePosition(ImagePositionInfo[] infoArray) {
+		if (pageImage != null) {
+			pageImage.setInteriorImagePosition(infoArray);
+			try {
+				pageImage.extractCharacters();
+			} catch (ImageException e) {
+				e.printStackTrace();
+			}
+		} else {
+			this.tmpInteriorImagePositions = infoArray;
+		}
+	}
+
+	public PageElement[] getPageElements() {
+		return (pageElements);
+	}
+
+	public void setCurrentStyles(HashMap _styleMap) {
+		Object[] keyArray = _styleMap.keySet().toArray();
+		int len = keyArray.length;
+		pageElements = new PageElement[len];
+		for (int i = 0; i < len; i++) {
+			try {
+				pageElements[i] = new PageElement((String) (keyArray[i]),
+						(CurrentStyles) (_styleMap.get(keyArray[i])));
+			} catch (ImageException e) {
+				e.printStackTrace();
+				pageElements[i] = null;
+			}
+		}
+	}
+
+	public String[] getAllowedForegroundColors() {
+		return (allowedForegroundColors);
+	}
+
+	public String[] getAllowedBackgroundColors() {
+		return (allowedBackgroundColors);
+	}
+
+	public void setAllowedColors(String[] _fg, String[] _bg) {
+		allowedForegroundColors = _fg;
+		allowedBackgroundColors = _bg;
+	}
+
+	public void setAllowedForegroundColors(String[] _fg) {
+		allowedForegroundColors = _fg;
+	}
+
+	public void setAllowedBackgroundColors(String[] _bg) {
+		allowedBackgroundColors = _bg;
+	}
+
+	public void clearAllowedColors() {
+		allowedForegroundColors = null;
+		allowedBackgroundColors = null;
+	}
+
+	public void clearAllowedForegroundColors() {
+		allowedForegroundColors = null;
+	}
+
+	public void clearAllowedBackgroundColors() {
+		allowedBackgroundColors = null;
+	}
+
+	public String getOverallRatingString() {
+		return (overallRatingString);
+	}
+
+	public SimulatedPageImage simulate(LowVisionType _lvType)
+			throws ImageException {
+		if (this.pageImage == null) {
+			return (null);
+		}
+		return (new SimulatedPageImage(this.pageImage, _lvType));
+	}
+
+	public List<IProblemItem> check(LowVisionType _lvType, String urlS,
+			int frameId) {
+
+		// TODO LowVisionProblem/LowVisionProblemGroup
+
+		LowVisionProblemGroup[] pageImageProblemArray = null;
+		LowVisionProblemGroup[] pageElementProblemArray = null;
+		LowVisionProblemGroup[] answerProblemArray = null;
+
+		if (pageImage != null) {
+			try {
+				pageImageProblemArray = pageImage.checkCharacters(_lvType);
+			} catch (LowVisionProblemException lvpe) {
+				lvpe.printStackTrace();
+			} catch (ImageException ie) {
+				ie.printStackTrace();
+			}
+		}
+
+		if (pageElements != null) {
+			Vector<LowVisionProblemGroup> pageElementProblemVec = new Vector<LowVisionProblemGroup>();
+			int len = pageElements.length;
+			for (int i = 0; i < len; i++) {
+				PageElement curElement = pageElements[i];
+				if (curElement == null) {
+					continue;
+				}
+				LowVisionProblem[] curProblemArray = curElement.check(_lvType,
+						this);
+				int curLen = 0;
+				if (curProblemArray != null) {
+					curLen = curProblemArray.length;
+				}
+
+				// convert to LowVisionProblemGroup
+				for (int j = 0; j < curLen; j++) {
+					Vector<LowVisionProblem> tmpVec = new Vector<LowVisionProblem>();
+					tmpVec.addElement(curProblemArray[j]);
+					LowVisionProblemGroup lvpGroup = null;
+					try {
+						lvpGroup = new LowVisionProblemGroup(tmpVec);
+						pageElementProblemVec.addElement(lvpGroup);
+					} catch (LowVisionProblemException lvpe) {
+						lvpe.printStackTrace();
+					}
+				}
+			}
+
+			int totalSize = pageElementProblemVec.size();
+			pageElementProblemArray = new LowVisionProblemGroup[totalSize];
+			for (int i = 0; i < totalSize; i++) {
+				pageElementProblemArray[i] = (LowVisionProblemGroup) (pageElementProblemVec
+						.elementAt(i));
+			}
+		}
+
+		int len1 = 0;
+		if (pageImageProblemArray != null) {
+			len1 = pageImageProblemArray.length;
+		}
+		int len2 = 0;
+		if (pageElementProblemArray != null) {
+			len2 = pageElementProblemArray.length;
+		}
+
+		answerProblemArray = new LowVisionProblemGroup[len1 + len2];
+		for (int i = 0; i < len1; i++) {
+			answerProblemArray[i] = pageImageProblemArray[i];
+		}
+		for (int i = 0; i < len2; i++) {
+			answerProblemArray[len1 + i] = pageElementProblemArray[i];
+		}
+
+		pageImageProblemArray = null;
+		pageElementProblemArray = null;
+
+		calcOverallRating(answerProblemArray);
+
+		return (LowVisionProblemConverter.convert(answerProblemArray, urlS,
+				frameId));
+	}
+
+	private void calcOverallRating(LowVisionProblemGroup[] _problemGroupArray) {
+		int len = 0;
+		if (_problemGroupArray != null) {
+			len = _problemGroupArray.length;
+		}
+
+		double totalSeverity = 0.0;
+		for (int k = 0; k < len; k++) {
+			LowVisionProblemGroup curGroup = _problemGroupArray[k];
+			if (curGroup == null) {
+				continue;
+			}
+			totalSeverity += curGroup.getProbability();
+		}
+		overallRatingString = ScoreUtil.getScoreString(totalSeverity);
+		overallRatingImageString = ScoreUtil.getScoreImageString(totalSeverity);
+
+	}
+
+	// Max size of Problem Map image
+	private static final int PROBLEM_MAP_LENGTH = 100;
+
+	public void unsupportedModeReport(File targetFile)
+			throws LowVisionException {
+
+		StringBuffer sb = new StringBuffer();
+		sb.append("<HTML>\n<HEAD>\n<TITLE>Report from LowVision Evaulator</TITLE>\n");
+		sb.append("</HEAD><BODY>");
+		// TODO
+		sb.append("</BODY>\n</HTML>\n");
+		if (targetFile != null) {
+			try {
+				PrintWriter pw = new PrintWriter(targetFile);
+				pw.println(sb.toString());
+				pw.close();
+			} catch (IOException e) {
+				e.printStackTrace();
+				throw new LowVisionException("Could not write to " + targetFile);
+			}
+		}
+	}
+
+	public void makeAndStoreReport(String _path, String _htmlName,
+			String _imgName, List _problemGroupArray) throws LowVisionException {
+		boolean doMakeProblemMap = true;
+		if (this.pageImage == null)
+			doMakeProblemMap = false;
+
+		String path = _path;
+		if (!(path.endsWith(File.separator))) {
+			path += File.separator;
+		}
+		String htmlPath = path + _htmlName;
+		String imgPath = path + _imgName;
+
+		int len = 0;
+		if (_problemGroupArray != null) {
+			len = _problemGroupArray.size();
+		}
+
+		Int2D scoreMap = null;
+
+		if (doMakeProblemMap) {
+			int shorter = pageWidth;
+			if (pageWidth > pageHeight) {
+				shorter = pageHeight;
+			}
+			int scale = (int) (Math.ceil(((double) shorter)
+					/ (double) (PROBLEM_MAP_LENGTH)));
+			if (scale <= 0) {
+				throw new LowVisionException("scale is out of range: " + scale);
+			}
+			int mapWidth = (int) (Math.ceil((double) (pageWidth)
+					/ (double) (scale)));
+			int mapHeight = (int) (Math.ceil((double) (pageHeight)
+					/ (double) (scale)));
+			scoreMap = new Int2D(mapWidth, mapHeight);
+
+			for (int k = 0; k < len; k++) {
+				if (_problemGroupArray.get(k) instanceof ProblemItemLV) {
+					ProblemItemLV curProblem = (ProblemItemLV) _problemGroupArray
+							.get(k);
+
+					int groupX = curProblem.getX();
+					if (groupX < 0)
+						groupX = 0;
+					int groupY = curProblem.getY();
+					if (groupY < 0)
+						groupY = 0;
+					int groupWidth = curProblem.getWidth();
+					int groupHeight = curProblem.getHeight();
+					/*
+					 *  TODO consideration for inline element
+					 *   x+width or y+height might
+					 *    exseed the page size
+					 *    overlap the next block level element
+					 *    etc.
+					 */
+					int rightLimit = groupX + groupWidth;
+					if (pageWidth < rightLimit)
+						rightLimit = pageWidth;
+					int bottomLimit = groupY + groupHeight;
+					if (pageHeight < bottomLimit)
+						bottomLimit = pageHeight;
+					for (int j = groupY; j < bottomLimit; j++) {
+						for (int i = groupX; i < rightLimit; i++) {
+							// scoreMap.data[j+groupY][i+groupX] = fillingColor;
+							// debug
+							try {
+								scoreMap.data[j / scale][i / scale] += curProblem
+										.getSeverityLV();
+							} catch (Exception e) {
+								e.printStackTrace();
+								DebugUtil.errMsg(this, "i=" + i + ", j=" + j
+										+ ", groupX=" + groupX + ", groupY="
+										+ groupY + ", groupWidth=" + groupWidth
+										+ ", groupHeight=" + groupHeight
+										+ ", pageWidth=" + pageWidth
+										+ ", pageHeight=" + pageHeight);
+								throw new LowVisionException(
+										"Error while making problem map");
+							}
+						}
+					}
+				}
+			}
+
+			double scaleDouble = (double) (scale * scale); 
+			for (int j = 0; j < mapHeight; j++) {
+				for (int i = 0; i < mapWidth; i++) {
+					scoreMap.data[j][i] = DecisionMaker
+							.getScoreMapColor(((double) (scoreMap.data[j][i]))
+									/ 100.0 / scaleDouble);
+				}
+			}
+
+			try {
+				ImageWriter.writeBufferedImage(scoreMap.toBufferedImage(),
+						imgPath);
+			} catch (LowVisionIOException lvioe) {
+				lvioe.printStackTrace();
+				throw new LowVisionException(
+						"An IO error occurred while writing the problem map file of this page.");
+			}
+		}
+		scoreMap = null;
+
+		StringBuffer sb = new StringBuffer();
+		sb.append("<HTML>\n<HEAD>\n<TITLE>Report from LowVision Evaulator</TITLE>\n");
+		sb.append("<STYLE type=\"text/css\">\n");
+		sb.append("IMG {border:2 solid black}\n");
+		sb.append("</STYLE>\n");
+		sb.append("</HEAD><BODY>");
+
+		// sb.append( "<DIV>\nOverall rating: <B>" + overallRatingString +
+		// "</B></DIV>\n");
+
+		// TODO lv report files -> result dir
+		sb.append("<DIV>\nOverall rating: <IMG src=\"./img/"
+				+ overallRatingImageString + "\" alt=\"" + overallRatingString
+				+ "\"></DIV>\n");
+
+		sb.append("<HR>");
+		sb.append("<DIV align=\"center\">\n");
+		if (doMakeProblemMap) {
+			sb.append("Problem Map<BR>\n");
+			sb.append("<IMG src=\"" + _imgName + "\" alt=\"score map\" ");
+			if (pageWidth >= pageHeight) {
+				sb.append("width=\"75%\"");
+			} else {
+				sb.append("height=\"75%\"");
+			}
+			sb.append(">\n");
+		} else {
+			sb.append("Problem map is not available for this page.");
+		}
+		sb.append("</DIV>\n");
+		sb.append("</BODY>\n</HTML>\n");
+		try {
+			PrintWriter pw = new PrintWriter(new FileWriter(htmlPath));
+			pw.println(sb.toString());
+			pw.close();
+		} catch (IOException e) {
+			e.printStackTrace();
+			throw new LowVisionException("Could not write to " + htmlPath);
+		}
+	}
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/character/CandidateCharacter.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/character/CandidateCharacter.java
new file mode 100644
index 0000000..f27e97c
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/character/CandidateCharacter.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.character;
+
+import org.eclipse.actf.visualization.engines.lowvision.image.ConnectedComponent;
+import org.eclipse.actf.visualization.engines.lowvision.image.Container;
+import org.eclipse.actf.visualization.engines.lowvision.image.PageComponent;
+import org.eclipse.actf.visualization.engines.lowvision.image.PageImage;
+
+/*
+ * Character candidate (SS, SM, part of MS)
+ * 
+ */
+public class CandidateCharacter extends PageComponent{
+	private int foregroundColor = -1;
+
+	public CandidateCharacter( PageImage _pi, ConnectedComponent _cc, int _color ){
+		super( CANDIDATE_CHARACTER_TYPE, _pi );
+		cc = _cc;
+		foregroundColor = _color;
+	}
+
+	public void setContainer( Container _c ){
+		container = _c;
+	}
+
+	public int getForegroundColor() {
+		return foregroundColor;
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/character/CandidateUnderlinedCharacter.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/character/CandidateUnderlinedCharacter.java
new file mode 100644
index 0000000..848d630
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/character/CandidateUnderlinedCharacter.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.character;
+
+import org.eclipse.actf.visualization.engines.lowvision.image.ConnectedComponent;
+import org.eclipse.actf.visualization.engines.lowvision.image.Container;
+import org.eclipse.actf.visualization.engines.lowvision.image.PageComponent;
+import org.eclipse.actf.visualization.engines.lowvision.image.PageImage;
+
+/*
+ * Character candidate with underline(SS, SM, part of MS(rare case))
+ */
+public class CandidateUnderlinedCharacter extends PageComponent {
+	private int foregroundColor = -1;
+
+	public CandidateUnderlinedCharacter(PageImage _pi, ConnectedComponent _cc,
+			int _color) {
+		super(CANDIDATE_UNDERLINED_CHARACTER_TYPE, _pi);
+		cc = _cc;
+		foregroundColor = _color;
+	}
+
+	public void setContainer(Container _c) {
+		container = _c;
+	}
+
+	public int getForegroundColor() {
+		return foregroundColor;
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/character/CharacterMS.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/character/CharacterMS.java
new file mode 100644
index 0000000..4f1f7e2
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/character/CharacterMS.java
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.character;
+
+import org.eclipse.actf.visualization.engines.lowvision.image.ConnectedComponent;
+import org.eclipse.actf.visualization.engines.lowvision.image.Container;
+import org.eclipse.actf.visualization.engines.lowvision.image.ImageException;
+import org.eclipse.actf.visualization.engines.lowvision.image.Int2D;
+import org.eclipse.actf.visualization.engines.lowvision.image.PageComponent;
+import org.eclipse.actf.visualization.engines.lowvision.image.PageImage;
+import org.eclipse.actf.visualization.engines.lowvision.image.Topology;
+
+/*
+ * Character (multi fg color/single bg color)
+ */
+public class CharacterMS extends PageComponent {
+	private int backgroundColor = -1; // container.color
+
+	private int foregroundColor = -1; // average color
+
+	private Topology topology = null;
+
+	private int[][] image = null;
+
+	public CharacterMS(PageImage _pi, ConnectedComponent _cc, Container _cont,
+			int[][] _pixel) throws ImageException {
+		super(MS_CHARACTER_TYPE, _pi);
+		cc = _cc;
+		container = _cont;
+		backgroundColor = _cont.getColor();
+		topology = new Topology(cc.thinning());
+		if (_pixel != null) {
+			int w = cc.getShape().getWidth();
+			int h = cc.getShape().getHeight();
+			int offsetX = cc.getLeft();
+			int offsetY = cc.getTop();
+			image = new int[h][w];
+			int sumR = 0;
+			int sumG = 0;
+			int sumB = 0;
+			byte[][] data = cc.getShape().getData();
+			for (int j = 0; j < h; j++) {
+				for (int i = 0; i < w; i++) {
+					image[j][i] = _pixel[j + offsetY][i + offsetX];
+					if (data[j][i] != 0) {
+						int color = image[j][i];
+						sumR += (color >> 16) & 0xff;
+						sumG += (color >> 8) & 0xff;
+						sumB += color & 0xff;
+					}
+				}
+			}
+			sumR /= cc.getCount();
+			sumG /= cc.getCount();
+			sumB /= cc.getCount();
+			foregroundColor = (sumR << 16) | (sumG << 8) | (sumB);
+		}
+	}
+
+	public CharacterMS(PageImage _pi, ConnectedComponent _cc, Container _cont,
+			Int2D _pixel) throws ImageException {
+		this(_pi, _cc, _cont, _pixel.data);
+	}
+
+	public int getBackgroundColor() {
+		return (backgroundColor);
+	}
+
+	public int getForegroundColor() {
+		return (foregroundColor);
+	}
+
+	public Int2D getInt2D() throws ImageException {
+		return (new Int2D(cc.getShape().getWidth(), cc.getShape().getHeight(), image));
+	}
+
+	public Int2D makeMarginedImage(int _margin) throws ImageException {
+		if (_margin == 0) {
+			return (getInt2D());
+		}
+		if (_margin < 0) {
+			throw new ImageException("The margin must be non-negative.");
+		}
+		Int2D i2d = new Int2D(cc.getShape().getWidth() + 2 * _margin, cc.getShape().getHeight() + 2
+				* _margin);
+		i2d.fill(backgroundColor);
+		for (int j = 0; j < cc.getShape().getHeight(); j++) {
+			for (int i = 0; i < cc.getShape().getWidth(); i++) {
+				i2d.data[j + _margin][i + _margin] = image[j][i];
+			}
+		}
+		return (i2d);
+	}
+
+	public Topology getTopology() {
+		return topology;
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/character/CharacterSM.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/character/CharacterSM.java
new file mode 100644
index 0000000..bc5887a
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/character/CharacterSM.java
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.character;
+
+import org.eclipse.actf.visualization.engines.lowvision.image.ConnectedComponent;
+import org.eclipse.actf.visualization.engines.lowvision.image.Container;
+import org.eclipse.actf.visualization.engines.lowvision.image.ImageException;
+import org.eclipse.actf.visualization.engines.lowvision.image.Int2D;
+import org.eclipse.actf.visualization.engines.lowvision.image.PageComponent;
+import org.eclipse.actf.visualization.engines.lowvision.image.PageImage;
+import org.eclipse.actf.visualization.engines.lowvision.image.Topology;
+
+/*
+ * Character (single fg color/multi bg color)
+ */
+public class CharacterSM extends PageComponent {
+	private int foregroundColor = -1;
+
+	private Topology topology = null;
+
+	private int[][] image = null;
+
+	public CharacterSM(CandidateCharacter _cChar, int[][] _pixel)
+			throws ImageException {
+		super(SM_CHARACTER_TYPE, _cChar.getPageImage());
+		cc = _cChar.cc;
+		container = _cChar.container;
+		foregroundColor = _cChar.getForegroundColor();
+		topology = new Topology(cc.thinning());
+		if (_pixel != null) {
+			int w = cc.getShape().getWidth();
+			int h = cc.getShape().getHeight();
+			int offsetX = cc.getLeft();
+			int offsetY = cc.getTop();
+			image = new int[h][w];
+			for (int j = 0; j < h; j++) {
+				for (int i = 0; i < w; i++) {
+					image[j][i] = _pixel[j + offsetY][i + offsetX];
+				}
+			}
+		}
+	}
+
+	public CharacterSM(CandidateCharacter _cChar, Int2D _pixel)
+			throws ImageException {
+		this(_cChar, _pixel.data);
+	}
+
+	public CharacterSM(PageImage _pi, ConnectedComponent _cc, Container _cont,
+			int _color, int[][] _pixel) throws ImageException {
+		super(SM_CHARACTER_TYPE, _pi);
+		cc = _cc;
+		container = _cont;
+		foregroundColor = _color;
+		topology = new Topology(cc.thinning());
+		if (_pixel != null) {
+			int w = cc.getShape().getWidth();
+			int h = cc.getShape().getHeight();
+			int offsetX = cc.getLeft();
+			int offsetY = cc.getTop();
+			image = new int[h][w];
+			for (int j = 0; j < h; j++) {
+				for (int i = 0; i < w; i++) {
+					image[j][i] = _pixel[j + offsetY][i + offsetX];
+				}
+			}
+		}
+	}
+
+	public CharacterSM(PageImage _pi, ConnectedComponent _cc, Container _cont,
+			int _color, Int2D _pixel) throws ImageException {
+		this(_pi, _cc, _cont, _color, _pixel.data);
+	}
+
+	public int getForegroundColor() {
+		return (foregroundColor);
+	}
+
+	public int[][] getImage() {
+		return (image);
+	}
+
+	public Int2D getInt2D() throws ImageException {
+		return (new Int2D(cc.getShape().getWidth(), cc.getShape().getHeight(), image));
+	}
+
+	public Int2D makeMarginedImage(int _margin) throws ImageException {
+		if (_margin == 0) {
+			return (getInt2D());
+		}
+		if (_margin < 0) {
+			throw new ImageException("The margin must be non-negative.");
+		}
+		int w = cc.getShape().getWidth();
+		int h = cc.getShape().getHeight();
+		int largeW = w + 2 * _margin;
+		int largeH = h + 2 * _margin;
+		Int2D i2d = new Int2D(largeW, largeH);
+		for (int j = 0; j < h; j++) {
+			for (int i = 0; i < w; i++) {
+				i2d.data[j + _margin][i + _margin] = image[j][i];
+			}
+			for (int i = 0; i < _margin; i++) {
+				i2d.data[j + _margin][i] = image[j][0];
+				i2d.data[j + _margin][largeW - 1 - i] = image[j][w - 1];
+			}
+		}
+		for (int i = 0; i < w; i++) {
+			for (int j = 0; j < _margin; j++) {
+				i2d.data[j][i + _margin] = image[0][i];
+				i2d.data[largeH - 1 - j][i + _margin] = image[h - 1][i];
+			}
+		}
+		for (int j = 0; j < _margin; j++) {
+			for (int i = 0; i < _margin; i++) {
+				i2d.data[j][i] = image[0][0];
+				i2d.data[j][largeW - 1 - i] = image[0][w - 1];
+				i2d.data[largeH - 1 - j][i] = image[h - 1][0];
+				i2d.data[largeH - 1 - j][largeW - 1 - i] = image[h - 1][w - 1];
+			}
+		}
+		return (i2d);
+	}
+
+	public Topology getTopology() {
+		return topology;
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/character/CharacterSS.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/character/CharacterSS.java
new file mode 100644
index 0000000..b54c926
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/character/CharacterSS.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.character;
+
+import org.eclipse.actf.visualization.engines.lowvision.image.ConnectedComponent;
+import org.eclipse.actf.visualization.engines.lowvision.image.Container;
+import org.eclipse.actf.visualization.engines.lowvision.image.ImageException;
+import org.eclipse.actf.visualization.engines.lowvision.image.Int2D;
+import org.eclipse.actf.visualization.engines.lowvision.image.PageComponent;
+import org.eclipse.actf.visualization.engines.lowvision.image.PageImage;
+import org.eclipse.actf.visualization.engines.lowvision.image.Topology;
+
+/*
+ * Character (single fg color/single bg color)
+ */
+public class CharacterSS extends PageComponent {
+	private int foregroundColor = -1;
+
+	private int backgroundColor = -1; // container.color
+
+	private Topology topology = null;
+
+	public CharacterSS(CandidateCharacter _cChar) throws ImageException {
+		super(SS_CHARACTER_TYPE, _cChar.getPageImage());
+		cc = _cChar.cc;
+		container = _cChar.getContainer();
+		foregroundColor = _cChar.getForegroundColor();
+		backgroundColor = container.getColor();
+		topology = new Topology(cc.thinning());
+	}
+
+	public CharacterSS(PageImage _pi, ConnectedComponent _cc, Container _cont,
+			int _fg) throws ImageException {
+		super(SS_CHARACTER_TYPE, _pi);
+		cc = _cc;
+		container = _cont;
+		foregroundColor = _fg;
+		backgroundColor = container.getColor();
+		topology = new Topology(cc.thinning());
+	}
+
+	public int getForegroundColor() {
+		return (foregroundColor);
+	}
+
+	public int getBackgroundColor() {
+		return (backgroundColor);
+	}
+
+	public Int2D makeMarginedImage(int _margin) {
+		Int2D i2d = new Int2D(cc.getShape().getWidth() + 2 * _margin, cc.getShape().getHeight() + 2
+				* _margin);
+		i2d.fill(backgroundColor);
+		byte[][] data = cc.getShape().getData(); 
+		for (int j = 0; j < cc.getShape().getHeight(); j++) {
+			for (int i = 0; i < cc.getShape().getWidth(); i++) {
+				if (data[j][i] != 0) {
+					i2d.data[j + _margin][i + _margin] = foregroundColor;
+				}
+			}
+		}
+		return (i2d);
+	}
+
+	public Topology getTopology() {
+		return topology;
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/character/CharacterUnderlinedSM.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/character/CharacterUnderlinedSM.java
new file mode 100644
index 0000000..d6cbe7c
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/character/CharacterUnderlinedSM.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.character;
+
+import org.eclipse.actf.visualization.engines.lowvision.image.ConnectedComponent;
+import org.eclipse.actf.visualization.engines.lowvision.image.PageComponent;
+import org.eclipse.actf.visualization.engines.lowvision.image.PageImage;
+
+/*
+ * Character (single fg color/multi bg color with underline)
+ */
+class CharacterUnderlinedSM extends PageComponent {
+	int foregroundColor;
+
+	int[][] image;
+
+	public CharacterUnderlinedSM(PageImage _pi, ConnectedComponent _cc,
+			int _color) {
+		super(CANDIDATE_UNDERLINED_CHARACTER_TYPE, _pi);
+		cc = _cc;
+		foregroundColor = _color;
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/checker/CharacterChecker.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/checker/CharacterChecker.java
new file mode 100644
index 0000000..aa16e27
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/checker/CharacterChecker.java
@@ -0,0 +1,626 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * 	  Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision.checker;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Stack;
+import java.util.Vector;
+
+import org.eclipse.actf.visualization.engines.lowvision.LowVisionCommon;
+import org.eclipse.actf.visualization.engines.lowvision.LowVisionType;
+import org.eclipse.actf.visualization.engines.lowvision.character.CharacterMS;
+import org.eclipse.actf.visualization.engines.lowvision.character.CharacterSM;
+import org.eclipse.actf.visualization.engines.lowvision.character.CharacterSS;
+import org.eclipse.actf.visualization.engines.lowvision.color.ColorIRGB;
+import org.eclipse.actf.visualization.engines.lowvision.image.BinaryImage;
+import org.eclipse.actf.visualization.engines.lowvision.image.ConnectedComponent;
+import org.eclipse.actf.visualization.engines.lowvision.image.Container;
+import org.eclipse.actf.visualization.engines.lowvision.image.ImageException;
+import org.eclipse.actf.visualization.engines.lowvision.image.Int2D;
+import org.eclipse.actf.visualization.engines.lowvision.image.PageImage;
+import org.eclipse.actf.visualization.engines.lowvision.image.Topology;
+import org.eclipse.actf.visualization.engines.lowvision.operator.LowVisionFilter;
+import org.eclipse.actf.visualization.engines.lowvision.problem.BlurProblem;
+import org.eclipse.actf.visualization.engines.lowvision.problem.ColorProblem;
+import org.eclipse.actf.visualization.engines.lowvision.problem.LowVisionProblem;
+import org.eclipse.actf.visualization.engines.lowvision.problem.LowVisionProblemException;
+import org.eclipse.actf.visualization.engines.lowvision.problem.LowVisionProblemGroup;
+import org.eclipse.actf.visualization.engines.lowvision.util.DecisionMaker;
+
+public class CharacterChecker implements LowVisionCommon {
+
+	// separated from PageImage
+
+	private PageImage pageImage;
+
+	public CharacterChecker(PageImage pageImage) {
+		this.pageImage = pageImage;
+	}
+
+	private class CompareByPriority implements Comparator<LowVisionProblem> {
+		public int compare(LowVisionProblem _o1, LowVisionProblem _o2) {
+			return (_o2.getPriority() - _o1.getPriority());
+		}
+	}
+
+	// handle PageImage as an image (without considering HTML char/image char)
+	public LowVisionProblemGroup[] checkAllCharacters(LowVisionType _lvType)
+			throws ImageException, LowVisionProblemException {
+
+		if (_lvType.countTypes() == 0) {
+			return (new LowVisionProblemGroup[0]);
+		}
+
+		Vector<LowVisionProblem> problemVec = new Vector<LowVisionProblem>();
+
+		// container
+		for (int k = 0; k < pageImage.getNumContainers(); k++) {
+
+			Container cont = pageImage.getContainers()[k];
+			Vector<LowVisionProblem> tmpProblemVec = new Vector<LowVisionProblem>();
+
+			// Problem -> ProblemGroup
+			for (int l = 0; l < cont.getNumSSCharacters(); l++) {
+				LowVisionProblem prob = checkOneSSCharacter(cont
+						.getSsCharacters()[l], _lvType);
+				if (prob != null) {
+					tmpProblemVec.addElement(prob);
+				}
+			}
+			for (int l = 0; l < cont.getNumMSCharacters(); l++) {
+				LowVisionProblem prob = checkOneMSCharacter(cont
+						.getMsCharacters()[l], _lvType);
+				if (prob != null) {
+					tmpProblemVec.addElement(prob);
+				}
+			}
+			for (int l = 0; l < cont.getNumSMCharacters(); l++) {
+				LowVisionProblem prob = checkOneSMCharacter(cont
+						.getSmCharacters()[l], _lvType);
+				if (prob != null) {
+					tmpProblemVec.addElement(prob);
+				}
+			}
+
+			Vector curProblemVec = collectProblems(tmpProblemVec);
+			if (curProblemVec == null) {
+				continue;
+			}
+			int curSize = curProblemVec.size();
+			for (int m = 0; m < curSize; m++) {
+				problemVec.addElement((LowVisionProblem) (curProblemVec
+						.elementAt(m)));
+			}
+
+			// /* generate problems for each character*/
+			// for( int l=0; l<cont.numSSCharacters; l++ ){
+			// Problem prob = checkOneSSCharacter( cont.ssCharacters[l], _lvType
+			// );
+			// if( prob != null ){
+			// problemVec.addElement( prob );
+			// }
+			// }
+			// for( int l=0; l<cont.numMSCharacters; l++ ){
+			// Problem prob = checkOneMSCharacter( cont.msCharacters[l], _lvType
+			// );
+			// if( prob != null ){
+			// problemVec.addElement( prob );
+			// }
+			// }
+			// for( int l=0; l<cont.numSMCharacters; l++ ){
+			// Problem prob = checkOneSMCharacter( cont.smCharacters[l], _lvType
+			// );
+			// if( prob != null ){
+			// problemVec.addElement( prob );
+			// }
+			// }
+		}
+
+		// SM Character (outside container)
+		Vector<LowVisionProblem> tmpProblemVec = new Vector<LowVisionProblem>();
+		for (int k = 0; k < pageImage.getNumNonContainedCharacters(); k++) {
+			LowVisionProblem prob = checkOneSMCharacter(pageImage
+					.getNonContainedCharacters()[k], _lvType);
+			if (prob != null) {
+				tmpProblemVec.addElement(prob);
+			}
+		}
+		Vector curProblemVec = collectProblems(tmpProblemVec);
+		if (curProblemVec != null) {
+			int curSize = curProblemVec.size();
+			for (int m = 0; m < curSize; m++) {
+				problemVec.addElement((LowVisionProblem) (curProblemVec
+						.elementAt(m)));
+			}
+		}
+
+		Collections.sort(problemVec, new CompareByPriority());
+		LowVisionProblemGroup[] problemArray = null;
+		int problemVecSize = problemVec.size();
+		if (problemVecSize > 0) {
+			problemArray = new LowVisionProblemGroup[problemVecSize];
+			for (int k = 0; k < problemVecSize; k++) {
+				problemArray[k] = (LowVisionProblemGroup) (problemVec
+						.elementAt(k));
+			}
+			problemVec.removeAllElements();
+			return (problemArray);
+		} else {
+			return (new LowVisionProblemGroup[0]);
+		}
+	}
+
+	// Simulate and check (MS Char)
+	private LowVisionProblem simulateAndCheckMSCharacter(CharacterMS _msc,
+			LowVisionType _lvType, int _bg) throws ImageException,
+			LowVisionProblemException {
+		/* Color change-> already simulated & checked*/		
+
+		if (!_lvType.doBlur()) {
+			return (null);
+		}
+		
+		// add margin (for Blur filter)
+		int margin = 0;
+		if (_lvType.getEyesight()) {
+			margin = _lvType.getEyesightRadius();
+		}
+		Int2D beforeI2d = _msc.makeMarginedImage(margin * 2);
+
+		// simulation
+		LowVisionFilter lvFilter = new LowVisionFilter(_lvType);
+		Int2D afterI2d = null;
+		try {
+			afterI2d = new Int2D(lvFilter.filter(beforeI2d.toBufferedImage(),
+					null));
+		} catch (Exception e) {
+			// e.printStackTrace();
+			throw new ImageException(
+					"Error occurred while simulating an MSCharacter.");
+		}
+
+		/*
+		 * Create BinaryImage from simulated image (with 1 margin)
+		 * (cut most outside margin <- blacken by BlurOp)
+		 */
+		int afterWidth = afterI2d.width - 2 * margin;
+		int afterHeight = afterI2d.height - 2 * margin;
+		BinaryImage bin = new BinaryImage(afterWidth, afterHeight);
+		HashMap<Integer, Boolean> answerMap = new HashMap<Integer, Boolean>();
+		try {
+			for (int j = 0; j < afterHeight; j++) {
+				for (int i = 0; i < afterWidth; i++) {
+					int pixel = afterI2d.data[j + margin][i + margin];
+					if (pixel == _bg) {
+						continue;
+					} else {
+						Integer pixelInt = new Integer(pixel);
+						Boolean answerBool = (Boolean) (answerMap.get(pixelInt));
+						if (answerBool == null) {
+							if (DecisionMaker.distinguishableTextColors(pixel,
+									_bg)) {
+								bin.data[j][i] = 1;
+								answerMap.put(pixelInt, new Boolean(true));
+							} else {
+								answerMap.put(pixelInt, new Boolean(false));
+							}
+						} else {
+							if (answerBool.booleanValue()) {
+								bin.data[j][i] = 1;
+							}
+						}
+					}
+				}
+			}
+		} catch (Exception e) {
+			// e.printStackTrace();
+			throw new ImageException(
+					"Error occurred while making binary image.");
+		}
+		int ccLeft = _msc.cc.getLeft() - margin;
+		if (ccLeft < 0)
+			ccLeft = 0;
+		int ccTop = _msc.cc.getTop() - margin;
+		if (ccTop < 0)
+			ccTop = 0;
+		ConnectedComponent cc = new ConnectedComponent(ccLeft, ccTop, bin,
+				ConnectedComponent.CONNECTIVITY_8);
+		Topology simTopo = cc.thinning().calcTopology();
+		if (simTopo.match(_msc.getTopology())) {
+			return (null);
+		} else {
+			double probability = 1.0;
+			if (_msc.getTopology().getCount() > 0) {
+				probability = (double) (Math.abs(_msc.getTopology().getCount()
+						- simTopo.getCount()))
+						/ (double) (_msc.getTopology().getCount());
+				if (probability > 1.0) {
+					probability = 1.0;
+				}
+			}
+			return (new BlurProblem(_msc, _lvType, probability));
+		}
+	}
+
+	// Simulate and check (SM Char)
+	private LowVisionProblem simulateAndCheckSMCharacter(CharacterSM _smc,
+			LowVisionType _lvType, int _fg) throws ImageException,
+			LowVisionProblemException {
+		/* Color change-> already simulated & checked*/				
+		
+		if (!_lvType.doBlur()) {
+			return (null);
+		}
+
+		// add margin (for Blur filter)
+		int margin = 0;
+		if (_lvType.getEyesight()) {
+			margin = _lvType.getEyesightRadius();
+		}
+		Int2D beforeI2d = _smc.makeMarginedImage(margin * 2);
+
+		// simulation
+		LowVisionFilter lvFilter = new LowVisionFilter(_lvType);
+		Int2D afterI2d = null;
+		try {
+			afterI2d = new Int2D(lvFilter.filter(beforeI2d.toBufferedImage(),
+					null));
+		} catch (Exception e) {
+			// e.printStackTrace();
+			throw new ImageException(
+					"Error occurred while simulating an SMCharacter.");
+		}
+
+		/*
+		 * Create BinaryImage from simulated image (with 1 margin)
+		 * (cut most outside margin <- blacken by BlurOp)
+		 */
+		int afterWidth = afterI2d.width - 2 * margin;
+		int afterHeight = afterI2d.height - 2 * margin;
+		BinaryImage bin = new BinaryImage(afterWidth, afterHeight);
+		HashMap<Integer, Boolean> answerMap = new HashMap<Integer, Boolean>();
+		try {
+			for (int j = 0; j < afterHeight; j++) {
+				for (int i = 0; i < afterWidth; i++) {
+					int pixel = afterI2d.data[j + margin][i + margin];
+					if (pixel == _fg) {
+						bin.data[j][i] = 1;
+						continue;
+					} else {
+						Integer pixelInt = new Integer(pixel);
+						Boolean answerBool = (Boolean) (answerMap.get(pixelInt));
+						if (answerBool == null) {
+							if (!(DecisionMaker.distinguishableTextColors(
+									pixel, _fg))) {
+								bin.data[j][i] = 1;
+								answerMap.put(pixelInt, new Boolean(false));
+							} else {
+								answerMap.put(pixelInt, new Boolean(true));
+							}
+						} else {
+							if (!(answerBool.booleanValue())) {
+								bin.data[j][i] = 1;
+							}
+						}
+					}
+				}
+			}
+		} catch (Exception e) {
+			// e.printStackTrace();
+			throw new ImageException(
+					"Error occurred while making binary image.");
+		}
+		int ccLeft = _smc.cc.getLeft() - margin;
+		if (ccLeft < 0)
+			ccLeft = 0;
+		int ccTop = _smc.cc.getTop() - margin;
+		if (ccTop < 0)
+			ccTop = 0;
+		ConnectedComponent cc = new ConnectedComponent(ccLeft, ccTop, bin,
+				ConnectedComponent.CONNECTIVITY_8);
+		Topology simTopo = cc.thinning().calcTopology();
+		if (simTopo.match(_smc.getTopology())) {
+			return (null);
+		} else {
+			double probability = 1.0;
+			if (_smc.getTopology().getCount() > 0) {
+				probability = (double) (Math.abs(_smc.getTopology().getCount()
+						- simTopo.getCount()))
+						/ (double) (_smc.getTopology().getCount());
+				if (probability > 1.0) {
+					probability = 1.0;
+				}
+			}
+			return (new BlurProblem(_smc, _lvType, probability));
+		}
+	}
+
+	// Simulate and check (SS Char)
+	private LowVisionProblem simulateAndCheckSSCharacter(CharacterSS _ssc,
+			LowVisionType _lvType, int _bg) throws ImageException,
+			LowVisionProblemException {
+
+		// add margin
+		int margin = 0;
+		if (_lvType.getEyesight()) {
+			margin = _lvType.getEyesightRadius();
+		}
+		Int2D beforeI2d = _ssc.makeMarginedImage(margin * 2);
+
+		// simulation
+		LowVisionFilter lvFilter = new LowVisionFilter(_lvType);
+		Int2D afterI2d = null;
+		try {
+			afterI2d = new Int2D(lvFilter.filter(beforeI2d.toBufferedImage(),
+					null));
+		} catch (Exception e) {
+			// e.printStackTrace();
+			throw new ImageException(
+					"Error occurred while simulating an SSCharacter.");
+		}
+
+		/*
+		 * Create BinaryImage from simulated image (with 1 margin) (cut most
+		 * outside margin <- blacken by BlurOp)
+		 */
+		int afterWidth = afterI2d.width - 2 * margin;
+		int afterHeight = afterI2d.height - 2 * margin;
+		BinaryImage bin = new BinaryImage(afterWidth, afterHeight);
+		HashMap<Integer, Boolean> answerMap = new HashMap<Integer, Boolean>();
+		try {
+			for (int j = 0; j < afterHeight; j++) {
+				for (int i = 0; i < afterWidth; i++) {
+					int pixel = afterI2d.data[j + margin][i + margin];
+					if (pixel == _bg) {
+						continue;
+					} else {
+						Integer pixelInt = new Integer(pixel);
+						Boolean answerBool = (Boolean) (answerMap.get(pixelInt));
+						if (answerBool == null) {
+							if (DecisionMaker.distinguishableTextColors(pixel,
+									_bg)) {
+								bin.data[j][i] = 1;
+								answerMap.put(pixelInt, new Boolean(true));
+							} else {
+								answerMap.put(pixelInt, new Boolean(false));
+							}
+						} else if (answerBool.booleanValue()) {
+							bin.data[j][i] = 1;
+						}
+					}
+				}
+			}
+		} catch (Exception e) {
+			// e.printStackTrace();
+			throw new ImageException(
+					"Error occurred while making binary image.");
+		}
+		int ccLeft = _ssc.cc.getLeft() - margin;
+		if (ccLeft < 0)
+			ccLeft = 0;
+		int ccTop = _ssc.cc.getTop() - margin;
+		if (ccTop < 0)
+			ccTop = 0;
+		ConnectedComponent cc = new ConnectedComponent(ccLeft, ccTop, bin,
+				ConnectedComponent.CONNECTIVITY_8);
+		Topology simTopo = cc.thinning().calcTopology();
+		if (simTopo.match(_ssc.getTopology())) {
+			return (null);
+		} else {
+			double probability = 1.0;
+			if (_ssc.getTopology().getCount() > 0) {
+				probability = (double) (Math.abs(_ssc.getTopology().getCount()
+						- simTopo.getCount()))
+						/ (double) (_ssc.getTopology().getCount());
+				if (probability > 1.0) {
+					probability = 1.0;
+				}
+			}
+			return (new BlurProblem(_ssc, _lvType, probability));
+		}
+	}
+
+	private LowVisionProblem checkOneMSCharacter(CharacterMS _msc,
+			LowVisionType _lvType) throws ImageException,
+			LowVisionProblemException {
+		int simBgColor = _msc.getBackgroundColor();
+		// Int2D i2d = _msc.getInt2D();
+
+		if (_lvType.doChangeColors()) {
+			try {
+				simBgColor = _lvType.convertColor(_msc.getBackgroundColor());
+				int simFgColor = _lvType
+						.convertColor(_msc.getForegroundColor());
+
+				double sev = W3CColorChecker.calcSeverity(new ColorIRGB(
+						simFgColor), new ColorIRGB(simBgColor));
+				if (sev > 0.0) {
+					return (new ColorProblem(_msc, _lvType, sev));
+				}
+			} catch (Exception e) {
+				// e.printStackTrace();
+			}
+		}
+
+		if (_lvType.doBlur()) {
+			return (simulateAndCheckMSCharacter(_msc, _lvType, simBgColor));
+		}
+		return (null);
+	}
+
+	private LowVisionProblem checkOneSMCharacter(CharacterSM _smc,
+			LowVisionType _lvType) throws ImageException,
+			LowVisionProblemException {
+		int simFgColor = _smc.getForegroundColor();
+		// Int2D i2d = _smc.getInt2D();
+
+		if (_lvType.doChangeColors()) {
+			try {
+				simFgColor = _lvType.convertColor(_smc.getForegroundColor());
+
+				// count bad bg pixels
+				int badCount = 0;
+				int w = _smc.getWidth();
+				int h = _smc.getHeight();
+				int[][] im = _smc.getImage();
+				byte[][] data = _smc.cc.getShape().getData();
+				HashMap<Integer, Boolean> map = new HashMap<Integer, Boolean>();
+				for (int j = 0; j < h; j++) {
+					for (int i = 0; i < w; i++) {
+						if (data[j][i] == 0) {
+							int simBg = _lvType.convertColor(im[j][i]);
+							Integer bgInt = new Integer(simBg);
+							Boolean bgBool = (Boolean) (map.get(bgInt));
+							if (bgBool == null) { // first time
+								if (!(DecisionMaker.distinguishableTextColors(
+										simFgColor, simBg))) {
+									badCount++;
+									map.put(bgInt, new Boolean(false));
+								} else {
+									map.put(bgInt, new Boolean(true));
+								}
+							} else {
+								if (!(bgBool.booleanValue())) {
+									badCount++;
+								}
+							}
+						}
+					}
+				}
+
+				double badRatio = (double) badCount
+						/ (double) (w * h - _smc.cc.getCount());
+				if (badRatio >= THRESHOLD_MIN_SM_COLOR_PROBLEM_RATIO) {
+					double probability = (badRatio - THRESHOLD_MIN_SM_COLOR_PROBLEM_RATIO)
+							/ (1.0 - THRESHOLD_MIN_SM_COLOR_PROBLEM_RATIO);
+					return (new ColorProblem(_smc, _lvType, probability));
+				}
+			} catch (Exception e) {
+				// e.printStackTrace();
+			}
+		}
+
+		if (_lvType.doBlur()) {
+			return (simulateAndCheckSMCharacter(_smc, _lvType, simFgColor));
+		}
+		return (null);
+	}
+
+	private LowVisionProblem checkOneSSCharacter(CharacterSS _ssc,
+			LowVisionType _lvType) throws ImageException,
+			LowVisionProblemException {
+		int simBgColor = _ssc.getBackgroundColor();
+
+		if (_lvType.doChangeColors()) {
+			try {
+				int simFgColor = _lvType
+						.convertColor(_ssc.getForegroundColor());
+				simBgColor = _lvType.convertColor(_ssc.getBackgroundColor());
+
+				double sev = W3CColorChecker.calcSeverity(new ColorIRGB(
+						simFgColor), new ColorIRGB(simBgColor));
+				if (sev > 0.0) {
+					return (new ColorProblem(_ssc, _lvType, sev));
+				}
+			} catch (Exception e) {
+				// e.printStackTrace();
+				throw new ImageException(
+						"An error occurred while checking colors of an SSCharacter.");
+			}
+		}
+
+		if (_lvType.doBlur()) {
+			return (simulateAndCheckSSCharacter(_ssc, _lvType, simBgColor));
+		}
+		return (null);
+	}
+
+	/* problem grouping */
+	private Vector collectProblems(Vector<LowVisionProblem> _tmpVec)
+			throws ImageException {
+		int size = _tmpVec.size();
+		if (size == 0) {
+			return (null);
+		}
+		int[] idMap = new int[size];
+		int id = 1;
+		for (int i = 0; i < size; i++) {
+			LowVisionProblem curProb = _tmpVec.elementAt(i);
+			if (idMap[i] == 0) { // not yet
+				idMap[i] = id;
+				assignProblemGroupID(curProb, id, _tmpVec, size, idMap);
+				id++;
+			}
+		}
+
+		Vector<LowVisionProblemGroup> resultVec = new Vector<LowVisionProblemGroup>();
+		for (int i = 1; i < id; i++) {
+			makeProblemGroupByID(resultVec, i, _tmpVec, size, idMap);
+		}
+
+		return (resultVec);
+	}
+
+	private void assignProblemGroupID(LowVisionProblem _curProb, int _id,
+			Vector<LowVisionProblem> _tmpVec, int _size, int[] _idMap)
+			throws ImageException {
+		try {
+			Stack<LowVisionProblem> searchStack = new Stack<LowVisionProblem>();
+			searchStack.push(_curProb);
+			while (!searchStack.empty()) {
+				LowVisionProblem sProb = searchStack.pop();
+				for (int i = 0; i < _size; i++) {
+					if (_idMap[i] == 0) {
+						LowVisionProblem tmpProb = _tmpVec.elementAt(i);
+						if (DecisionMaker.areSameGroupProblems(sProb, tmpProb)) {
+							_idMap[i] = _id;
+							searchStack.push(tmpProb);
+						}
+					}
+				}
+			}
+		} catch (LowVisionProblemException lvpe) {
+			// lvpe.printStackTrace();
+			throw new ImageException(
+					"Error occurred while making problem group.");
+		}
+	}
+
+	private void makeProblemGroupByID(Vector<LowVisionProblemGroup> _resultVec,
+			int _id, Vector<LowVisionProblem> _tmpVec, int _size, int[] _idMap)
+			throws ImageException {
+		Vector<LowVisionProblem> groupVector = new Vector<LowVisionProblem>();
+
+		for (int i = 0; i < _size; i++) {
+			if (_idMap[i] == _id) {
+				LowVisionProblem curProb = _tmpVec.elementAt(i);
+				groupVector.addElement(curProb);
+			}
+		}
+		int groupSize = groupVector.size();
+		if (groupSize <= 0) {
+			throw new ImageException("No instance belongs to the group. id = "
+					+ _id);
+		}
+		LowVisionProblemGroup pg = null;
+		try {
+			pg = new LowVisionProblemGroup(groupVector);
+		} catch (LowVisionProblemException lvpe) {
+			// lvpe.printStackTrace();
+			throw new ImageException(
+					"LowVisionProblemGroup cannot be constracted.");
+		}
+		_resultVec.addElement(pg);
+	}
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/checker/ColorChecker.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/checker/ColorChecker.java
new file mode 100644
index 0000000..63c59de
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/checker/ColorChecker.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.checker;
+
+import org.eclipse.actf.visualization.engines.lowvision.color.ColorIRGB;
+
+public abstract class ColorChecker {
+	ColorIRGB color1 = null;
+	ColorIRGB color2 = null;
+
+	public ColorChecker( ColorIRGB _c1, ColorIRGB _c2 ){
+		color1 = _c1;
+		color2 = _c2;
+	}
+	public ColorChecker( int _i1, int _i2 ){
+		color1 = new ColorIRGB( _i1 );
+		color2 = new ColorIRGB( _i2 );
+	}
+	//[0.0, 1.0]
+	public abstract double calcSeverity();
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/checker/W3CColorChecker.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/checker/W3CColorChecker.java
new file mode 100644
index 0000000..5dceb1c
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/checker/W3CColorChecker.java
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.checker;
+
+import org.eclipse.actf.visualization.engines.lowvision.color.ColorIRGB;
+
+public class W3CColorChecker extends ColorChecker {
+	private static final double THRESHOLD_Y = 125.0;
+
+	private static final int THRESHOLD_C = 500;
+
+	private double diffY;
+
+	private int diffC;
+
+	private double sevY;
+
+	private double sevC;
+
+	private double severity;
+
+	public W3CColorChecker(ColorIRGB _c1, ColorIRGB _c2) {
+		super(_c1, _c2);
+		int r1 = color1.getR();
+		int g1 = color1.getG();
+		int b1 = color1.getB();
+		int r2 = color2.getR();
+		int g2 = color2.getG();
+		int b2 = color2.getB();
+		double y1 = calcY(r1, g1, b1);
+		double y2 = calcY(r2, g2, b2);
+		diffY = Math.abs(y1 - y2);
+		diffC = Math.abs(r1 - r2) + Math.abs(g1 - g2) + Math.abs(b1 - b2);
+		sevY = calcSevY(diffY);
+		sevC = calcSevC(diffC);
+		severity = Math.min(sevY, sevC);
+	}
+
+	public W3CColorChecker(int _i1, int _i2) {
+		this(new ColorIRGB(_i1), new ColorIRGB(_i2));
+	}
+
+	public double calcSeverity() {
+		return (this.severity);
+	}
+
+	public static double calcSeverity(ColorIRGB _c1, ColorIRGB _c2) {
+		return ((new W3CColorChecker(_c1, _c2)).calcSeverity());
+	}
+
+	public double calcLuminanceSeverity() {
+		return (this.sevY);
+	}
+
+	public static double calcLuminanceSeverity(ColorIRGB _c1, ColorIRGB _c2) {
+		return ((new W3CColorChecker(_c1, _c2)).calcLuminanceSeverity());
+	}
+
+	public double calcChrominanceSeverity() {
+		return (this.sevC);
+	}
+
+	public static double calcChrominanceSeverity(ColorIRGB _c1, ColorIRGB _c2) {
+		return ((new W3CColorChecker(_c1, _c2)).calcChrominanceSeverity());
+	}
+
+	public int calcLuminanceDifference() {
+		int iDiff = (int) (Math.round(this.diffY));
+		if (iDiff < 0)
+			iDiff = 0;
+		else if (255 < iDiff)
+			iDiff = 255;
+		return (iDiff);
+	}
+
+	public static int calcLuminanceDifference(ColorIRGB _c1, ColorIRGB _c2) {
+		return ((new W3CColorChecker(_c1, _c2)).calcLuminanceDifference());
+	}
+
+	public int calcChrominanceDifference() {
+		return (this.diffC);
+	}
+
+	public static int calcChrominanceDifference(ColorIRGB _c1, ColorIRGB _c2) {
+		return ((new W3CColorChecker(_c1, _c2)).calcChrominanceDifference());
+	}
+
+	private static double calcY(int _r, int _g, int _b) {
+		return ((double) (_r * 299 + _g * 587 + _b * 114) / 1000.0);
+	}
+
+	private static double calcSevY(double _diffY) {
+		double sevY = 0.0;
+		if (_diffY < THRESHOLD_Y) {
+			sevY = -_diffY / THRESHOLD_Y + 1.0;
+		}
+		if (sevY < 0.0)
+			sevY = 0.0;
+		else if (1.0 < sevY)
+			sevY = 1.0;
+		return (sevY);
+	}
+
+	private static double calcSevC(int _diffC) {
+		double sevC = 0.0;
+		if (_diffC < THRESHOLD_C) {
+			sevC = -(double) _diffC / (double) THRESHOLD_C + 1.0;
+		}
+		if (sevC < 0.0)
+			sevC = 0.0;
+		else if (1.0 < sevC)
+			sevC = 1.0;
+		return (sevC);
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/color/ColorCSS.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/color/ColorCSS.java
new file mode 100644
index 0000000..7321b6c
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/color/ColorCSS.java
@@ -0,0 +1,122 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.color;
+
+import java.util.StringTokenizer;
+
+/*
+ * colors in CSS
+ * RGB(256)
+ * 
+ * valid syntax
+ *  #RRGGBB
+ *  #RGB
+ *  rgb(R,G,B)
+ *  rgb(R%,G%,B%)
+ *  pre-defined colors(16) (see ColorUtil.java)
+ */
+public class ColorCSS extends ColorIRGB{
+	private static final String DELIM = "/";
+
+	// default values
+	static final int TRANSPARENT_R = 0xff; // "transparent"
+	static final int TRANSPARENT_G = 0xff; // "transparent"
+	static final int TRANSPARENT_B = 0xff; // "transparent"
+	public static final int TRANSPARENT = ((TRANSPARENT_R&0xff)<<16) | ((TRANSPARENT_G&0xff)<<8) | (TRANSPARENT_B&0xff); 
+	public static final int DEFAULT_BACKGROUND_COLOR_INT = TRANSPARENT;
+	public static final int DEFAULT_COLOR_INT = 0;
+
+	String originalString = "";
+
+	public ColorCSS( String _s ) throws ColorException{
+		this( _s, true );
+	}
+
+	public ColorCSS( String _s, boolean _check ) throws ColorException{
+		if( !(_s.endsWith(DELIM)) ){
+			originalString = _s;
+		}else{
+			originalString = _s.substring( 0, _s.length()-1 );
+		}
+
+		// foreground color
+		if( originalString.indexOf(DELIM) == -1 ){			
+			ColorIRGB ci = new ColorIRGB( originalString );
+			R = ci.getR();
+			G = ci.getG();
+			B = ci.getB();
+		}
+		else{ // background-color -> need to consider ancestor
+
+			StringTokenizer st = new StringTokenizer( originalString.toLowerCase(), DELIM );
+			boolean success = false;
+			while( st.hasMoreTokens() ){
+				String tmpStr = st.nextToken();
+								
+				if( !(tmpStr.equals( "transparent" )) ){
+					// ColorIRGB ci = interpret( tmpStr );
+					ColorIRGB ci = new ColorIRGB( tmpStr );
+					R = ci.getR();
+					G = ci.getG();
+					B = ci.getB();
+					success = true;
+					break;
+				}
+			}
+			if( !success ){
+				R = TRANSPARENT_R;
+				G = TRANSPARENT_G;
+				B = TRANSPARENT_B;
+			}
+		}
+
+		if( _check ){ rangeCheck(); }
+		else{ rangeAdjust(); }
+	}
+
+	public ColorCSS() throws ColorException{
+		throw new ColorException( "Constructor in wrong format." );
+	}
+	public ColorCSS( int _i ) throws ColorException{
+		throw new ColorException( "Constructor in wrong format." );
+	}
+	public ColorCSS( int _i1, int _i2, int _i3 ) throws ColorException{
+		throw new ColorException( "Constructor in wrong format." );
+	}
+	public ColorCSS( int _i1, int _i2, int _i3, boolean _b ) throws ColorException{
+		throw new ColorException( "Constructor in wrong format." );
+	}
+
+	private void rangeCheck() throws ColorException{
+		if( R<0 || R>255){
+			throw new ColorException( "R is out of range: " + R + ", inputString = " + originalString );
+		}
+		if( G<0 || G>255){
+			throw new ColorException( "G is out of range: " + G + ", inputString = " + originalString );
+		}
+		if( B<0 || B>255){
+			throw new ColorException( "B is out of range: " + B + ", inputString = " + originalString );
+		}
+	}
+	private void rangeAdjust(){
+		if( R<0 ) R = 0;
+		else if( R>255 ) R = 255;
+		if( G<0 ) G = 0;
+		else if( G>255 ) G = 255;
+		if( B<0 ) B = 0;
+		else if( B>255 ) B = 255;
+	}
+	
+	public String getOriginalString(){
+		return( originalString );
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/color/ColorException.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/color/ColorException.java
new file mode 100644
index 0000000..9ab79a2
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/color/ColorException.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision.color;
+
+public class ColorException extends Exception{
+    public ColorException(){
+		super();
+    }
+    public ColorException( String _s ){
+		super(_s);
+    }
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/color/ColorIRGB.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/color/ColorIRGB.java
new file mode 100644
index 0000000..e1ab864
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/color/ColorIRGB.java
@@ -0,0 +1,288 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision.color;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+// sRGB [0,255]
+public class ColorIRGB {
+	int R;
+
+	int G;
+
+	int B;
+
+	public ColorIRGB() {
+	}
+
+	// convert from BufferedImage.TYPE_INT_RGB
+	public ColorIRGB(int _i) {
+		R = _i >> 16 & 0xff;
+		G = _i >> 8 & 0xff;
+		B = _i & 0xff;
+	}
+
+	public ColorIRGB(int _r, int _g, int _b) throws ColorException {
+		setR(_r);
+		setG(_g);
+		setB(_b);
+	}
+
+	public ColorIRGB(int _r, int _g, int _b, boolean _check)
+			throws ColorException {
+		setR(_r, _check);
+		setG(_g, _check);
+		setB(_b, _check);
+	}
+
+	// color definition in CSS2
+	// pre-defined 16 colors (see ColorUtil.java)
+	// #RRGGBB
+	// #RGB
+	// rgb(R,G,B)
+	// rgb(R%,G%,B%)
+	public ColorIRGB(String _str) throws ColorException {
+		Pattern patRemoveSpace = Pattern.compile("^\\s*(\\S.+\\S)\\s*$");
+		Matcher matRemoveSpace = patRemoveSpace.matcher(_str.toLowerCase());
+		if (!(matRemoveSpace.find())) {
+			throw new ColorException(
+					"There no color spacifications. Input string is \"" + _str
+							+ "\"");
+		}
+		String spec = matRemoveSpace.group(1);
+
+		String tmpS = ColorUtil.predefinedColor2Pound(spec);
+		if (tmpS != null) {
+			spec = tmpS;
+		}
+
+		if (spec.startsWith("#")) {
+			spec = spec.substring(1); // remove "#"
+			if (spec.length() == 6) {
+				String rStr = spec.substring(0, 2);
+				String gStr = spec.substring(2, 4);
+				String bStr = spec.substring(4);
+				try {
+					R = Integer.parseInt(rStr, 16);
+					G = Integer.parseInt(gStr, 16);
+					B = Integer.parseInt(bStr, 16);
+				} catch (NumberFormatException e) {
+					e.printStackTrace();
+					throw new ColorException("Bad color specification(1): #"
+							+ spec);
+				}
+			} else if (spec.length() == 3) {
+				String rStr = spec.substring(0, 1);
+				String gStr = spec.substring(1, 2);
+				String bStr = spec.substring(2);
+				try {
+					R = Integer.parseInt(rStr + rStr, 16);
+					G = Integer.parseInt(gStr + gStr, 16);
+					B = Integer.parseInt(bStr + bStr, 16);
+				} catch (NumberFormatException e) {
+					e.printStackTrace();
+					throw new ColorException("Bad color specification(2): #"
+							+ spec);
+				}
+			} else {
+				throw new ColorException("Bad color specification(3): #" + spec);
+			}
+		} else if (spec.startsWith("rgb(") && spec.endsWith(")")) {
+			spec = spec.substring(4); // remove "rgb("
+			spec = spec.substring(0, spec.length() - 1); // remove ")"
+			if (spec.indexOf("%") == -1) {
+				Pattern patRGB = Pattern
+						.compile("^\\s*([\\+\\-]?\\d+)\\s*\\,\\s*([\\+\\-]?\\d+)\\s*\\,\\s*([\\+\\-]?\\d+)\\s*$");
+				Matcher matRGB = patRGB.matcher(spec);
+				if (!(matRGB.find())) {
+					throw new ColorException("Bad color specification(4): rgb("
+							+ spec + ")");
+				}
+				try {
+					setR(Integer.parseInt(matRGB.group(1)), false);
+					setG(Integer.parseInt(matRGB.group(2)), false);
+					setB(Integer.parseInt(matRGB.group(3)), false);
+				} catch (NumberFormatException e) {
+					e.printStackTrace();
+					throw new ColorException("Bad color specification(5): rgb("
+							+ spec + ")");
+				}
+			} else { // float value
+				Pattern patRGB = Pattern
+						.compile("^\\s*([\\+\\-]?\\d+(\\.\\d+)*)\\%\\s*\\,\\s*([\\+\\-]?\\d+(\\.\\d+)*)\\%\\s*\\,\\s*([\\+\\-]?\\d+(\\.\\d+)*)\\%\\s*$");
+				Matcher matRGB = patRGB.matcher(spec);
+				if (!(matRGB.find())) {
+					throw new ColorException("Bad color specification(6): rgb("
+							+ spec + ")");
+				}
+				try {
+					setR(
+							(int) ((Float.parseFloat(matRGB.group(1))) / 100.0f * 255.0f),
+							false);
+					setG(
+							(int) ((Float.parseFloat(matRGB.group(3))) / 100.0f * 255.0f),
+							false);
+					setB(
+							(int) ((Float.parseFloat(matRGB.group(5))) / 100.0f * 255.0f),
+							false);
+				} catch (Exception e) {
+					e.printStackTrace();
+					throw new ColorException("Bad color specification(7): rgb("
+							+ spec + ")");
+				}
+			}
+		} else if (spec.equals("transparent")) {
+			R = ColorCSS.TRANSPARENT_R;
+			G = ColorCSS.TRANSPARENT_G;
+			B = ColorCSS.TRANSPARENT_B;
+		} else {
+			throw new ColorException("Unknown color specification: " + spec);
+		}
+	}
+
+	public int getR() {
+		return (R);
+	}
+
+	public int getG() {
+		return (G);
+	}
+
+	public int getB() {
+		return (B);
+	}
+
+	public void setR(int _r) throws ColorException {
+		setR(_r, false);
+	}
+
+	public void setR(int _r, boolean _check) throws ColorException {
+		if (_r < 0) {
+			if (_check)
+				throw new ColorException("Smaller than minimum.");
+			else
+				R = 0;
+		} else if (255 < _r) {
+			if (_check)
+				throw new ColorException("Larger than maximum.");
+			else
+				R = 255;
+		} else
+			R = _r;
+	}
+
+	public void setG(int _g) throws ColorException {
+		setG(_g, false);
+	}
+
+	public void setG(int _g, boolean _check) throws ColorException {
+		if (_g < 0) {
+			if (_check)
+				throw new ColorException("Smaller than minimum.");
+			else
+				G = 0;
+		} else if (255 < _g) {
+			if (_check)
+				throw new ColorException("Larger than maximum.");
+			else
+				G = 255;
+		} else
+			G = _g;
+	}
+
+	public void setB(int _b) throws ColorException {
+		setB(_b, false);
+	}
+
+	public void setB(int _b, boolean _check) throws ColorException {
+		if (_b < 0) {
+			if (_check)
+				throw new ColorException("Smaller than minimum.");
+			else
+				B = 0;
+		} else if (255 < _b) {
+			if (_check)
+				throw new ColorException("Larger than maximum.");
+			else
+				B = 255;
+		} else
+			B = _b;
+	}
+
+	public boolean equals(ColorIRGB _c) throws ColorException {
+		if (_c == null) {
+			// return( false );
+			throw new ColorException("The parameter is null.");
+		}
+		if ((_c.getR() == R) && (_c.getG() == G) && (_c.getB() == B)) {
+			return (true);
+		} else {
+			return (false);
+		}
+	}
+
+	public boolean equals(int _i) {
+		if (this.toInt() == _i) {
+			return (true);
+		} else {
+			return (false);
+		}
+	}
+
+	public ColorSRGB toSRGB() throws ColorException {
+		return (toSRGB(false));
+	}
+
+	public ColorSRGB toSRGB(boolean _check) throws ColorException {
+		ColorSRGB s = new ColorSRGB((float) R / 255.0f, (float) G / 255.0f,
+				(float) B / 255.0f, _check);
+		// s.setR( (float)R/255.0f, _check );
+		// s.setG( (float)G/255.0f, _check );
+		// s.setB( (float)B/255.0f, _check );
+		return (s);
+	}
+
+	public ColorXYZ toXYZ() throws ColorException {
+		return (toXYZ(false));
+	}
+
+	public ColorXYZ toXYZ(boolean _check) throws ColorException {
+		return (toSRGB(_check).toXYZ(_check));
+	}
+
+	public ColorYXY toYXY() throws ColorException {
+		return (toYXY(false));
+	}
+
+	public ColorYXY toYXY(boolean _check) throws ColorException {
+		return (toSRGB(_check).toXYZ(_check).toYXY(_check));
+	}
+
+	// return as BufferedImage.TYPE_INT_RGB
+	public int toInt() {
+		return ((R & 0xff) << 16 | (G & 0xff) << 8 | (B & 0xff));
+	}
+
+	public void dump(PrintStream _ps) {
+		PrintWriter pw = new PrintWriter(_ps, true);
+		dump(pw);
+	}
+
+	public void dump(PrintWriter _pw) {
+		_pw.println("-------");
+		_pw.println("dumping color values");
+		_pw.println("R= " + R + ", G= " + G + ", B= " + B);
+		_pw.println("-------");
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/color/ColorLAB.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/color/ColorLAB.java
new file mode 100644
index 0000000..7345c1d
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/color/ColorLAB.java
@@ -0,0 +1,155 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.color;
+
+/*
+ * L*a*b* color space
+ */
+public class ColorLAB {
+	private static final double THIRD = 1.0 / 3.0;
+
+	private float L;
+
+	private float a;
+
+	private float b;
+
+	// ColorXYZ [0.0, 1.0]
+	public ColorLAB(ColorXYZ _xyz) {
+		float x = _xyz.getX();
+		float y = _xyz.getY();
+		float z = _xyz.getZ();
+
+		// L*
+		if (y > 0.008856f) {
+			L = (float) (116.0 * Math.pow((double) y, THIRD) - 16.0);
+		} else {
+			L = 903.3f * y;
+		}
+
+		// a*,b*
+		double xThird = Math.pow((double) x, THIRD);
+		double yThird = Math.pow((double) y, THIRD);
+		double zThird = Math.pow((double) z, THIRD);
+		a = (float) (500.0 * (xThird - yThird));
+		b = (float) (200.0 * (yThird - zThird));
+	}
+
+	public ColorLAB(float _l, float _a, float _b) throws ColorException {
+		setL(_l);
+		setA(_a);
+		setB(_b);
+	}
+
+	public float getL() {
+		return (L);
+	}
+
+	public void setL(float _l) throws ColorException {
+		if (_l < 0.0f || 100.0f < _l) {
+			throw new ColorException("L is out of range: " + _l);
+		}
+		L = _l;
+	}
+
+	public float getA() {
+		return (a);
+	}
+
+	public void setA(float _a) {
+		a = _a;
+	}
+
+	public float getB() {
+		return (b);
+	}
+
+	public void setB(float _b) {
+		b = _b;
+	}
+
+	public ColorXYZ toXYZ() throws ColorException {
+		float y = 0.0f;
+		double y3 = 0.0;
+		if (L > 8.0f) {
+			y3 = (double) ((L + 16.0f) / 116.0f);
+			y = (float) (Math.pow(y3, 3.0));
+		} else {
+			y = L / 903.3f;
+			y3 = Math.pow((double) y, THIRD);
+		}
+		float x = (float) (Math.pow(((double) a / 500.0 + y3), 3.0));
+		float z = (float) (Math.pow((y3 - (double) b / 200.0), 3.0));
+
+		return (new ColorXYZ(x, y, z, false));
+	}
+
+	public float chroma() {
+		return ((float) (Math.sqrt(a * a + b * b)));
+	}
+
+	public double hueAngle() {
+		return (Math.atan2(b, a));
+	}
+
+	// color-difference
+	public static float deltaE(ColorLAB _c1, ColorLAB _c2) {
+		double dL = _c1.L - _c2.L;
+		double dA = _c1.a - _c2.a;
+		double dB = _c1.b - _c2.b;
+		return ((float) (Math.sqrt(dL * dL + dA * dA + dB * dB)));
+	}
+
+	//brightness difference (ABS)
+	public static float deltaL(ColorLAB _c1, ColorLAB _c2) {
+		return (Math.abs(_c1.L - _c2.L));
+	}
+
+	//hue difference
+	public static float deltaH(ColorLAB _c1, ColorLAB _c2) {
+		float dC = _c1.chroma() - _c2.chroma();
+		float dA = _c1.a - _c2.a;
+		float dB = _c1.b - _c2.b;
+
+		return ((float) (Math.sqrt(dA * dA + dB * dB - dC * dC)));
+	}
+
+	public static double deltaHueAngle(ColorLAB _c1, ColorLAB _c2) {
+		double ha1 = _c1.hueAngle();
+		double ha2 = _c2.hueAngle();
+
+		/*
+		 *  in usual case, achromatic color -> return NaN
+		 *  this method returns 0 (means not need to consider the difference)
+		 */
+		if (Double.isNaN(ha1)) {
+			// return( Double.NaN );
+			return (0.0);
+		}
+		if (Double.isNaN(ha2)) {
+			// return( Double.NaN );
+			return (0.0);
+		}
+		double diff = Math.abs(ha1 - ha2);
+		if (diff <= Math.PI) {
+			return (diff);
+		} else if (diff <= 2 * Math.PI) {
+			return (2 * Math.PI - diff);
+		} else { 
+			return (diff - 2 * Math.PI);
+		}
+	}
+
+	public static double deltaHueAngleInDegree(ColorLAB _c1, ColorLAB _c2) {
+		return (deltaHueAngle(_c1, _c2) * 180.0 / Math.PI);
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/color/ColorSRGB.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/color/ColorSRGB.java
new file mode 100644
index 0000000..ba03f68
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/color/ColorSRGB.java
@@ -0,0 +1,152 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision.color;
+
+import java.awt.color.ColorSpace;
+import java.awt.color.ICC_ColorSpace;
+
+//sRGB [0.0 , 1.0]
+public class ColorSRGB {
+	private ICC_ColorSpace cs;
+	private float[] rgb = new float[3];
+
+	public ColorSRGB( float _r, float _g, float _b ) throws ColorException{
+		cs =(ICC_ColorSpace) (ColorSpace.getInstance(ColorSpace.CS_sRGB));		
+		setR(_r);
+		setG(_g);
+		setB(_b);
+	}
+	public ColorSRGB( float _r, float _g, float _b, boolean _check ) throws ColorException{
+		cs =(ICC_ColorSpace) (ColorSpace.getInstance(ColorSpace.CS_sRGB));		
+		setR(_r,_check);
+		setG(_g,_check);
+		setB(_b,_check);
+	}
+
+	public float getR() {
+		return (rgb[0]);
+	}
+	public float getG() {
+		return (rgb[1]);
+	}
+	public float getB() {
+		return (rgb[2]);
+	}
+
+	public void setR(float _r) throws ColorException {
+		setR(_r, false);
+	}
+	public void setR(float _r, boolean _check) throws ColorException {
+		if (_r < 0.0f) {
+			if (_check)
+				throw new ColorException("Smaller than minimum.");
+			else
+				rgb[0] = 0.0f;
+		} else if (1.0f < _r) {
+			if (_check)
+				throw new ColorException("Larger than maximum.");
+			else
+				rgb[0] = 1.0f;
+		} else
+			rgb[0] = _r;
+	}
+	public void setG(float _g) throws ColorException {
+		setG(_g, false);
+	}
+	public void setG(float _g, boolean _check) throws ColorException {
+		if (_g < 0.0f) {
+			if (_check)
+				throw new ColorException("Smaller than minimum.");
+			else
+				rgb[1] = 0.0f;
+		} else if (1.0f < _g) {
+			if (_check)
+				throw new ColorException("Larger than maximum.");
+			else
+				rgb[1] = 1.0f;
+		} else
+			rgb[1] = _g;
+	}
+	public void setB(float _b) throws ColorException {
+		setB(_b, false);
+	}
+	public void setB(float _b, boolean _check) throws ColorException {
+		if (_b < 0.0f) {
+			if (_check)
+				throw new ColorException("Smaller than minimum.");
+			else
+				rgb[2] = 0.0f;
+		} else if (1.0f < _b) {
+			if (_check)
+				throw new ColorException("Larger than maximum.");
+			else
+				rgb[2] = 1.0f;
+		} else
+			rgb[2] = _b;
+	}
+
+	public ColorIRGB toIRGB() throws ColorException {
+		return (toIRGB(false));
+	}
+	public ColorIRGB toIRGB(boolean _check) throws ColorException {
+		int ir = Math.round(rgb[0] * 255.0f);
+		int ig = Math.round(rgb[1] * 255.0f);
+		int ib = Math.round(rgb[2] * 255.0f);
+
+		ColorIRGB i = new ColorIRGB();
+		i.setR(ir, _check);
+		i.setG(ig, _check);
+		i.setB(ib, _check);
+		return (i);
+	}
+
+	public ColorXYZ toXYZ() throws ColorException {
+		return (toXYZ(false));
+	}
+	public ColorXYZ toXYZ(boolean _check) throws ColorException {
+		float[] fxyz = null;
+
+		boolean success = false;
+		while( !success ){
+			try{
+				fxyz = cs.toCIEXYZ(rgb);
+				success = true;
+			}catch( Exception e ){
+				// e.printStackTrace();
+				try{
+					Thread.sleep( 20L );
+				}catch( InterruptedException ie ){
+					;
+				}
+			}
+		}
+
+		ColorXYZ xyz = new ColorXYZ();
+		xyz.setX(fxyz[0], _check);
+		xyz.setY(fxyz[1], _check);
+		xyz.setZ(fxyz[2], _check);
+		return (xyz);
+	}
+
+	public ColorYXY toYXY() throws ColorException {
+		return (toYXY(false));
+	}
+	public ColorYXY toYXY(boolean _check) throws ColorException {
+		return (toXYZ(_check).toYXY(_check));
+	}
+
+	public ColorYIQ toYIQ() throws ColorException{
+		return( new ColorYIQ(this) );
+	}
+	public ColorYIQ toYIQ(boolean _check) throws ColorException{
+		return( new ColorYIQ(this,_check));
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/color/ColorSpaceSRGB.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/color/ColorSpaceSRGB.java
new file mode 100644
index 0000000..446d8a1
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/color/ColorSpaceSRGB.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision.color;
+
+import java.awt.color.ColorSpace;
+import java.awt.color.ICC_ColorSpace;
+
+public class ColorSpaceSRGB{
+    ICC_ColorSpace CS = (ICC_ColorSpace)(ColorSpace.getInstance( ColorSpace.CS_sRGB ));
+    float[] fromCIEXYZ( float[] _xyz ){
+		return( CS.fromCIEXYZ( _xyz ) );
+    }
+    float[] toCIEXYZ( float[] _rgb ){
+		return( CS.toCIEXYZ( _rgb ) );
+    }
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/color/ColorUtil.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/color/ColorUtil.java
new file mode 100644
index 0000000..689663a
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/color/ColorUtil.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.color;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+public class ColorUtil {
+	// pre-defined 16 colors (HTML4.0, XHTML1.0, CSS2)
+	private static final String predefinedColors[] = {
+		"black", "#000000", "silver", "#c0c0c0",
+		"gray", "#808080", "grey", "#808080", "white", "#ffffff",
+		"maroon", "#800000", "red", "#ff0000",
+		"purple", "#800080", "fuchsia", "#ff00ff",
+		"green", "#008000", "lime", "#00ff00",
+		"olive", "#808000", "yellow", "#ffff00",
+		"navy", "#000080", "blue", "#0000ff",
+		"teal", "#008080", "aqua", "#00ffff"
+	};
+	private static final int numPredefinedColors = predefinedColors.length/2;
+
+	public static boolean isPredefinedColor( String _s ){
+		String s = _s.toLowerCase();
+		for( int i=0; i<numPredefinedColors; i++ ){
+			if( predefinedColors[i*2].equals(s) ){
+				return( true );
+			}
+		}
+		return( false );
+	}
+
+	public static String predefinedColor2Pound( String _s ){
+		String s = _s.toLowerCase();
+		for( int i=0; i<numPredefinedColors; i++ ){
+			if( predefinedColors[i*2].equals(s) ){
+				return( predefinedColors[i*2+1] );
+			}
+		}
+		return( null );
+	}
+
+	// TYPE_INT_RGB <--> R,G,B
+	public static int[] intToRGB( int _i ){
+		int[] rgb = new int[3];
+		rgb[0] = (_i>>16) & 0xff;
+		rgb[1] = (_i>>8) & 0xff;
+		rgb[2] = _i & 0xff;
+		return( rgb );
+	}
+	public static int RGBToInt( int _r, int _g, int _b ){
+		return( (_r&0xff)<<16 | (_g&0xff)<<8 | (_b&0xff) );
+	}
+	
+	public static void dumpColor( PrintStream _ps, int _i ){
+		(new ColorIRGB(_i)).dump(_ps);
+	}
+
+	public static void dumpColor( PrintWriter _pw, int _i ){
+		(new ColorIRGB(_i)).dump(_pw);
+	}
+	
+	/*
+	 * assign distinguishable colors for sequential IDs
+	 * 
+	 */
+	public static int distinguishableColor( int _id ){
+		int r = 0;
+		int g = 0;
+		int b = 0;
+		if( _id == 0 ){
+			return( 0x00ffffff );
+		}
+		else{
+			for( int l=0; l<8; l++ ){
+				r += ((_id>>(l*3))&1)<<(7-l);
+				g += ((_id>>(l*3+1))&1)<<(7-l);
+				b += ((_id>>(l*3+2))&1)<<(7-l);
+			}
+			return( (r<<16) | (g<<8) | b );
+		}
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/color/ColorXYZ.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/color/ColorXYZ.java
new file mode 100644
index 0000000..9dc256f
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/color/ColorXYZ.java
@@ -0,0 +1,157 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision.color;
+
+import java.awt.color.ColorSpace;
+import java.awt.color.ICC_ColorSpace;
+
+/*
+ * XYZ [0.0, 1.0] (div by 100.0 to convert from CIE)
+ * 
+ */
+public class ColorXYZ {
+	ICC_ColorSpace cs = (ICC_ColorSpace) (ColorSpace
+			.getInstance(ColorSpace.CS_sRGB));
+
+	private float[] xyz = new float[3];
+
+	public ColorXYZ() {
+	}
+
+	public ColorXYZ(float[] _xyz) throws ColorException {
+		this(_xyz, false);
+	}
+
+	public ColorXYZ(float[] _xyz, boolean _check) throws ColorException {
+		this(_xyz[0], _xyz[1], _xyz[2], _check);
+	}
+
+	public ColorXYZ(float _x, float _y, float _z) throws ColorException {
+		this(_x, _y, _z, false);
+	}
+
+	public ColorXYZ(float _x, float _y, float _z, boolean _check)
+			throws ColorException {
+		setX(_x, _check);
+		setY(_y, _check);
+		setZ(_z, _check);
+	}
+
+	public float getX() {
+		return (xyz[0]);
+	}
+
+	public float getY() {
+		return (xyz[1]);
+	}
+
+	public float getZ() {
+		return (xyz[2]);
+	}
+
+	public void setX(float _x) throws ColorException {
+		setX(_x, false);
+	}
+
+	public void setX(float _x, boolean _check) throws ColorException {
+		if (_x < 0.0f) {
+			if (_check)
+				throw new ColorException("Smaller than minimum.");
+			else
+				xyz[0] = 0.0f;
+		} else if (1.0f < _x) {
+			if (_check)
+				throw new ColorException("Larger than maximum.");
+			else
+				xyz[0] = 1.0f;
+		} else
+			xyz[0] = _x;
+	}
+
+	public void setY(float _y) throws ColorException {
+		setY(_y, false);
+	}
+
+	public void setY(float _y, boolean _check) throws ColorException {
+		if (_y < 0.0f) {
+			if (_check)
+				throw new ColorException("Smaller than minimum.");
+			else
+				xyz[1] = 0.0f;
+		} else if (1.0f < _y) {
+			if (_check)
+				throw new ColorException("Larger than maximum.");
+			else
+				xyz[1] = 1.0f;
+		} else
+			xyz[1] = _y;
+	}
+
+	public void setZ(float _z) throws ColorException {
+		setZ(_z, false);
+	}
+
+	public void setZ(float _z, boolean _check) throws ColorException {
+		if (_z < 0.0f) {
+			if (_check)
+				throw new ColorException("Smaller than minimum.");
+			else
+				xyz[2] = 0.0f;
+		} else if (1.0f < _z) {
+			if (_check)
+				throw new ColorException("Larger than maximum.");
+			else
+				xyz[2] = 1.0f;
+		} else
+			xyz[2] = _z;
+	}
+
+	public ColorSRGB toSRGB() throws ColorException {
+		return (toSRGB(false));
+	}
+
+	public ColorSRGB toSRGB(boolean _check) throws ColorException {
+		float[] frgb = cs.fromCIEXYZ(xyz);
+		ColorSRGB s = new ColorSRGB(frgb[0], frgb[1], frgb[2], _check);
+		return (s);
+	}
+
+	public ColorYXY toYXY() throws ColorException {
+		return (toYXY(false));
+	}
+
+	public ColorYXY toYXY(boolean _check) throws ColorException {
+		float sum = xyz[0] + xyz[1] + xyz[2];
+		ColorYXY yxy = new ColorYXY();
+		if (sum == 0.0f) {
+			yxy.setYY(0.0f);
+			yxy.setX(0.0f);
+			yxy.setY(0.0f);
+		} else {
+			yxy.setYY(xyz[1], _check);
+			yxy.setX(xyz[0] / sum, _check);
+			yxy.setY(xyz[1] / sum, _check);
+		}
+		return (yxy);
+	}
+
+	public ColorIRGB toIRGB() throws ColorException {
+		return (toIRGB(false));
+	}
+
+	public ColorIRGB toIRGB(boolean _check) throws ColorException {
+		return (toSRGB(_check).toIRGB(_check));
+	}
+
+	public ColorLAB toLAB() {
+		return (new ColorLAB(this));
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/color/ColorYIQ.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/color/ColorYIQ.java
new file mode 100644
index 0000000..9d97085
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/color/ColorYIQ.java
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.color;
+
+/*
+ * NTSC YIQ [0.0, 1.0] (float)
+ */
+public class ColorYIQ {
+	private float Y;
+
+	private float I;
+
+	private float Q;
+
+	public ColorYIQ(ColorSRGB _srgb) throws ColorException {
+		this(_srgb, false);
+	}
+
+	public ColorYIQ(ColorSRGB _srgb, boolean _check) throws ColorException {
+		float r = _srgb.getR();
+		float g = _srgb.getG();
+		float b = _srgb.getB();
+		Y = 0.299f * r + 0.587f * g + 0.114f * b;
+		I = 0.596f * r - 0.274f * g - 0.322f * b;
+		Q = 0.211f * r - 0.522f * g + 0.311f * b;
+
+		if (_check) {
+			rangeCheck();
+		} else {
+			rangeAdjust();
+		}
+	}
+
+	private void rangeCheck() throws ColorException {
+		if (Y < 0.0f || 1.0f < Y) {
+			throw new ColorException("Y is out of range: " + Y);
+		}
+		if (I < 0.0f || 1.0f < I) {
+			throw new ColorException("I is out of range: " + I);
+		}
+		if (Q < 0.0f || 1.0f < Q) {
+			throw new ColorException("Q is out of range: " + Q);
+		}
+	}
+
+	private void rangeAdjust() {
+		if (Y < 0.0f)
+			Y = 0.0f;
+		else if (Y > 1.0f)
+			Y = 1.0f;
+		if (I < 0.0f)
+			I = 0.0f;
+		else if (I > 1.0f)
+			I = 1.0f;
+		if (Q < 0.0f)
+			Q = 0.0f;
+		else if (Q > 1.0f)
+			Q = 1.0f;
+	}
+
+	public float getY() {
+		return (Y);
+	}
+
+	public float getI() {
+		return (I);
+	}
+
+	public float getQ() {
+		return (Q);
+	}
+
+	public void setY(float _y) {
+		Y = _y;
+	}
+
+	public void seti(float _i) {
+		I = _i;
+	}
+
+	public void setQ(float _q) {
+		Q = _q;
+	}
+
+	public ColorSRGB toSRGB() throws ColorException {
+		float r = 1.0f * Y + 0.955653f * I + 0.622895f * Q;
+		float g = 1.0f * Y - 0.27215f * I - 0.64834f * Q;
+		float b = 1.0f * Y - 1.10516f * I + 1.704625f * Q;
+		return (new ColorSRGB(r, g, b, false));
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/color/ColorYXY.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/color/ColorYXY.java
new file mode 100644
index 0000000..d5200df
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/color/ColorYXY.java
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision.color;
+
+/*
+ * Yxy x,y [0.0, 1.0] Y (yy) [0.0, 1.0] (in usual [0, 100])
+ */
+public class ColorYXY {
+	private float YY;
+
+	private float x;
+
+	private float y;
+
+	public ColorYXY() {
+	}
+
+	public ColorYXY(float _yy, float _x, float _y) throws ColorException {
+		this(_yy, _x, _y, false);
+	}
+
+	public ColorYXY(float _yy, float _x, float _y, boolean _check)
+			throws ColorException {
+		setYY(_yy, _check);
+		setX(_x, _check);
+		setY(_y, _check);
+	}
+
+	public float getYY() {
+		return (YY);
+	}
+
+	public float getX() {
+		return (x);
+	}
+
+	public float getY() {
+		return (y);
+	}
+
+	public void setYY(float _yy) throws ColorException {
+		setYY(_yy, false);
+	}
+
+	public void setYY(float _yy, boolean _check) throws ColorException {
+		if (_yy < 0.0f) {
+			if (_check)
+				throw new ColorException("Smaller than minimum.");
+			else
+				YY = 0.0f;
+		} else if (1.0f < _yy) {
+			if (_check)
+				throw new ColorException("Larger than maximum.");
+			else
+				YY = 1.0f;
+		} else
+			YY = _yy;
+	}
+
+	public void setX(float _x) throws ColorException {
+		setX(_x, false);
+	}
+
+	public void setX(float _x, boolean _check) throws ColorException {
+		if (_x < 0.0f) {
+			if (_check)
+				throw new ColorException("Smaller than minimum.");
+			else
+				x = 0.0f;
+		} else if (1.0f < _x) {
+			if (_check)
+				throw new ColorException("Larger than maximum.");
+			else
+				x = 1.0f;
+		} else
+			x = _x;
+	}
+
+	public void setY(float _y) throws ColorException {
+		setY(_y, false);
+	}
+
+	public void setY(float _y, boolean _check) throws ColorException {
+		if (_y < 0.0f) {
+			if (_check)
+				throw new ColorException("Smaller than minimum.");
+			else
+				y = 0.0f;
+		} else if (1.0f < _y) {
+			if (_check)
+				throw new ColorException("Larger than maximum.");
+			else
+				y = 1.0f;
+		} else
+			y = _y;
+	}
+
+	public ColorXYZ toXYZ() throws ColorException {
+		return (toXYZ(false));
+	}
+
+	public ColorXYZ toXYZ(boolean _check) throws ColorException {
+		ColorXYZ xyz = new ColorXYZ();
+		if (y == 0.0f) {
+			xyz.setX(0.0f);
+			xyz.setY(0.0f);
+			xyz.setZ(0.0f);
+		} else {
+			xyz.setX(YY / y * x, _check);
+			xyz.setY(YY, _check);
+			xyz.setZ(YY / y * (1 - x - y), _check);
+		}
+		return (xyz);
+	}
+
+	public ColorSRGB toSRGB() throws ColorException {
+		return (toSRGB(false));
+	}
+
+	public ColorSRGB toSRGB(boolean _check) throws ColorException {
+		return (toXYZ(_check).toSRGB(_check));
+	}
+
+	public ColorIRGB toIRGB() throws ColorException {
+		return (toIRGB(false));
+	}
+
+	public ColorIRGB toIRGB(boolean _check) throws ColorException {
+		return (toXYZ(_check).toSRGB(_check).toIRGB(_check));
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/BinaryImage.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/BinaryImage.java
new file mode 100644
index 0000000..e6f9bba
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/BinaryImage.java
@@ -0,0 +1,553 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision.image;
+
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBufferInt;
+import java.awt.image.WritableRaster;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.util.Vector;
+
+/*
+ * Binary Image data[y][x] ([0][0] to [height-1][width-1])
+ */
+public class BinaryImage {
+
+	public static final short METHOD_SPECIFY_FOREGROUND = 0; // fgcolor
+
+	public static final short METHOD_SPECIFY_BACKGROUND = 1; // bgcolor
+
+	public static final int NOT_MEASURED = -1;
+	
+	int width;
+
+	int height;
+
+	public byte[][] data;
+
+	private int area = NOT_MEASURED;
+
+	public BinaryImage(int _w, int _h) {
+		width = _w;
+		height = _h;
+		data = new byte[height][width];
+	}
+
+	public BinaryImage(int _width, int _height, int[][] _data, short _method,
+			int _i) throws ImageException {
+		this((new Int2D(_width, _height, _data)), _method, _i);
+	}
+
+	public BinaryImage(Int2D _i2d, short _method, int _i) {
+		width = _i2d.width;
+		height = _i2d.height;
+		data = new byte[height][width];
+
+		if (_method == METHOD_SPECIFY_FOREGROUND) {
+			setDataSpecifyForeground(_i2d, _i);
+		}
+		if (_method == METHOD_SPECIFY_BACKGROUND) {
+			setDataSpecifyBackground(_i2d, _i);
+		}
+	}
+
+	private void setDataSpecifyForeground(Int2D _i2d, int _foreground) {
+		area = 0;
+		for (int j = 0; j < height; j++) {
+			for (int i = 0; i < width; i++) {
+				if (_i2d.data[j][i] == _foreground) {
+					data[j][i] = 1;
+					area++;
+				} else
+					data[j][i] = 0;
+			}
+		}
+	}
+
+	private void setDataSpecifyBackground(Int2D _i2d, int _background) {
+		area = 0;
+		for (int j = 0; j < height; j++) {
+			for (int i = 0; i < width; i++) {
+				if (_i2d.data[j][i] == _background)
+					data[j][i] = 0;
+				else {
+					data[j][i] = 1;
+					area++;
+				}
+			}
+		}
+	}
+
+	public BinaryImage(BufferedImage _bi, short _method, int _i) {
+		width = _bi.getWidth();
+		height = _bi.getHeight();
+		data = new byte[height][width];
+
+		if (_method == METHOD_SPECIFY_FOREGROUND) {
+			setDataSpecifyForeground(_bi, _i);
+		}
+		if (_method == METHOD_SPECIFY_BACKGROUND) {
+			setDataSpecifyBackground(_bi, _i);
+		}
+	}
+
+	private void setDataSpecifyForeground(BufferedImage _bi, int _foreground) {
+		WritableRaster srcRaster = _bi.copyData(null);
+		DataBufferInt srcBufInt = (DataBufferInt) (srcRaster.getDataBuffer());
+		int[] srcArray = srcBufInt.getData();
+
+		area = 0;
+		int k = 0;
+		for (int j = 0; j < height; j++) {
+			for (int i = 0; i < width; i++) {
+				if (srcArray[k] == _foreground) {
+					data[j][i] = 1;
+					area++;
+				} else
+					data[j][i] = 0;
+				k++;
+			}
+		}
+	}
+
+	private void setDataSpecifyBackground(BufferedImage _bi, int _background) {
+		WritableRaster srcRaster = _bi.copyData(null);
+		DataBufferInt srcBufInt = (DataBufferInt) (srcRaster.getDataBuffer());
+		int[] srcArray = srcBufInt.getData();
+
+		area = 0;
+		int k = 0;
+		for (int j = 0; j < height; j++) {
+			for (int i = 0; i < width; i++) {
+				if (srcArray[k] == _background)
+					data[j][i] = 0;
+				else {
+					data[j][i] = 1;
+					area++;
+				}
+				k++;
+			}
+		}
+	}
+
+	/*
+	 * create (daub) image by using vertex set -vertex set must be ordered in
+	 * clockwise -assume convex shape (to obtain convex closure)
+	 */
+	public BinaryImage(int _w, int _h, Coord[] _vertex) {
+		this(_w, _h);
+
+		Coord[] vertex = null;
+		int numVertex = _vertex.length;
+		if (_vertex[0].equals(_vertex[numVertex - 1])) {
+			vertex = _vertex;
+		} else {
+			vertex = new Coord[numVertex + 1];
+			for (int i = 0; i < numVertex; i++) {
+				vertex[i] = _vertex[i];
+			}
+			vertex[numVertex] = _vertex[0];
+			numVertex++;
+		}
+
+		Coord curPoint = new Coord(-1, -1);
+		for (int j = 0; j < height; j++) {
+			for (int i = 0; i < width; i++) {
+				data[j][i] = 1;
+				curPoint.set(i, j);
+				for (int k = 0; k < numVertex - 1; k++) {
+					if (Coord
+							.isLeftToVector(vertex[k], vertex[k + 1], curPoint)) {
+						data[j][i] = 0;
+						break;
+					}
+				}
+			}
+		}
+		measureArea();
+	}
+
+	public BinaryImage deepCopy() {
+		BinaryImage bi = new BinaryImage(width, height);
+		for (int j = 0; j < height; j++) {
+			for (int i = 0; i < width; i++) {
+				bi.data[j][i] = this.data[j][i];
+			}
+		}
+		bi.area = this.area;
+		return (bi);
+	}
+
+	/*
+	 * copy into new BinaryImage (0,0)-> (_offsetX,_offsetY)
+	 * 
+	 * protrusion -strict -> error -not strict -> clip
+	 */
+	public BinaryImage offsetCopy(int _newWidth, int _newHeight, int _offsetX,
+			int _offsetY, boolean _strict) throws ImageException {
+		BinaryImage bi = new BinaryImage(_newWidth, _newHeight);
+		if (_offsetX < 0 || _newWidth <= _offsetX) {
+			throw new ImageException("Bad offset value.");
+		}
+		if (_offsetY < 0 || _newHeight <= _offsetY) {
+			throw new ImageException("Bad offset value.");
+		}
+		int endI = width;
+		int endJ = height;
+		int overWidth = _offsetX + width - _newWidth;
+		int overHeight = _offsetY + height - _newHeight;
+		if (overWidth > 0) {
+			if (_strict) {
+				throw new ImageException("Not enough image area.");
+			} else {
+				endI -= overWidth;
+			}
+		}
+		if (overHeight > 0) {
+			if (_strict) {
+				throw new ImageException("Not enough image area.");
+			} else {
+				endJ -= overHeight;
+			}
+		}
+		for (int j = 0; j < endJ; j++) {
+			for (int i = 0; i < endI; i++) {
+				bi.data[j + _offsetY][i + _offsetX] = this.data[j][i];
+			}
+		}
+
+		return (bi);
+	}
+
+	public BinaryImage offsetCopy(int _newWidth, int _newHeight, int _offsetX,
+			int _offsetY) throws ImageException {
+		return (offsetCopy(_newWidth, _newHeight, _offsetX, _offsetY, true));
+	}
+
+	public int getWidth() {
+		return (width);
+	}
+
+	public int getHeight() {
+		return (height);
+	}
+
+	public byte[][] getData() {
+		return (data);
+	}
+
+	public int getArea() {
+		if (area == NOT_MEASURED) {
+			measureArea();
+		}
+		return (area);
+	}
+
+	// calc area
+	public int measureArea() {
+		area = 0;
+		for (int j = 0; j < height; j++) {
+			for (int i = 0; i < width; i++) {
+				if (data[j][i] != 0)
+					area++;
+			}
+		}
+		return (area);
+	}
+
+	public boolean equals(BinaryImage _bi) {
+		if (this.width != _bi.width) {
+			return (false);
+		}
+		if (this.height != _bi.height) {
+			return (false);
+		}
+		for (int j = 0; j < height; j++) {
+			for (int i = 0; i < width; i++) {
+				if (this.data[j][i] != _bi.data[j][i]) {
+					return (false);
+				}
+			}
+		}
+		return (true);
+	}
+
+	// fg->black, bg->white
+	public BufferedImage toBufferedImage() {
+		return (toBufferedImage(0x00000000, 0x00ffffff));
+	}
+
+	public BufferedImage toBufferedImage(int _foreground, int _background) {
+		BufferedImage destImage = new BufferedImage(width, height,
+				BufferedImage.TYPE_INT_RGB);
+		WritableRaster destRaster = destImage.copyData(null);
+		DataBufferInt destBufInt = (DataBufferInt) (destRaster.getDataBuffer());
+		int[] destArray = destBufInt.getData();
+
+		int k = 0;
+		for (int j = 0; j < height; j++) {
+			for (int i = 0; i < width; i++) {
+				if (data[j][i] == 0)
+					destArray[k] = _background;
+				else
+					destArray[k] = _foreground;
+				k++;
+			}
+		}
+
+		destImage.setData(destRaster);
+		return (destImage);
+	}
+
+	public LabeledImage labelConnectedComponents() {
+		return (new LabeledImage(this));
+	}
+
+	public LabeledImage labelConnectedComponents(short _method) {
+		return (new LabeledImage(this, _method));
+	}
+
+	// return array of fg Coord
+	public Coord[] extractPoints() {
+		Vector<Coord> tmpVec = new Vector<Coord>();
+
+		for (int j = 0; j < height; j++) {
+			for (int i = 0; i < width; i++) {
+				if (data[j][i] != 0) {
+					Coord co = new Coord(i, j);
+					tmpVec.addElement(co);
+				}
+			}
+		}
+
+		int size = tmpVec.size();
+		if (size > 0) {
+			Coord[] coArray = new Coord[size];
+			for (int i = 0; i < size; i++) {
+				coArray[i] = (Coord) (tmpVec.elementAt(i));
+			}
+			return (coArray);
+		} else {
+			return (null);
+		}
+	}
+
+	// put points as fg
+	public void putPoints(Coord[] _coArray) {
+		if (_coArray == null || _coArray.length == 0)
+			return;
+		int len = _coArray.length;
+		for (int i = 0; i < len; i++) {
+			Coord co = _coArray[i];
+			data[co.y][co.x] = 1;
+		}
+	}
+
+	// return most Top-Left fg point
+	public Coord topLeftPoint() {
+		for (int j = 0; j < height; j++)
+			for (int i = 0; i < width; i++)
+				if (data[j][i] != 0)
+					return (new Coord(i, j));
+		return (null);
+	}
+
+	public static BinaryImage subtract(BinaryImage _bi1, BinaryImage _bi2)
+			throws ImageException {
+		int width = _bi1.width;
+		int height = _bi1.height;
+		if (width != _bi2.width || height != _bi2.height) {
+			throw new ImageException(
+					"subtract(): Sizes of the two image must be the same");
+		}
+
+		BinaryImage newImage = new BinaryImage(width, height);
+		for (int j = 0; j < height; j++) {
+			for (int i = 0; i < width; i++) {
+				if (_bi1.data[j][i] != 0 && _bi2.data[j][i] == 0)
+					newImage.data[j][i] = 1;
+			}
+		}
+
+		return (newImage);
+	}
+
+	public BinaryImage subtract(BinaryImage _bi) throws ImageException {
+		return (subtract(this, _bi));
+	}
+
+	public LineSegment detectLongestHorizontalLine() {
+		return (detectLongestHorizontalLine(height - 1));
+	}
+
+	public LineSegment detectLongestHorizontalLine(int _maxHeight) {
+		int maxLength = 0;
+		Coord maxStart = new Coord(-1, -1);
+		Coord maxEnd = new Coord(-1, -1);
+		Coord curStart = new Coord(-1, -1);
+		for (int j = 0; j <= _maxHeight; j++) {
+			boolean flag = false;
+			int curLength = 0;
+			for (int i = 0; i < width; i++) {
+				if (data[j][i] != 0) {
+					if (flag) {
+						curLength++;
+					} else {
+						flag = true;
+						curLength = 1;
+						curStart.set(i, j);
+					}
+				} else {
+					if (flag) {
+						if (curLength >= maxLength) {
+							maxLength = curLength;
+							maxStart.copy(curStart);
+							maxEnd.set(i - 1, j);
+						}
+						flag = false;
+					}
+					// else{
+					// }
+				}
+			}
+			if (flag && curLength >= maxLength) {
+				maxLength = curLength;
+				maxStart.copy(curStart);
+				maxEnd.set(width - 1, j);
+			}
+		}
+
+		if (maxLength > 0) {
+			return (new LineSegment(maxStart, maxEnd));
+		} else {
+			return (null);
+		}
+	}
+
+	// extract underline from this image
+	public BinaryImage drawUnderline() throws ImageException {
+		// TODO separated by other image
+		return (drawLongestHorizontalLine());
+	}
+
+	// 1px
+	public BinaryImage drawLongestHorizontalLine() throws ImageException {
+		LineSegment horSeg = detectLongestHorizontalLine();
+		if (horSeg == null)
+			return (null);
+		if (horSeg.isVertical() || horSeg.isDiagonal())
+			throw new ImageException(
+					"Endpoints cannot be successfully detected");
+		BinaryImage bi = new BinaryImage(width, height);
+		Coord left = horSeg.getLeftPoint();
+		Coord right = horSeg.getRightPoint();
+		for (int i = left.x; i <= right.x; i++) {
+			bi.data[left.y][i] = 1;
+		}
+		return (bi);
+	}
+
+	// covers thick lines (2px and above)
+	public BinaryImage drawLongestHorizontalLineWithThick()
+			throws ImageException {
+		LineSegment horSeg = detectLongestHorizontalLine();
+		if (horSeg == null)
+			return (null);
+		if (horSeg.isVertical() || horSeg.isDiagonal())
+			throw new ImageException(
+					"Endpoints cannot be successfully detected");
+		BinaryImage bi = new BinaryImage(width, height);
+		Coord left = horSeg.getLeftPoint();
+		Coord right = horSeg.getRightPoint();
+		for (int i = left.x; i <= right.x; i++) {
+			bi.data[left.y][i] = 1;
+		}
+		int maxHeight = left.y - 1;
+		int curX0 = left.x;
+		int curX1 = right.x;
+		while (maxHeight > 0) {
+			LineSegment horSeg2 = detectLongestHorizontalLine(maxHeight);
+			if (horSeg2 == null) {
+				break;
+			}
+			if (horSeg2.isVertical() || horSeg2.isDiagonal())
+				throw new ImageException(
+						"Endpoints cannot be successfully detected");
+			Coord left2 = horSeg.getLeftPoint();
+			Coord right2 = horSeg.getRightPoint();
+			if ((left2.y == maxHeight) && (left2.x == curX0)
+					&& (right2.x == curX1)) {
+				for (int i = left2.x; i <= right2.x; i++) {
+					bi.data[maxHeight][i] = 1;
+				}
+				maxHeight--;
+			} else {
+				break;
+			}
+		}
+
+		return (bi);
+	}
+
+	public void dump() {
+		dump(System.out);
+	}
+
+	public void dump(PrintStream _ps) {
+		PrintWriter pw = new PrintWriter(_ps, true);
+		dump(pw);
+	}
+
+	public void dump(PrintWriter _pw) {
+		_pw.println("-------------------------------");
+		_pw.println("Dumping a BinaryImage");
+		_pw.println("Width = " + width + ", Height = " + height);
+		for (int j = 0; j < height; j++) {
+			StringBuffer sb = new StringBuffer();
+			for (int i = 0; i < width; i++) {
+				if (data[j][i] == 0)
+					sb.append("0");
+				else
+					sb.append("1");
+			}
+			_pw.println(sb.toString());
+		}
+		_pw.println("-------------------------------");
+	}
+
+	public void dump(PrintStream _ps, int _left, int _top, int _width,
+			int _height) {
+		PrintWriter pw = new PrintWriter(_ps, true);
+		dump(pw, _left, _top, _width, _height);
+	}
+
+	public void dump(PrintWriter _pw, int _left, int _top, int _width,
+			int _height) {
+		_pw.println("-------------------------------");
+		_pw.println("Dumping a part of a BinaryImage");
+		_pw.println("Image width = " + width + ", Image height = " + height);
+		_pw.println("Start point = ( " + _left + ", " + _top + ")");
+		_pw.println("Printed width = " + _width + ", Printed height = "
+				+ _height);
+		for (int j = 0; j < _height; j++) {
+			StringBuffer sb = new StringBuffer();
+			for (int i = 0; i < _width; i++) {
+				if (data[j + _top][i + _left] == 0)
+					sb.append("0");
+				else
+					sb.append("1");
+			}
+			_pw.println(sb.toString());
+		}
+		_pw.println("-------------------------------");
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/ColorHistogram.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/ColorHistogram.java
new file mode 100644
index 0000000..6f07184
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/ColorHistogram.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.image;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+
+public class ColorHistogram {
+	private HashMap<Integer, ColorHistogramBin> pixelMap = new HashMap<Integer, ColorHistogramBin>();
+
+	private ColorHistogramBin[] sortedArrayByOccurrence = null;
+
+	// shows histogram was changed or not after make sortedArrayByOccurrence
+	private boolean changedFlag = true;
+
+	public boolean changed() {
+		return (changedFlag);
+	}
+
+	public ColorHistogramBin[] getSortedArrayByOccurrence() {
+		return (sortedArrayByOccurrence);
+	}
+
+	public int getSize() {
+		return (pixelMap.size());
+	}
+
+	public void put(int _color) {
+		changedFlag = true;
+		Integer curPixel = new Integer(_color);
+		ColorHistogramBin curHistBin = (ColorHistogramBin) (pixelMap
+				.get(curPixel));
+		if (curHistBin != null) {
+			curHistBin.occurrence++;
+		} else {
+			curHistBin = new ColorHistogramBin(curPixel.intValue());
+			curHistBin.occurrence++;
+			pixelMap.put(curPixel, curHistBin);
+		}
+	}
+
+	public void makeSortedArrayByOccurrence() {
+		if (!changedFlag) {
+			return;
+		}
+		if (getSize() == 0) {
+			return;
+		}
+		changedFlag = false;
+		Object[] keyArray = pixelMap.keySet().toArray();
+		int len = keyArray.length;
+		sortedArrayByOccurrence = new ColorHistogramBin[len];
+
+		for (int i = 0; i < len; i++) {
+			sortedArrayByOccurrence[i] = (ColorHistogramBin) (pixelMap
+					.get(keyArray[i]));
+		}
+		Arrays.sort(sortedArrayByOccurrence, new ComparatorByOccurrence());
+	}
+
+	public class ComparatorByOccurrence implements Comparator<ColorHistogramBin> {
+		public int compare(ColorHistogramBin o1, ColorHistogramBin o2) {
+			return(o2.occurrence-o1.occurrence);
+		}
+	}
+
+
+	public static ColorHistogram makeColorHistogram(int[][] _pixel, int _width,
+			int _height) {
+		ColorHistogram histo = new ColorHistogram();
+		for (int j = 0; j < _height; j++) {
+			for (int i = 0; i < _width; i++) {
+				histo.put(_pixel[j][i]);
+			}
+		}
+		histo.makeSortedArrayByOccurrence();
+		return (histo);
+	}
+
+	public static ColorHistogram makeColorHistogram(Int2D _i2d) {
+		return (makeColorHistogram(_i2d.data, _i2d.width, _i2d.height));
+	}
+
+	public void dump(PrintStream _ps) {
+		PrintWriter pw = new PrintWriter(_ps, true);
+		dump(pw);
+	}
+
+	public void dump(PrintWriter _pw) {
+		if (changedFlag)
+			makeSortedArrayByOccurrence();
+		int len = sortedArrayByOccurrence.length;
+		for (int i = 0; i < len; i++) {
+			ColorHistogramBin cur = sortedArrayByOccurrence[i];
+			int curOccur = cur.occurrence;
+			int r = cur.getR();
+			int g = cur.getG();
+			int b = cur.getB();
+			_pw.println(i + ": rgb = ( " + r + ", " + g + ", " + b
+					+ ") occurrence = " + curOccur);
+		}
+	}
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/ColorHistogramBin.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/ColorHistogramBin.java
new file mode 100644
index 0000000..09ce6b7
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/ColorHistogramBin.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.image;
+
+public class ColorHistogramBin {
+	int color;
+	int occurrence = 0;
+
+	ColorHistogramBin( int _c ){
+		color = _c;
+	}
+
+	int getR(){
+		return( color>>16 & 0xff );
+	}
+	int getG(){
+		return( color>>8 & 0xff );
+	}
+	int getB(){
+		return( color & 0xff );
+	}
+
+	
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/ConnectedComponent.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/ConnectedComponent.java
new file mode 100644
index 0000000..f825b98
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/ConnectedComponent.java
@@ -0,0 +1,562 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision.image;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.util.Vector;
+
+/*
+ * represent single connected component
+ * 
+ * shape: rectangle of the connected component
+ * shape.data[0][0]->originalImage.data[shape.top][shape.left]
+ * 
+ * Connected component derived by using thinning has same shape size of the
+ * original component (before the thinning)
+ */
+public class ConnectedComponent {
+
+	public static final short CONNECTIVITY_UNSET = 0;
+
+	public static final short CONNECTIVITY_4 = 1;
+
+	public static final short CONNECTIVITY_8 = 2;
+
+	public static final short THINNING_HILDITCH = 10;
+
+	public static final short THINNING_DEFAULT = THINNING_HILDITCH;
+
+	int left;
+
+	int top;
+
+	BinaryImage shape;
+
+	private int count; // number of pixelin the connected component
+
+	short connectivity = CONNECTIVITY_UNSET; // 4 or 8
+
+	public ConnectedComponent(int _left, int _top, int _width, int _height,
+			int _count) {
+		left = _left;
+		top = _top;
+		count = _count;
+		shape = new BinaryImage(_width, _height);
+	}
+
+	public ConnectedComponent(int _left, int _top, BinaryImage _bi, short _conn) {
+		left = _left;
+		top = _top;
+		shape = _bi;
+		connectivity = _conn;
+		if (_bi.getArea() == BinaryImage.NOT_MEASURED)
+			_bi.measureArea();
+		count = _bi.getArea();
+	}
+
+	public ConnectedComponent deepCopy() {
+		ConnectedComponent cc = new ConnectedComponent(left, top, shape.width,
+				shape.height, count);
+		cc.shape = this.shape.deepCopy();
+		cc.connectivity = this.connectivity;
+		return (cc);
+	}
+
+	public int getLeft() {
+		return (left);
+	}
+
+	void setLeft(int _l) {
+		left = _l;
+	}
+
+	public int getTop() {
+		return (top);
+	}
+
+	void setTop(int _t) {
+		top = _t;
+	}
+
+	public int getWidth() {
+		return (shape.width );
+	}
+
+	public int getHeight() {
+		return (shape.height );
+	}
+
+	public BinaryImage getShape() {
+		return (shape);
+	}
+
+	public int getCount() {
+		return (count);
+	}
+
+	public boolean equals(ConnectedComponent _cc) {
+		if (this.left != _cc.left) {
+			return (false);
+		}
+		if (this.top != _cc.top) {
+			return (false);
+		}
+		return (this.shape.equals(_cc.shape));
+	}
+
+	public static boolean includes(ConnectedComponent _a, ConnectedComponent _b) {
+		if (_a.left > _b.left) {
+			return (false);
+		}
+		if (_a.top > _b.top) {
+			return (false);
+		}
+		if (_a.left + _a.shape.width < _b.left + _b.shape.width) {
+			return (false);
+		}
+		if (_a.top + _a.shape.height < _b.top + _b.shape.height) {
+			return (false);
+		}
+		int w = _b.shape.width;
+		int h = _b.shape.height;
+		int offsetX = _b.left - _a.left;
+		int offsetY = _b.top - _a.top;
+		for (int j = 0; j < h; j++) {
+			for (int i = 0; i < w; i++) {
+				if (_b.shape.data[j][i] != 0
+						&& _a.shape.data[j + offsetY][i + offsetX] == 0) {
+					return (false);
+				}
+			}
+		}
+		return (true);
+	}
+
+	public boolean includes(ConnectedComponent _cc) {
+		return (includes(this, _cc));
+	}
+
+	public boolean isIncludedBy(ConnectedComponent _cc) {
+		return (includes(_cc, this));
+	}
+
+	public double getDensity() {
+		return ((double) count / ((double) (shape.width) * (double) (shape.height)));
+	}
+
+	// adjust shape size (for removal of underline of link, etc.)
+	public void adjustShape() {
+		LabeledImage li = new LabeledImage(this.shape);
+		ConnectedComponent cc = li.components[0];
+		this.left += cc.left;
+		this.top += cc.top;
+		this.shape = cc.shape;
+	}
+
+	public ConnectedComponent calcContour() throws ImageException {
+		if (connectivity == CONNECTIVITY_UNSET) {
+			throw new ImageException(
+					"Information on connectivity is needed to calculate genus");
+		}
+
+		int width = shape.width;
+		int height = shape.height;
+		if (width <= 2 || height <= 2)
+			return (this.deepCopy());
+
+		BinaryImage bi = new BinaryImage(width, height);
+		for (int j = 0; j < height; j++) {
+			if (shape.data[j][0] != 0)
+				bi.data[j][0] = 1;
+			if (shape.data[j][width - 1] != 0)
+				bi.data[j][width - 1] = 1;
+		}
+		for (int i = 0; i < width; i++) {
+			if (shape.data[0][i] != 0)
+				bi.data[0][i] = 1;
+			if (shape.data[height - 1][i] != 0)
+				bi.data[height - 1][i] = 1;
+		}
+
+		if (connectivity == CONNECTIVITY_4) {
+			for (int j = 1; j < height - 1; j++) {
+				for (int i = 1; i < width - 1; i++) {
+					if (shape.data[j][i] != 0
+							&& (shape.data[j - 1][i - 1] == 0
+									|| shape.data[j - 1][i] == 0
+									|| shape.data[j - 1][i + 1] == 0
+									|| shape.data[j][i - 1] == 0
+									|| shape.data[j][i + 1] == 0
+									|| shape.data[j + 1][i - 1] == 0
+									|| shape.data[j + 1][i] == 0 || shape.data[j + 1][i + 1] == 0))
+						bi.data[j][i] = 1;
+				}
+			}
+		} else if (connectivity == CONNECTIVITY_8) {
+			for (int j = 1; j < height - 1; j++) {
+				for (int i = 1; i < width - 1; i++) {
+					if (shape.data[j][i] != 0
+							&& (shape.data[j - 1][i] == 0
+									|| shape.data[j + 1][i] == 0
+									|| shape.data[j][i - 1] == 0 || shape.data[j][i + 1] == 0))
+						bi.data[j][i] = 1;
+				}
+			}
+		} else {
+			throw new ImageException("Unknown connectivity");
+		}
+
+		ConnectedComponent cc = new ConnectedComponent(left, top, bi,
+				connectivity);
+		return (cc);
+	}
+
+	public ConnectedComponent thinning() throws ImageException {
+		return (thinning(THINNING_DEFAULT));
+	}
+
+	public ConnectedComponent thinning(short _method) throws ImageException {
+		if (_method == THINNING_HILDITCH) {
+			return (thinningHilditch());
+		} else {
+			// TBD
+			throw new ImageException("Unknown thinning method: " + _method);
+		}
+	}
+
+	// Hilditch
+	public ConnectedComponent thinningHilditch() {
+
+		int width = shape.width;
+		int height = shape.height;
+
+		// add 1px to rim
+		BinaryImage biBefore = new BinaryImage(width + 2, height + 2);
+		BinaryImage biAfter = new BinaryImage(width + 2, height + 2);
+		for (int j = 0; j < height; j++) {
+			for (int i = 0; i < width; i++) {
+				biBefore.data[j + 1][i + 1] = shape.data[j][i];
+			}
+		}
+
+		while (scanForThinningHilditch(biBefore, biAfter) > 0) {
+
+			biBefore = biAfter;
+			biAfter = new BinaryImage(width + 2, height + 2);
+		}
+
+		BinaryImage bi = new BinaryImage(width, height);
+		for (int j = 0; j < height; j++) {
+			for (int i = 0; i < width; i++) {
+				bi.data[j][i] = biBefore.data[j + 1][i + 1];
+			}
+		}
+
+		return (new ConnectedComponent(left, top, bi, CONNECTIVITY_8));
+	}
+
+	private int scanForThinningHilditch(BinaryImage _before, BinaryImage _after) {
+		int width = _before.width;
+		int height = _before.height;
+		int numChanged = 0;
+		for (int j = 1; j < height - 1; j++) {
+			for (int i = 1; i < width - 1; i++) {
+				if (_before.data[j][i] == 0)
+					continue;
+
+				Neighbor nei = new Neighbor(_before, i, j);
+				if (nei.numBackground4() == 0) { // (1)
+					_after.data[j][i] = 1;
+					continue;
+				}
+				if (nei.connectivityNumber8() != 1) { // (2)
+					_after.data[j][i] = 1;
+					continue;
+				}
+				if (nei.numForeground8() < 2) { // (3)
+					_after.data[j][i] = 1;
+					continue;
+				}
+				Neighbor nei2 = nei.deepCopy();
+				nei2.x[2] = _after.data[j - 1][i + 1]; // right upper
+				nei2.x[3] = _after.data[j - 1][i]; // upper
+				nei2.x[4] = _after.data[j - 1][i - 1]; // left upper
+				nei2.x[5] = _after.data[j][i - 1]; // left
+				if (nei2.numForeground8() == 0) { // (4)
+					_after.data[j][i] = 1;
+					continue;
+				}
+				// need to check (5)
+				Neighbor nei3 = nei.deepCopy();
+				nei3.x[3] = _after.data[j - 1][i];
+				if (nei3.connectivityNumber8() != 1) { // (5-A) upper
+					_after.data[j][i] = 1;
+					continue;
+				}
+				Neighbor nei4 = nei.deepCopy();
+				nei4.x[5] = _after.data[j][i - 1];
+				if (nei4.connectivityNumber8() != 1) { // (5-B) left
+					_after.data[j][i] = 1;
+					continue;
+				}
+
+				// remove the pixel(do nothing)
+				numChanged++;
+			}
+		}
+		return (numChanged);
+	}
+
+	public Topology calcTopology() throws ImageException {
+		return (new Topology(this));
+	}
+
+	public ConnectedComponent calcConvexHull() throws ImageException {
+		ConnectedComponent cont = calcContour();
+		Coord[] contPoints = cont.shape.extractPoints();
+		if (contPoints == null)
+			return (null);
+		int len = contPoints.length;
+		if (len == 0)
+			return (null);
+		if (len < 5)
+			return (this.deepCopy());
+
+		Vector<Coord> vertexVector = new Vector<Coord>();
+		Coord p0 = shape.topLeftPoint();
+		vertexVector.addElement(p0);
+		Coord curPoint = p0;
+		Coord curVector = new Coord(1, 0);
+		Coord nextPoint = nextConvexHullVertex(contPoints, curPoint, curVector);
+		while (!nextPoint.equals(p0)) {
+			vertexVector.addElement(nextPoint);
+			curVector.set(nextPoint.x - curPoint.x, nextPoint.y - curPoint.y);
+			curPoint = nextPoint;
+			nextPoint = nextConvexHullVertex(contPoints, curPoint, curVector);
+		}
+		int numVertex = vertexVector.size();
+		Coord[] vertexArray = new Coord[numVertex];
+		for (int i = 0; i < numVertex; i++) {
+			vertexArray[i] = (Coord) (vertexVector.elementAt(i));
+		}
+
+		// // debug(from here)
+		// Coord.dump(System.out, vertexArray);
+		// // debug(to here)
+
+		BinaryImage newShape = new BinaryImage(shape.width, shape.height,
+				vertexArray);
+		return (new ConnectedComponent(left, top, newShape, connectivity));
+	}
+
+	/*
+	 * find the point from _all that angle made by vector and (_origin to
+	 * target) become the smallest degree->clockwise
+	 */
+	private Coord nextConvexHullVertex(Coord[] _all, Coord _origin,
+			Coord _vector) throws ImageException {
+		if (_all == null) {
+			throw new ImageException("Empty vertex set.");
+		}
+		int len = _all.length;
+		if (len == 0) {
+			throw new ImageException("No vertex");
+		}
+
+		Coord answer = new Coord(-1, -1);
+		Coord curVector = new Coord(-1, -1);
+		double maxCos = -2.0;
+		double maxDistance = 0.0;
+		for (int i = 0; i < len; i++) {
+			Coord curPoint = _all[i];
+			if (curPoint.equals(_origin))
+				continue;
+			curVector.set(curPoint.x - _origin.x, curPoint.y - _origin.y);
+			double curCos = Coord.cosine(_vector, curVector);
+			if (maxCos < curCos) {
+				maxCos = curCos;
+				maxDistance = Coord.distance(_origin, curPoint);
+				answer.copy(curPoint);
+			} else if (maxCos == curCos) {
+				double curDistance = Coord.distance(_origin, curPoint);
+				if (curDistance > maxDistance) {
+					maxDistance = curDistance;
+					answer.copy(curPoint);
+				}
+			}
+		}
+
+		return (answer);
+	}
+
+	/*
+	 * calc genus (Euler number)
+	 *  4: G = V - E + F
+	 *  8: G = V - E - D + T - F
+	 * V: number of fg pix
+	 * E: number of connected fg pixel(2pix, vertically, horizontally)
+	 * D: number of connected fg pixel(2pix, diagonal)
+	 * T: number of connected fg pixel(3pix, vertically, horizontally)
+	 * F: number of connected fg pixel(2x2 pixels)
+	 */
+	public int calcGenus() throws ImageException {
+		if (connectivity == CONNECTIVITY_UNSET) {
+			throw new ImageException(
+					"Information on connectivity is needed to calculate genus");
+		}
+
+		int width = shape.width;
+		int height = shape.height;
+		if (width <= 2 || height <= 2)
+			return (1);
+
+		int v = shape.measureArea();
+		int e = 0;
+		int d = 0;
+		int t = 0;
+		int f = 0;
+
+		if (connectivity == CONNECTIVITY_4) {
+			for (int j = 0; j < height - 1; j++) {
+				for (int i = 0; i < width - 1; i++) {
+					if (shape.data[j][i] != 0) {
+						if (shape.data[j + 1][i] != 0)
+							e++;
+						if (shape.data[j][i + 1] != 0)
+							e++;
+						if (shape.data[j + 1][i] != 0
+								&& shape.data[j][i + 1] != 0
+								&& shape.data[j + 1][i + 1] != 0)
+							f++;
+					}
+				}
+				if (shape.data[j][width - 1] != 0
+						&& shape.data[j + 1][width - 1] != 0)
+					e++;
+			}
+			for (int i = 0; i < width - 1; i++)
+				if (shape.data[height - 1][i] != 0
+						&& shape.data[height - 1][i + 1] != 0)
+					e++;
+			return (v - e + f);
+		} else if (connectivity == CONNECTIVITY_8) {
+			for (int j = 0; j < height - 1; j++) {
+				for (int i = 0; i < width - 1; i++) {
+					if (shape.data[j][i] != 0) {
+						boolean ne = false;
+						boolean sw = false;
+						boolean se = false;
+						if (shape.data[j + 1][i] != 0) {
+							sw = true;
+							e++;
+						}
+						if (shape.data[j][i + 1] != 0) {
+							ne = true;
+							e++;
+						}
+						if (shape.data[j + 1][i + 1] != 0) {
+							se = true;
+							d++;
+						}
+						if (ne && sw)
+							t++;
+						if (ne && se)
+							t++;
+						if (sw && se)
+							t++;
+						if (ne && sw && se)
+							f++;
+					}
+					if (shape.data[j][i + 1] != 0) {
+						if (shape.data[j + 1][i] != 0) {
+							d++;
+							if (shape.data[j + 1][i + 1] != 0)
+								t++;
+						}
+					}
+				}
+				if (shape.data[j][width - 1] != 0
+						&& shape.data[j + 1][width - 1] != 0)
+					e++;
+			}
+			for (int i = 0; i < width - 1; i++)
+				if (shape.data[height - 1][i] != 0
+						&& shape.data[height - 1][i + 1] != 0)
+					e++;
+			return (v - e - d + t - f);
+		} else {
+			throw new ImageException("Unknown connectivity");
+		}
+	}
+	
+	public void dump(PrintStream _ps) {
+		PrintWriter pw = new PrintWriter(_ps, true);
+		dump(pw);
+	}
+
+	public void dump(PrintWriter _pw) {
+		_pw.println("-------------------------------");
+		_pw.println("Dumping a ConnectedComponent");
+		_pw.println("Left = " + left + ", Top = " + top + ", Width = "
+				+ shape.width + ", Height = " + shape.height);
+		for (int j = 0; j < shape.height; j++) {
+			StringBuffer sb = new StringBuffer();
+			for (int i = 0; i < shape.width; i++) {
+				if (shape.data[j][i] == 0)
+					sb.append(".");
+				else
+					sb.append("#");
+			}
+			_pw.println(sb.toString());
+		}
+		_pw.println("-------------------------------");
+	}
+
+	public void dump(PrintStream _ps, int _left, int _top, int _width,
+			int _height) {
+		PrintWriter pw = new PrintWriter(_ps, true);
+		dump(pw, _left, _top, _width, _height);
+	}
+
+	public void dump(PrintWriter _pw, int _left, int _top, int _width,
+			int _height) {
+		_pw.println("-------------------------------");
+		_pw.println("Dumping a part of a ConnectedComponent");
+		_pw.println("Left = " + left + ", Top = " + top + ", Width = "
+				+ shape.width + ", Height = " + shape.height);
+		_pw.println("Start point = ( " + _left + ", " + _top + ")");
+		_pw.println("Printed width = " + _width + ", Printed height = "
+				+ _height);
+		for (int j = 0; j < _height; j++) {
+			StringBuffer sb = new StringBuffer();
+			for (int i = 0; i < _width; i++) {
+				if (shape.data[j + _top][i + _left] == 0)
+					sb.append(".");
+				else
+					sb.append("#");
+			}
+			_pw.println(sb.toString());
+		}
+		_pw.println("-------------------------------");
+	}
+
+	public Int2D drawShape(Int2D _i2d, int _color) {
+		for (int j = 0; j < shape.height; j++) {
+			for (int i = 0; i < shape.width; i++) {
+				if (shape.data[j][i] != 0) {
+					_i2d.data[j + top][i + left] = _color;
+				}
+			}
+		}
+		return (_i2d);
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/Container.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/Container.java
new file mode 100644
index 0000000..3f90e24
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/Container.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision.image;
+
+import java.util.Vector;
+
+import org.eclipse.actf.visualization.engines.lowvision.character.CandidateCharacter;
+import org.eclipse.actf.visualization.engines.lowvision.character.CandidateUnderlinedCharacter;
+import org.eclipse.actf.visualization.engines.lowvision.character.CharacterMS;
+import org.eclipse.actf.visualization.engines.lowvision.character.CharacterSM;
+import org.eclipse.actf.visualization.engines.lowvision.character.CharacterSS;
+
+public class Container extends PageComponent {
+	private int color;
+
+	int numSSCharacters = 0; // ssCharacters.length
+
+	CharacterSS[] ssCharacters = null;
+
+	int numMSCharacters = 0; // msCharacters.length
+
+	CharacterMS[] msCharacters = null;
+
+	int numSMCharacters = 0; // smCharacters.length
+
+	CharacterSM[] smCharacters = null;
+
+	Vector<CandidateCharacter> candidateCharacterVector = new Vector<CandidateCharacter>();
+
+	Vector<CandidateUnderlinedCharacter> candidateUnderlinedCharacterVector = new Vector<CandidateUnderlinedCharacter>();
+
+	Vector<CharacterSS> ssCharacterVector = new Vector<CharacterSS>();
+
+	Vector<CharacterMS> msCharacterVector = new Vector<CharacterMS>();
+
+	public Container(PageImage _pi, int _ID, ConnectedComponent _cc, int _color) {
+		super(CONTAINER_TYPE, _pi);
+		cc = _cc;
+		color = _color;
+		componentID = _ID;
+	}
+
+	void ssVector2Array() {
+		numSSCharacters = ssCharacterVector.size();
+		ssCharacters = new CharacterSS[numSSCharacters];
+		for (int k = 0; k < numSSCharacters; k++) {
+			ssCharacters[k] = ssCharacterVector.elementAt(k);
+		}
+		ssCharacterVector.removeAllElements();
+	}
+
+	void msVector2Array() {
+		numMSCharacters = msCharacterVector.size();
+		msCharacters = new CharacterMS[numMSCharacters];
+		for (int k = 0; k < numMSCharacters; k++) {
+			msCharacters[k] = msCharacterVector.elementAt(k);
+		}
+		msCharacterVector.removeAllElements();
+	}
+
+	public int getColor() {
+		return color;
+	}
+
+	public int getNumMSCharacters() {
+		return numMSCharacters;
+	}
+
+	public int getNumSMCharacters() {
+		return numSMCharacters;
+	}
+
+	public int getNumSSCharacters() {
+		return numSSCharacters;
+	}
+
+	public CharacterMS[] getMsCharacters() {
+		return msCharacters;
+	}
+
+	public CharacterSM[] getSmCharacters() {
+		return smCharacters;
+	}
+
+	public CharacterSS[] getSsCharacters() {
+		return ssCharacters;
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/Coord.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/Coord.java
new file mode 100644
index 0000000..60f9bdb
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/Coord.java
@@ -0,0 +1,177 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision.image;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+public class Coord {
+	int x; // holizontal
+
+	int y; // vertical
+
+	public Coord(int _x, int _y) {
+		x = _x;
+		y = _y;
+	}
+
+	public int getX() {
+		return (x);
+	}
+
+	public int getY() {
+		return (y);
+	}
+
+	public void set(int _x, int _y) {
+		x = _x;
+		y = _y;
+	}
+
+	public void setX(int _x) {
+		x = _x;
+	}
+
+	public void setY(int _y) {
+		y = _y;
+	}
+
+	public void copy(Coord _co) {
+		x = _co.x;
+		y = _co.y;
+	}
+
+	public boolean isOrigin() {
+		if (x == 0 && y == 0)
+			return (true);
+		else
+			return (false);
+	}
+
+	public boolean equals(Coord _co) {
+		if (x == _co.x && y == _co.y)
+			return (true);
+		else
+			return (false);
+	}
+
+	// a+b
+	public static Coord add(Coord _a, Coord _b) {
+		return (new Coord(_a.x + _b.x, _a.y + _b.y));
+	} // add( Coord, Coord )
+
+	// this+b
+	public Coord add(Coord _b) {
+		return (add(this, _b));
+	} // add( Coord )
+
+	// a-b
+	public static Coord subtract(Coord _a, Coord _b) {
+		return (new Coord(_a.x - _b.x, _a.y - _b.y));
+	} // subtract( Coord, Coord )
+
+	// this-b
+	public Coord subtract(Coord _b) {
+		return (subtract(this, _b));
+	} // subtract( Coord )
+
+	public static int distancePow2(Coord _a, Coord _b) {
+		int xDif = _a.x - _b.x;
+		int yDif = _a.y - _b.y;
+		return (xDif * xDif + yDif * yDif);
+	}
+
+	public static int distancePow2(Coord _a) {
+		return (_a.x * _a.x + _a.y * _a.y);
+	}
+
+	public static double distance(Coord _a, Coord _b) {
+		return (Math.sqrt((double) distancePow2(_a, _b)));
+	}
+
+	public static double distance(Coord _a) {
+		return (Math.sqrt((double) distancePow2(_a)));
+	}
+
+	public static boolean isOnLine(Coord _start, Coord _end, Coord _point) {
+		Coord vector1 = Coord.subtract(_end, _start);
+		Coord vector2 = Coord.subtract(_point, _start);
+		if (outerProduct(vector1, vector2) == 0)
+			return (true);
+		else
+			return (false);
+	}
+
+	public static boolean isLeftToVector(Coord _start, Coord _end, Coord _point) {
+		Coord vector1 = Coord.subtract(_end, _start);
+		Coord vector2 = Coord.subtract(_point, _start);
+		if (outerProduct(vector2, vector1) > 0)
+			return (true);
+		else
+			return (false);
+	}
+
+	public static boolean isRightToVector(Coord _start, Coord _end, Coord _point) {
+		Coord vector1 = Coord.subtract(_end, _start);
+		Coord vector2 = Coord.subtract(_point, _start);
+		if (outerProduct(vector1, vector2) > 0)
+			return (true);
+		else
+			return (false);
+	}
+
+	public static int innerProduct(Coord _a, Coord _b) {
+		return (_a.x * _b.x + _a.y * _b.y);
+	}
+
+	public static double cosine(Coord _a, Coord _b) throws ImageException {
+		if (_a.isOrigin() || _b.isOrigin()) {
+			throw new ImageException("Cannot calculate cosine of zero-vectors");
+		}
+		return ((double) innerProduct(_a, _b) / (distance(_a) * distance(_b)));
+	}
+
+	public static int outerProduct(Coord _a, Coord _b) {
+		return (_a.x * _b.y - _a.y * _b.x);
+	}
+
+	public void dump() {
+		dump(System.out);
+	}
+
+	public void dump(PrintStream _ps) {
+		PrintWriter pw = new PrintWriter(_ps, true);
+		dump(pw);
+	}
+
+	public void dump(PrintWriter _pw) {
+		_pw.println("-------------------------------");
+		_pw.println("Dumping a point");
+		_pw.println("(" + x + "," + y + ")");
+		_pw.println("-------------------------------");
+	}
+
+	public static void dump(PrintStream _ps, Coord[] _points) {
+		PrintWriter pw = new PrintWriter(_ps, true);
+		dump(pw, _points);
+	}
+
+	public static void dump(PrintWriter _pw, Coord[] _points) {
+		int numPoints = _points.length;
+		_pw.println("-------------------------------");
+		_pw.println("Dumping points");
+		_pw.println("# of points = " + numPoints);
+		for (int i = 0; i < numPoints; i++) {
+			_pw.println("(" + _points[i].x + "," + _points[i].y + ")");
+			_pw.println("-----");
+		}
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/ImageException.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/ImageException.java
new file mode 100644
index 0000000..21ec9d0
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/ImageException.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision.image;
+
+public class ImageException extends Exception{
+	private static final long serialVersionUID = -3796816367042170808L;
+
+	public ImageException(){
+		super();
+	}
+	public ImageException( String _s ){
+		super(_s);
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/ImageUtil.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/ImageUtil.java
new file mode 100644
index 0000000..61e4a34
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/ImageUtil.java
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision.image;
+
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBufferInt;
+import java.awt.image.WritableRaster;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+public class ImageUtil {
+	public static Int2D bufferedImageToInt2D(BufferedImage _bi)
+			throws ImageException {
+		if (_bi == null) {
+			throw new ImageException("Input BufferedImage is null.");
+		}
+		int width = _bi.getWidth();
+		int height = _bi.getHeight();
+		Int2D i2d = new Int2D(width, height);
+		WritableRaster srcRaster = _bi.copyData(null);
+
+		DataBufferInt srcBufInt = (DataBufferInt) (srcRaster.getDataBuffer());
+		int[] srcArray = srcBufInt.getData();
+		int k = 0;
+		for (int j = 0; j < height; j++) {
+			for (int i = 0; i < width; i++) {
+				i2d.data[j][i] = srcArray[k];
+				k++;
+			}
+		}
+		return (i2d);
+	}
+
+	public static BufferedImage int2DToBufferedImage(Int2D _i2d) {
+		return (int2DArrayToBufferedImage(_i2d.data, _i2d.width, _i2d.height));
+	}
+
+	public static int[][] bufferedImageToInt2DArray(BufferedImage _bi,
+			int _width, int _height) {
+		int[][] pixel = new int[_height][_width];
+		WritableRaster srcRaster = _bi.copyData(null);
+		DataBufferInt srcBufInt = (DataBufferInt) (srcRaster.getDataBuffer());
+		int[] srcArray = srcBufInt.getData();
+		int k = 0;
+		for (int j = 0; j < _height; j++) {
+			for (int i = 0; i < _width; i++) {
+				pixel[j][i] = srcArray[k];
+				k++;
+			}
+		}
+		return (pixel);
+	}
+
+	public static BufferedImage int2DArrayToBufferedImage(int[][] _pixel,
+			int _width, int _height) {
+		BufferedImage destBufferedImage = new BufferedImage(_width, _height,
+				BufferedImage.TYPE_INT_RGB);
+		WritableRaster destRaster = destBufferedImage.copyData(null);
+		DataBufferInt destBufInt = (DataBufferInt) (destRaster.getDataBuffer());
+		int[] destArray = destBufInt.getData();
+		int k = 0;
+		for (int j = 0; j < _height; j++) {
+			for (int i = 0; i < _width; i++) {
+				destArray[k] = _pixel[j][i];
+				k++;
+			}
+		}
+		destBufferedImage.setData(destRaster);
+		return (destBufferedImage);
+	}
+
+	public static int[][] copyInt2DArray(int[][] _src, int _width, int _height) {
+		int[][] destArray2D = new int[_height][_width];
+		for (int j = 0; j < _height; j++) {
+			for (int i = 0; i < _width; i++) {
+				destArray2D[j][i] = _src[j][i];
+			}
+		}
+		return (destArray2D);
+	}
+
+	public static void dumpInt2DArray(PrintStream _ps, int[][] _data,
+			int _width, int _height) {
+		PrintWriter pw = new PrintWriter(_ps, false);
+		dumpInt2DArray(pw, _data, _width, _height);
+	}
+
+	public static void dumpInt2DArray(PrintWriter _pw, int[][] _data,
+			int _width, int _height) {
+		_pw.println("-------");
+		_pw.println("dumping int[][]");
+		_pw.println("width = " + _width + ", height = " + _height);
+		_pw.println("data:");
+		for (int j = 0; j < _height; j++) {
+			for (int i = 0; i < _width; i++) {
+				_pw.print("" + _data[j][i]);
+			}
+			_pw.println("");
+		}
+		_pw.println("-------");
+		_pw.flush();
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/Int2D.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/Int2D.java
new file mode 100644
index 0000000..9ae8e48
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/Int2D.java
@@ -0,0 +1,198 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.image;
+
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBufferInt;
+import java.awt.image.WritableRaster;
+import java.io.InputStream;
+
+import org.eclipse.actf.visualization.engines.lowvision.internal.io.BMPReader;
+import org.eclipse.actf.visualization.engines.lowvision.internal.io.BMPWriter;
+import org.eclipse.actf.visualization.engines.lowvision.io.LowVisionIOException;
+
+/*
+ * data[y][x] = BufferdImage.TYPE_INT_RGB (null, R, G, B)
+ * 
+ * data[0][0] is top left
+ */
+public class Int2D {
+	public int width;
+
+	public int height;
+
+	public int[][] data;
+
+	public Int2D(int _w, int _h) {
+		width = _w;
+		height = _h;
+		data = new int[height][width];
+	}
+
+	public Int2D(int _w, int _h, int[][] _array) throws ImageException {
+		this(_w, _h);
+		if (_array.length < _h || _array[0].length < _w) {
+			throw new ImageException("Out of range");
+		}
+		for (int j = 0; j < height; j++) {
+			for (int i = 0; i < width; i++) {
+				this.data[j][i] = _array[j][i];
+			}
+		}
+	}
+
+	public Int2D(Int2D _src) {
+		this(_src.width, _src.height);
+		for (int j = 0; j < height; j++) {
+			for (int i = 0; i < width; i++) {
+				this.data[j][i] = _src.data[j][i];
+			}
+		}
+	}
+
+	public Int2D(BufferedImage _bi) {
+		this(_bi.getWidth(), _bi.getHeight());
+		WritableRaster srcRaster = _bi.copyData(null);
+		DataBufferInt srcBufInt = (DataBufferInt) (srcRaster.getDataBuffer());
+		int[] srcArray = srcBufInt.getData();
+		int k = 0;
+		for (int j = 0; j < height; j++) {
+			for (int i = 0; i < width; i++) {
+				data[j][i] = srcArray[k];
+				k++;
+			}
+		}
+	}
+
+	public static Int2D deepCopy(Int2D _src) {
+		int width = _src.width;
+		int height = _src.height;
+		Int2D dest = new Int2D(width, height);
+		for (int j = 0; j < height; j++) {
+			for (int i = 0; i < width; i++) {
+				dest.data[j][i] = _src.data[j][i];
+			}
+		}
+		return (dest);
+	}
+
+	public Int2D deepCopy() {
+		return (deepCopy(this));
+	}
+
+	public int getWidth() {
+		return (width);
+	}
+
+	public int getHeight() {
+		return (height);
+	}
+
+	public static Int2D readFromBMPFile(String _fileName)
+			throws LowVisionIOException {
+		return (BMPReader.readInt2D(_fileName));
+	}
+
+	public static Int2D readFromBMPInputStream(InputStream _is)
+			throws LowVisionIOException {
+		return (BMPReader.readInt2D(_is));
+	}
+
+	public BufferedImage toBufferedImage() {
+		return (ImageUtil.int2DToBufferedImage(this));
+	}
+
+	public void writeToBMPFile(String _fileName) throws LowVisionIOException {
+		BMPWriter.writeInt2D(this, _fileName);
+	}
+
+	public void writeToBMPFile(String _fileName, int _bitCount)
+			throws LowVisionIOException {
+		BMPWriter.writeInt2D(this, _fileName, _bitCount);
+	}
+
+	public static void writeToBMPFile(Int2D _src, String _fileName)
+			throws LowVisionIOException {
+		BMPWriter.writeInt2D(_src, _fileName);
+	}
+
+	public static void writeToBMPFile(Int2D _src, String _fileName,
+			int _bitCount) throws LowVisionIOException {
+		BMPWriter.writeInt2D(_src, _fileName, _bitCount);
+	}
+
+	public void fill(int _color) {
+		for (int j = 0; j < height; j++) {
+			for (int i = 0; i < width; i++) {
+				data[j][i] = _color;
+			}
+		}
+	}
+
+	public Int2D cutMargin(int _m) throws ImageException {
+		if (width <= 2 * _m || height <= 2 * _m) {
+			throw new ImageException("The margin is too wide.");
+		}
+		int newW = width - 2 * _m;
+		int newH = height - 2 * _m;
+		Int2D i2d = new Int2D(newW, newH);
+		for (int j = 0; j < newH; j++) {
+			for (int i = 0; i < newW; i++) {
+				i2d.data[j][i] = this.data[j + _m][i + _m];
+			}
+		}
+		return (i2d);
+	}
+
+	public void drawContour(ConnectedComponent _cc, int _color,
+			boolean _overWrite) {
+		Int2D dest = this;
+		if (!_overWrite) {
+			dest = this.deepCopy();
+		}
+
+		int ccLeft = _cc.left;
+		int ccTop = _cc.top;
+		int ccWidth = _cc.shape.width;
+		int ccHeight = _cc.shape.height;
+
+		for (int j = 0; j < ccHeight; j++) {
+			if (_cc.shape.data[j][0] != 0) {
+				dest.data[j + ccTop][ccLeft] = _color;
+			}
+			if (_cc.shape.data[j][ccWidth - 1] != 0) {
+				dest.data[j + ccTop][ccWidth - 1 + ccLeft] = _color;
+			}
+		}
+		for (int i = 0; i < ccWidth; i++) {
+			if (_cc.shape.data[0][i] != 0) {
+				dest.data[ccTop][i + ccLeft] = _color;
+			}
+			if (_cc.shape.data[ccHeight - 1][0] != 0) {
+				dest.data[ccHeight - 1 + ccTop][ccLeft] = _color;
+			}
+		}
+
+		for (int j = 1; j < ccHeight - 1; j++) {
+			for (int i = 1; i < ccWidth - 1; i++) {
+				if (_cc.shape.data[j][i] != 0) {
+					if (_cc.shape.data[j][i - 1] == 0
+							|| _cc.shape.data[j][i + 1] == 0
+							|| _cc.shape.data[j - 1][i] == 0
+							|| _cc.shape.data[j + 1][i] == 0) {
+						dest.data[j + ccTop][i + ccLeft] = _color;
+					}
+				}
+			}
+		}
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/InteriorImage.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/InteriorImage.java
new file mode 100644
index 0000000..f92e7d1
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/InteriorImage.java
@@ -0,0 +1,348 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.image;
+
+import java.awt.image.BufferedImage;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Vector;
+
+import org.eclipse.actf.model.ui.editor.ImagePositionInfo;
+import org.eclipse.actf.visualization.engines.lowvision.LowVisionCommon;
+import org.eclipse.actf.visualization.engines.lowvision.LowVisionException;
+import org.eclipse.actf.visualization.engines.lowvision.LowVisionType;
+import org.eclipse.actf.visualization.engines.lowvision.color.ColorIRGB;
+import org.eclipse.actf.visualization.engines.lowvision.operator.LowVisionFilter;
+import org.eclipse.actf.visualization.engines.lowvision.problem.ImageColorProblem;
+import org.eclipse.actf.visualization.engines.lowvision.problem.LowVisionProblem;
+import org.eclipse.actf.visualization.engines.lowvision.problem.LowVisionProblemException;
+import org.eclipse.actf.visualization.engines.lowvision.problem.LowVisionProblemGroup;
+import org.eclipse.actf.visualization.engines.lowvision.util.DecisionMaker;
+
+public class InteriorImage extends PageComponent {
+
+	public static final int UNSET = -1;
+
+	int left = UNSET; // relative position
+
+	int top = UNSET; // relative position
+
+	Int2D pixel = null;
+
+	int numLargeComponents = 0;
+
+	InteriorImageComponent[] largeComponents = null;
+
+	String url = null;
+
+	// a part of PageImage
+	public InteriorImage(PageImage _pi, int _x, int _y, int _width, int _height) {
+		super(INTERIOR_IMAGE_TYPE, _pi);
+
+		left = _x;
+		top = _y;
+		pixel = new Int2D(_width, _height);
+		for (int j = 0; j < _height; j++) {
+			for (int i = 0; i < _width; i++) {
+				pixel.data[j][i] = _pi.pixel.data[j + top][i + left];
+			}
+		}
+	}
+
+	// a part of PageImage
+	public InteriorImage(PageImage _pi, ImagePositionInfo _pos) {
+		this(_pi, _pos.getX(), _pos.getY(), _pos.getWidth(), _pos.getHeight());
+		url = _pos.getUrl();
+	}
+
+	public InteriorImage(Int2D _i2d) {
+		super(INTERIOR_IMAGE_TYPE, null);
+		pixel = _i2d.deepCopy();
+	}
+
+	public InteriorImage(BufferedImage _bi) throws ImageException {
+		super(INTERIOR_IMAGE_TYPE, null);
+		pixel = ImageUtil.bufferedImageToInt2D(_bi);
+	}
+
+	public int getLeft() {
+		return (left);
+	}
+
+	public int getTop() {
+		return (top);
+	}
+
+	public String getUrl() {
+		return (url);
+	}
+
+	// content type detection
+	/*
+	 * private static final int MIN_CHARACTER_IMAGE_HEIGHT = 20; private static
+	 * final int MIN_FIGURE_IMAGE_HEIGHT = 150;
+	 * 
+	 * public void setContentType(){ int width = getWidth(); int height =
+	 * getHeight(); short fileType = IoUtil.getFileType( this.url ); //null ->
+	 * TYPE_UNKNOWN if( height < MIN_CHARACTER_IMAGE_HEIGHT ){ contentType =
+	 * OTHER_TYPE; return; } // if( fileType != IoUtil.TYPE_GIF ){ // //TBD
+	 * consider gradation (edge) in JPEG graph// contentType = OTHER_TYPE; //
+	 * return; // } if( height < MIN_FIGURE_IMAGE_HEIGHT ){ contentType =
+	 * OTHER_TYPE; return; } contentType = FIGURE_TYPE; }
+	 */
+
+	public int getWidth() {
+		return (pixel.width );
+	}
+
+	public int getHeight() {
+		return (pixel.height );
+	}
+
+	public String dumpLargeComponents() {
+		if (numLargeComponents == 0) {
+			return ("There are no large components.");
+		}
+		String msg = "There are " + numLargeComponents + " large components.\n";
+		for (int i = 0; i < numLargeComponents; i++) {
+			InteriorImageComponent curComponent = largeComponents[i];
+			ColorIRGB curColor = new ColorIRGB(curComponent.getColor());
+			msg += i + ": ( " + curColor.getR() + ", " + curColor.getG() + ", "
+					+ curColor.getB() + ")\n";
+		}
+		return (msg);
+	}
+
+	public void extractLargeComponents() {
+		if (largeComponents != null) {
+			return;
+		}
+
+		Vector<InteriorImageComponent> largeComponentVector = new Vector<InteriorImageComponent>();
+
+		ColorHistogram histo = ColorHistogram.makeColorHistogram(pixel);
+
+		int histoSize = histo.getSize();
+		int numProcessedColors = histoSize;
+		ColorHistogramBin[] histoArray = histo.getSortedArrayByOccurrence();
+		for (int i = 0; i < histoSize; i++) {
+			if (histoArray[i].occurrence < LowVisionCommon.THRESHOLD_MIN_LARGE_COMPONENT_PIXELS) {
+				numProcessedColors = i;
+				break;
+			}
+		}
+
+		for (int k = 0; k < numProcessedColors; k++) {
+			Vector<ConnectedComponent> currentVector = new Vector<ConnectedComponent>();
+
+			int curColor = histoArray[k].color;
+			BinaryImage binaryByColor = new BinaryImage(pixel,
+					BinaryImage.METHOD_SPECIFY_FOREGROUND, curColor);
+
+			LabeledImage curLabeledImage = new LabeledImage(binaryByColor,
+					LabeledImage.METHOD_8_CONNECTIVITY);
+			int numComponents = curLabeledImage.numComponents;
+			ConnectedComponent[] components = curLabeledImage.components;
+
+			for (int l = 0; l < numComponents; l++) {
+				ConnectedComponent curCc = components[l];
+				if (curCc.getCount() >= LowVisionCommon.THRESHOLD_MIN_LARGE_COMPONENT_PIXELS) {
+					currentVector.addElement(curCc);
+				}
+			}
+
+			if (currentVector.size() > 0) {
+				InteriorImageComponent iic = new InteriorImageComponent(this,
+						curColor, currentVector);
+				if (iic.occupation >= LowVisionCommon.THRESHOLD_MIN_LARGE_COMPONENT_OCCUPATION) {
+					largeComponentVector.addElement(iic);
+				}
+				currentVector.removeAllElements();
+			}
+		}
+
+		// sort by pixelsize order
+		Collections.sort(largeComponentVector, new CompareByCount());
+
+		numLargeComponents = largeComponentVector.size();
+		if (numLargeComponents > 0) {
+			largeComponents = new InteriorImageComponent[numLargeComponents];
+			for (int k = 0; k < numLargeComponents; k++) {
+				largeComponents[k] = (InteriorImageComponent) (largeComponentVector
+						.elementAt(k));
+			}
+			largeComponentVector.removeAllElements();
+		}
+	}
+
+	private class CompareByCount implements Comparator<InteriorImageComponent> {
+		public int compare(InteriorImageComponent _o1,
+				InteriorImageComponent _o2) {
+			return (_o2.count - _o1.count);
+		}
+	}
+
+	public LowVisionProblemGroup[] checkColors(LowVisionType _lvType)
+			throws ImageException {
+		if (!_lvType.doChangeColors()) {
+			return (null);
+		}
+
+		extractLargeComponents();
+
+		if (numLargeComponents <= 1) {
+			return (null);
+		}
+
+		Vector<LowVisionProblem> problemVector = new Vector<LowVisionProblem>();
+		try {
+			for (int k = 0; k < numLargeComponents - 1; k++) {
+				for (int l = k + 1; l < numLargeComponents; l++) {
+					InteriorImageComponent iic1 = largeComponents[k];
+					InteriorImageComponent iic2 = largeComponents[l];
+					int origColor1 = iic1.color;
+					int origColor2 = iic2.color;
+
+					// do not handle similar color parts in original image (to
+					// avoide false positive)
+					if (!(DecisionMaker.distinguishableImageColors(origColor1,
+							origColor2))) {
+						continue;
+					}
+
+					int convColor1 = _lvType.convertColor(origColor1);
+					int convColor2 = _lvType.convertColor(origColor2);
+
+					if (!(DecisionMaker.distinguishableImageColors(convColor1,
+							convColor2))) {
+
+						double probability = 1.0 - DecisionMaker
+								.calcColorDistanceForImage(convColor1,
+										convColor2);
+						if (probability < LowVisionCommon.THRESHOLD_MIN_IMAGE_COLOR_PROBLEM_PROBABILITY) {
+							continue;
+						}
+
+						ImageColorProblem probl = new ImageColorProblem(this,
+								_lvType, probability, iic1, iic2);
+						problemVector.addElement(probl);
+					}
+				}
+			}
+		} catch (Exception e) {
+			// e.printStackTrace();
+			throw new ImageException(
+					"Exception occurred while checking colors.");
+		}
+
+		// (A) assume ImageProblem only
+		if (problemVector.size() > 0) {
+			Collections.sort(problemVector, new CompareByProbability());
+			LowVisionProblemGroup group = null;
+			try {
+				group = new LowVisionProblemGroup(problemVector);
+			} catch (LowVisionProblemException lvpe) {
+				// lvpe.printStackTrace();
+				throw new ImageException(
+						"Error occurred while making an instance of LowVisionProblemGroup.");
+			}
+			LowVisionProblemGroup[] groupArray = new LowVisionProblemGroup[1];
+			groupArray[0] = group;
+			return (groupArray);
+		} else {
+			return (null);
+		}
+
+		// (B) several types of problems
+		/*
+		 * Vector problemGroupVector = collectProblems( problemVector );
+		 * 
+		 * int vecSize = problemGroupVector.size(); if( vecSize > 0 ){
+		 * LowVisionProblemGroup[] probGroupArray = new
+		 * LowVisionProblemGroup[vecSize]; for( int k=0; k<vecSize; k++ ){
+		 * probGroupArray[k] =
+		 * (LowVisionProblemGroup)(problemGroupVector.elementAt(k)); } return(
+		 * probGroupArray ); } else{ return( null ); }
+		 */
+	}
+
+	private Vector collectProblems(Vector<LowVisionProblem> _vec)
+			throws ImageException {
+		if (_vec == null || _vec.size() == 0) {
+			return (null);
+		}
+
+		Vector<LowVisionProblemGroup> answerVec = new Vector<LowVisionProblemGroup>();
+
+		int curSize = _vec.size();
+		while (curSize > 0) {
+			// search problems should be merged with curProb
+			LowVisionProblem curProb = _vec.elementAt(curSize - 1);
+			_vec.removeElementAt(curSize - 1);
+			Vector<LowVisionProblem> curVec = new Vector<LowVisionProblem>();
+			curVec.addElement(curProb);
+
+			short curType = curProb.getType();
+
+			for (int k = curSize - 2; k >= 0; k--) {
+				LowVisionProblem tmpProb = _vec.elementAt(k);
+				if (tmpProb.getType() == curType) {
+					_vec.removeElementAt(k);
+					curVec.addElement(tmpProb);
+				}
+			}
+
+			// sort by probability
+			Collections.sort(curVec, new CompareByProbability());
+
+			LowVisionProblemGroup curGroup = null;
+			try {
+				curGroup = new LowVisionProblemGroup(curVec);
+			} catch (LowVisionProblemException lvpe) {
+				// lvpe.printStackTrace();
+				throw new ImageException(
+						"Error occurred while making an instance of LowVisionProblemGroup.");
+			}
+			if (curGroup != null) {
+				answerVec.addElement(curGroup);
+			}
+			curSize = _vec.size();
+		}
+		return (answerVec);
+	}
+
+	private class CompareByProbability implements Comparator<LowVisionProblem> {
+		public int compare(LowVisionProblem _o1, LowVisionProblem _o2) {
+			double diff = _o2.getProbability() - _o1.getProbability();
+			if (diff > 0) {
+				return (1);
+			} else if (diff < 0) {
+				return (-1);
+			} else {
+				return (0);
+			}
+		}
+	}
+
+	public Int2D simulate(LowVisionType _lvType) throws ImageException {
+		LowVisionFilter lvFilter = new LowVisionFilter(_lvType);
+		try {
+			Int2D simulatedPixel = ImageUtil.bufferedImageToInt2D(lvFilter
+					.filter(pixel.toBufferedImage(), null));
+			return (simulatedPixel);
+		} catch (LowVisionException lve) {
+			// lve.printStackTrace();
+			throw new ImageException(
+					"Exception occurred while simulating an interiorImage");
+		}
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/InteriorImageComponent.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/InteriorImageComponent.java
new file mode 100644
index 0000000..e9fdc52
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/InteriorImageComponent.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.image;
+
+import java.util.Vector;
+
+public class InteriorImageComponent {
+	InteriorImage containerImage = null;
+
+	int color;
+
+	int numConnectedComponents = 0;
+
+	ConnectedComponent[] connectedComponents = null;
+
+	int count = 0; // number of pixel in connected component
+
+	double occupation = 0.0; // occupation ratio in original image
+
+	InteriorImageComponent(InteriorImage _ii, int _color, Vector _vec) {
+		containerImage = _ii;
+		color = _color;
+		numConnectedComponents = _vec.size();
+		if (numConnectedComponents > 0) {
+			connectedComponents = new ConnectedComponent[numConnectedComponents];
+			for (int k = 0; k < numConnectedComponents; k++) {
+				ConnectedComponent cc = (ConnectedComponent) (_vec.elementAt(k));
+				count += cc.getCount();
+				connectedComponents[k] = cc;
+			}
+			occupation = (double) count
+					/ (double) (_ii.getWidth() * _ii.getHeight());
+		}
+	}
+
+	public InteriorImage getContainerImage() {
+		return (containerImage);
+	}
+
+	public int getColor() {
+		return (color);
+	}
+
+	public int getNumConnectedComponents() {
+		return (numConnectedComponents);
+	}
+
+	public ConnectedComponent[] getConnectedComponents() {
+		return (connectedComponents);
+	}
+
+	public ConnectedComponent getConnectedComponent(int _index)
+			throws ImageException {
+		if (_index < 0 || numConnectedComponents <= _index) {
+			throw new ImageException("Out of range: specified index = "
+					+ _index + ", while #ConnectedComponent = "
+					+ numConnectedComponents);
+		}
+		return (connectedComponents[_index]);
+	}
+
+	public int getCount() {
+		return (count);
+	}
+
+	public double getOccupation() {
+		return (occupation);
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/LabeledImage.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/LabeledImage.java
new file mode 100644
index 0000000..41d8aee
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/LabeledImage.java
@@ -0,0 +1,339 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision.image;
+
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBufferInt;
+import java.awt.image.WritableRaster;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.util.Stack;
+import java.util.Vector;
+
+import org.eclipse.actf.visualization.engines.lowvision.color.ColorUtil;
+
+/*
+ * Labeled image obtained by connected component detection.
+ * 
+ * use (width, height, label) or (numComponents, components)
+ * 
+ * label bg-> 0 fg (connected components) > 1 (Integer)
+ * 
+ */
+public class LabeledImage {
+	public static final short METHOD_8_CONNECTIVITY = 0;
+
+	public static final short METHOD_4_CONNECTIVITY = 1;
+
+	int width;
+
+	int height;
+
+	int[][] label;
+
+	int numComponents; // numComponents == components.length
+
+	ConnectedComponent[] components;
+
+	short method;
+
+	int left;
+
+	int right;
+
+	int top;
+
+	int bottom;
+
+	int count;
+
+	public LabeledImage(BinaryImage _bi) {
+		this(_bi, METHOD_8_CONNECTIVITY);
+	}
+
+	public LabeledImage(BinaryImage _bi, short _method) {
+		width = _bi.width;
+		height = _bi.height;
+		label = new int[height][width];
+		method = _method;
+
+		Vector<ConnectedComponent> ccVector = new Vector<ConnectedComponent>();
+		int currentLabel = 1;
+		for (int j = 0; j < height; j++) {
+			for (int i = 0; i < width; i++) {
+				// same color & not labeled
+				if (_bi.data[j][i] > 0 && label[j][i] == 0) {
+					label[j][i] = currentLabel;
+					count = 1;
+					labelNeighbor(_bi, i, j, currentLabel, _method);
+
+					ConnectedComponent currentCC = new ConnectedComponent(left,
+							top, right - left + 1, bottom - top + 1, count);
+					for (int j2 = top; j2 <= bottom; j2++) {
+						for (int i2 = left; i2 <= right; i2++) {
+							if (label[j2][i2] == currentLabel) {
+								currentCC.shape.data[j2 - top][i2 - left] = 1;
+							}
+						}
+					}
+					ccVector.addElement(currentCC);
+
+					currentLabel++;
+				}
+			}
+		}
+
+		numComponents = currentLabel - 1;
+		components = new ConnectedComponent[numComponents];
+		short conn = ConnectedComponent.CONNECTIVITY_UNSET;
+		if (method == METHOD_8_CONNECTIVITY)
+			conn = ConnectedComponent.CONNECTIVITY_8;
+		else if (method == METHOD_4_CONNECTIVITY)
+			conn = ConnectedComponent.CONNECTIVITY_4;
+		for (int i = 0; i < numComponents; i++) {
+			components[i] = (ConnectedComponent) (ccVector.elementAt(i));
+			components[i].connectivity = conn;
+		}
+	}
+
+	/*
+	 * search connected components for pixel(_i, _j)
+	 */
+	private void labelNeighbor(BinaryImage _bi, int _i, int _j, int _label,
+			short _method) {
+		left = _i;
+		right = _i;
+		top = _j;
+		bottom = _j;
+
+		Stack<Coord> labelingStack = new Stack<Coord>();
+		Coord startCoord = new Coord(_i, _j);
+		labelingStack.push(startCoord);
+
+		while (!labelingStack.empty()) {
+			Coord co = (Coord) (labelingStack.pop());
+			int i = co.x;
+			int j = co.y;
+
+			// right
+			if (i < width - 1 && _bi.data[j][i + 1] > 0 && label[j][i + 1] == 0) {
+				label[j][i + 1] = _label;
+				count++;
+				if (right < i + 1)
+					right = i + 1;
+				Coord co2 = new Coord(i + 1, j);
+				labelingStack.push(co2);
+			}
+			// left
+			if (i > 0 && _bi.data[j][i - 1] > 0 && label[j][i - 1] == 0) {
+				label[j][i - 1] = _label;
+				count++;
+				if (left > i - 1)
+					left = i - 1;
+				Coord co2 = new Coord(i - 1, j);
+				labelingStack.push(co2);
+			}
+			// upper
+			if (j > 0 && _bi.data[j - 1][i] > 0 && label[j - 1][i] == 0) {
+				label[j - 1][i] = _label;
+				count++;
+				if (top > j - 1)
+					top = j - 1;
+				Coord co2 = new Coord(i, j - 1);
+				labelingStack.push(co2);
+			}
+			// bottom
+			if (j < height - 1 && _bi.data[j + 1][i] > 0
+					&& label[j + 1][i] == 0) {
+				label[j + 1][i] = _label;
+				count++;
+				if (bottom < j + 1)
+					bottom = j + 1;
+				Coord co2 = new Coord(i, j + 1);
+				labelingStack.push(co2);
+			}
+			if (_method == METHOD_8_CONNECTIVITY) {
+				// upper left
+				if (j > 0 && i > 0 && _bi.data[j - 1][i - 1] > 0
+						&& label[j - 1][i - 1] == 0) {
+					label[j - 1][i - 1] = _label;
+					count++;
+					if (left > i - 1)
+						left = i - 1;
+					if (top > j - 1)
+						top = j - 1;
+					Coord co2 = new Coord(i - 1, j - 1);
+					labelingStack.push(co2);
+				}
+				// upper right
+				if (j > 0 && i < width - 1 && _bi.data[j - 1][i + 1] > 0
+						&& label[j - 1][i + 1] == 0) {
+					label[j - 1][i + 1] = _label;
+					count++;
+					if (right < i + 1)
+						right = i + 1;
+					if (top > j - 1)
+						top = j - 1;
+					Coord co2 = new Coord(i + 1, j - 1);
+					labelingStack.push(co2);
+				}
+				// bottom left
+				if (j < height - 1 && i > 0 && _bi.data[j + 1][i - 1] > 0
+						&& label[j + 1][i - 1] == 0) {
+					label[j + 1][i - 1] = _label;
+					count++;
+					if (left > i - 1)
+						left = i - 1;
+					if (bottom < j + 1)
+						bottom = j + 1;
+					Coord co2 = new Coord(i - 1, j + 1);
+					labelingStack.push(co2);
+				}
+				// bottom right
+				if (j < height - 1 && i < width - 1
+						&& _bi.data[j + 1][i + 1] > 0
+						&& label[j + 1][i + 1] == 0) {
+					label[j + 1][i + 1] = _label;
+					count++;
+					if (right < i + 1)
+						right = i + 1;
+					if (bottom < j + 1)
+						bottom = j + 1;
+					Coord co2 = new Coord(i + 1, j + 1);
+					labelingStack.push(co2);
+				}
+			}
+		}
+	}
+
+	public int getWidth() {
+		return (width);
+	}
+
+	public int getHeight() {
+		return (height);
+	}
+
+	public int[][] getLabel() {
+		return (label);
+	}
+
+	public int getNumComponents() {
+		return (numComponents);
+	}
+
+	public ConnectedComponent[] getComponents() {
+		return (components);
+	}
+
+	public short getMethod() {
+		return (method);
+	}
+
+	public BinaryImage toBinaryImage() {
+		BinaryImage bi = new BinaryImage(width, height);
+		for (int j = 0; j < height; j++) {
+			for (int i = 0; i < width; i++) {
+				if (label[j][i] != 0)
+					bi.data[j][i] = 1;
+			}
+		}
+
+		return (bi);
+	}
+
+	/*
+	 * assign color to each label and generate bufferd image
+	 */
+	public BufferedImage toBufferedImage() throws ImageException {
+		if ((numComponents >> 24) != 0) {
+			throw new ImageException("Too many labels to make bufferedImage.");
+		}
+
+		BufferedImage destImage = new BufferedImage(width, height,
+				BufferedImage.TYPE_INT_RGB);
+		WritableRaster destRaster = destImage.copyData(null);
+		DataBufferInt destBufInt = (DataBufferInt) (destRaster.getDataBuffer());
+		int[] destArray = destBufInt.getData();
+
+		// int pixel = 0;
+		int k = 0;
+		for (int j = 0; j < height; j++) {
+			for (int i = 0; i < width; i++) {
+				destArray[k] = ColorUtil.distinguishableColor(label[j][i]);
+				k++;
+			}
+		}
+
+		destImage.setData(destRaster);
+		return (destImage);
+	}
+
+	public void dump(PrintStream _ps, boolean _printLabel) {
+		PrintWriter pw = new PrintWriter(_ps, true);
+		dump(pw, _printLabel);
+	}
+
+	public void dump(PrintWriter _pw, boolean _printLabel) {
+		if (_printLabel)
+			dumpLabel(_pw);
+		else
+			dumpComponents(_pw);
+	}
+
+	public void dumpLabel(PrintStream _ps) {
+		PrintWriter pw = new PrintWriter(_ps, true);
+		dumpLabel(pw);
+	}
+
+	public void dumpLabel(PrintWriter _pw) {
+		_pw.println("-------------------------------");
+		_pw.println("Dumping a labeledImage");
+		_pw.println("Width = " + width + ", Height = " + height);
+		for (int j = 0; j < height; j++) {
+			StringBuffer sb = new StringBuffer();
+			for (int i = 0; i < width; i++) {
+				if (label[j][i] == 0)
+					sb.append(".");
+				else
+					sb.append("" + (label[j][i] % 10));
+			}
+			_pw.println(sb.toString());
+		}
+		_pw.println("-------------------------------");
+	}
+
+	public void dumpComponents(PrintStream _ps) {
+		PrintWriter pw = new PrintWriter(_ps, true);
+		dumpComponents(pw);
+	}
+
+	public void dumpComponents(PrintWriter _pw) {
+		_pw.println("-------------------------------");
+		_pw.println("Dumping components");
+		_pw.println("# of components = " + numComponents);
+		for (int i = 0; i < numComponents; i++) {
+			dumpComponents(_pw, i);
+		}
+		_pw.println("-------------------------------");
+	}
+
+	public void dumpComponents(PrintStream _ps, int _i) {
+		PrintWriter pw = new PrintWriter(_ps, true);
+		dumpComponents(pw, _i);
+	}
+
+	public void dumpComponents(PrintWriter _pw, int _i) {
+		_pw.println("-----");
+		_pw.println("Components # = " + _i);
+		components[_i].dump(_pw);
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/LineSegment.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/LineSegment.java
new file mode 100644
index 0000000..60effc7
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/LineSegment.java
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision.image;
+
+public class LineSegment {
+	public static final short POINT = 0;
+	public static final short HORIZONTAL_LINE = 1;
+	public static final short VERTICAL_LINE = 2;
+	public static final short DIAGONAL_LINE = 3;
+
+	int x0; //upper/left
+	int y0; //upper/left
+	int x1;
+	int y1;
+
+	public LineSegment( int _x0, int _y0, int _x1, int _y1 ){
+		if( _x0 < _x1 ){
+			x0 = _x0;
+			y0 = _y0;
+			x1 = _x1;
+			y1 = _y1;
+		}
+		else if( _x0 > _x1 ){
+			x0 = _x1;
+			y0 = _y1;
+			x1 = _x0;
+			y1 = _y0;
+		}
+		else if( _y0 <= _y1 ){
+			x0 = _x0;
+			y0 = _y0;
+			x1 = _x1;
+			y1 = _y1;
+		}
+		else{
+			x0 = _x1;
+			y0 = _y1;
+			x1 = _x0;
+			y1 = _y0;
+		}
+	}
+	public LineSegment( Coord _co0, Coord _co1 ){
+		this( _co0.x, _co0.y, _co1.x, _co1.y );
+	}
+
+	public Coord getLeftPoint(){
+		return( new Coord( x0, y0 ));
+	}
+	public Coord getRightPoint(){
+		return( new Coord( x1, y1 ));
+	}
+	
+	public Coord getUpperPoint(){
+		if( y0 <= y1 ){
+			return( new Coord( x0, y0 ) );
+		}
+		else{
+			return( new Coord( x1, y1 ));
+		}
+	}
+	public Coord getLowerPoint(){
+		if( y0 > y1 ){
+			return( new Coord( x0, y0 ) );
+		}
+		else{
+			return( new Coord( x1, y1 ));
+		}
+	}
+	
+	public short getType(){
+		if( x0==x1 ){
+			if( y0==y1 ){
+				return( POINT );
+			}
+			else{
+				return( VERTICAL_LINE );
+			}
+		}
+		else{ // x0!=x1
+			if( y0==y1 ){
+				return( HORIZONTAL_LINE );
+			}
+			else{
+				return( DIAGONAL_LINE );
+			}
+		}
+	}
+	public boolean isPoint(){
+		return( (getType()==POINT) );
+	}
+	public boolean isVertical(){
+		return( (getType()==VERTICAL_LINE) );
+	}
+	public boolean isHorizontal(){
+		return( (getType()==HORIZONTAL_LINE) );
+	}
+	public boolean isDiagonal(){
+		return( (getType()==DIAGONAL_LINE) );
+	}
+	
+	// return number of pixels
+	public double getLength(){
+		int xDiff = x1-x0+1;
+		int yDiff = y1-y0+1;
+		if( x0 == x1 ){
+			return( (double)(Math.abs(yDiff)) );
+		}
+		else if( y0 == y1 ){
+			return( (double)(Math.abs(xDiff)) );
+		}
+		else{
+			return( Math.sqrt((double)(xDiff*xDiff + yDiff*yDiff)) );
+		}
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/Neighbor.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/Neighbor.java
new file mode 100644
index 0000000..4ed38f5
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/Neighbor.java
@@ -0,0 +1,110 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision.image;
+
+/*
+ * x4 x3 x2 x5 x0 x1 x6 x7 x8
+ * 
+ * x9 = x1
+ */
+public class Neighbor {
+	int[] x = new int[10];
+
+	public Neighbor() {
+	}
+
+	public Neighbor(BinaryImage _bi, int _i, int _j) {
+		int width = _bi.width;
+		int height = _bi.height;
+		if (_bi.data[_j][_i] != 0) {
+			x[0] = 1;
+		}
+		if (_i > 0) {
+			if (_j > 0 && _bi.data[_j - 1][_i - 1] != 0)
+				x[4] = 1;
+			if (_bi.data[_j][_i - 1] != 0)
+				x[5] = 1;
+			if (_j < height - 1 && _bi.data[_j + 1][_i - 1] != 0)
+				x[6] = 1;
+		}
+		if (_j > 0 && _bi.data[_j - 1][_i] != 0)
+			x[3] = 1;
+		if (_j < height - 1 && _bi.data[_j + 1][_i] != 0)
+			x[7] = 1;
+		if (_i < width - 1) {
+			if (_j > 0 && _bi.data[_j - 1][_i + 1] != 0)
+				x[2] = 1;
+			if (_bi.data[_j][_i + 1] != 0) {
+				x[1] = 1;
+				x[9] = 1;
+			}
+			if (_j < height - 1 && _bi.data[_j + 1][_i + 1] != 0)
+				x[8] = 1;
+		}
+	}
+
+	public Neighbor deepCopy() {
+		Neighbor nei = new Neighbor();
+		for (int i = 0; i < 10; i++) {
+			nei.x[i] = this.x[i];
+		}
+		return (nei);
+	}
+
+	public int numForeground4() {
+		return (x[1] + x[3] + x[5] + x[7]);
+	}
+
+	public int numForeground8() {
+		return (x[1] + x[2] + x[3] + x[4] + x[5] + x[6] + x[7] + x[8]);
+	}
+
+	public int numBackground4() {
+		return (4 - (x[1] + x[3] + x[5] + x[7]));
+	}
+
+	public int numBackground8() {
+		return (8 - (x[1] + x[2] + x[3] + x[4] + x[5] + x[6] + x[7] + x[8]));
+	}
+
+	// -1 -> target pixel = bg
+	public int connectivityNumber4() {
+		if (x[0] == 0)
+			return (-1);
+		int num = 0;
+		for (int i = 1; i <= 7; i += 2) { // i = 1,3,5,7
+			num += (x[i] - x[i] * x[i + 1] * x[i + 2]);
+		}
+		return (num);
+	}
+
+	// -1 -> target pixel = bg
+	public int connectivityNumber8() {
+		if (x[0] == 0)
+			return (-1);
+		int num = 0;
+		for (int i = 1; i <= 7; i += 2) { // i = 1,3,5,7
+			num += ((1 - x[i]) - (1 - x[i]) * (1 - x[i + 1]) * (1 - x[i + 2]));
+		}
+		return (num);
+	}
+
+	// -1 -> target pixel = bg
+	public int crossingNumber() {
+		if (x[0] == 0)
+			return (-1);
+		int num = 0;
+		for (int i = 1; i < 9; i++) {
+			num += x[i] * (1 - x[i + 1]);
+		}
+		return (num);
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/PageComponent.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/PageComponent.java
new file mode 100644
index 0000000..4fd01b6
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/PageComponent.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.image;
+
+public abstract class PageComponent {
+	public static final short UNDEFINED_TYPE = -1;
+	
+	public static final short CONTAINER_TYPE = 1;
+	public static final short CANDIDATE_CHARACTER_TYPE = 2; 
+	public static final short CANDIDATE_UNDERLINED_CHARACTER_TYPE = 3; 
+
+	public static final short SS_CHARACTER_TYPE = 4; // single fg/single bg
+	public static final short MS_CHARACTER_TYPE = 5; // multi fg /single bg
+	public static final short SM_CHARACTER_TYPE = 6; // single fg/multi bg
+	// public static final short MM_CHARACTER_TYPE = 7; // multi fg/multi bg (do not consider)
+
+	public static final short INTERIOR_IMAGE_TYPE = 10;
+	public static final short OTHER_TYPE = 100; // others
+
+	private PageImage pageImage = null;
+	int componentID;
+	short type;
+	public ConnectedComponent cc = null;
+	public Container container = null;
+	
+	public PageComponent( short _type, PageImage _pi ){
+		type = _type;
+		pageImage = _pi;
+	}
+
+	public PageImage getPageImage(){
+		return( pageImage );
+	}
+	public int getID(){
+		return( componentID );
+	}
+	public void setID( int _id ){
+		componentID = _id;
+	}
+	public short getType(){
+		return( type );
+	}
+	public void setType( short _type ){
+		type = _type;
+	}
+	public ConnectedComponent getConnectedComponent(){
+		return( cc );
+	}
+	public void setConnectedComponent( ConnectedComponent _cc ){
+		cc = _cc;
+	}
+	public Container getContainer(){
+		return( container );
+	}
+	public int getX(){
+		return( cc.left );
+	}
+	public int getY(){
+		return( cc.top );
+	}
+	public int getWidth(){
+		return( cc.shape.width );
+	}
+	public int getHeight(){
+		return( cc.shape.height );
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/PageImage.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/PageImage.java
new file mode 100644
index 0000000..00545da
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/PageImage.java
@@ -0,0 +1,972 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision.image;
+
+import java.awt.image.BufferedImage;
+import java.io.PrintWriter;
+import java.util.Vector;
+
+import org.eclipse.actf.model.ui.editor.ImagePositionInfo;
+import org.eclipse.actf.visualization.engines.lowvision.LowVisionCommon;
+import org.eclipse.actf.visualization.engines.lowvision.LowVisionType;
+import org.eclipse.actf.visualization.engines.lowvision.character.CandidateCharacter;
+import org.eclipse.actf.visualization.engines.lowvision.character.CandidateUnderlinedCharacter;
+import org.eclipse.actf.visualization.engines.lowvision.character.CharacterMS;
+import org.eclipse.actf.visualization.engines.lowvision.character.CharacterSM;
+import org.eclipse.actf.visualization.engines.lowvision.character.CharacterSS;
+import org.eclipse.actf.visualization.engines.lowvision.checker.CharacterChecker;
+import org.eclipse.actf.visualization.engines.lowvision.internal.util.DebugUtil;
+import org.eclipse.actf.visualization.engines.lowvision.io.ImageReader;
+import org.eclipse.actf.visualization.engines.lowvision.io.LowVisionIOException;
+import org.eclipse.actf.visualization.engines.lowvision.problem.LowVisionProblemException;
+import org.eclipse.actf.visualization.engines.lowvision.problem.LowVisionProblemGroup;
+import org.eclipse.actf.visualization.engines.lowvision.util.DecisionMaker;
+
+/*
+ * Rednered image of Web page
+ * 
+ */
+public class PageImage implements LowVisionCommon {
+	private static final boolean DO_CHECK_CHARACTERS = false;
+
+	private static final boolean DO_CHECK_IMAGES = true;
+
+	// private static final boolean DO_CHAR_TEST = false;
+
+	Int2D pixel = null;
+
+	int numContainers; // containers.length;
+
+	Container[] containers;
+
+	int numNonContainedCharacters; // nonContainedCharacters.length
+
+	CharacterSM[] nonContainedCharacters; // SM Char
+
+	boolean extractedFlag = false; //
+
+	ImagePositionInfo[] imagePositions = null;
+
+	boolean useImagePositions = false;
+
+	InteriorImage[] interiorImageArray = null;
+
+	int currentContainerID = 1;
+
+	int[][] containerMap = null;
+
+	// for debug (TBD move back into extractCharacters())
+	Vector<Container> containerVector = new Vector<Container>();
+
+	Vector<CandidateCharacter> candidateCharacterVector = new Vector<CandidateCharacter>();
+
+	Vector<CandidateUnderlinedCharacter> candidateUnderlinedCharacterVector = new Vector<CandidateUnderlinedCharacter>();
+
+	PrintWriter writer = null;
+
+	public PageImage() {
+	}
+
+	public PageImage(Int2D _i2d) {
+		this(_i2d, true);
+	}
+
+	public PageImage(Int2D _i2d, boolean _removeScrollBar) {
+		Int2D i2d = null;
+		if (_removeScrollBar) {
+			if (LowVisionCommon.REMOVE_SURROUNDINGS) {
+				try {
+					i2d = _i2d.cutMargin(LowVisionCommon.SURROUNDINGS_WIDTH);
+				} catch (ImageException ie) {
+					// ie.printStackTrace();
+					i2d = _i2d;
+				}
+			} else {
+				i2d = _i2d;
+			}
+			if (LowVisionCommon.REMOVE_SCROLL_BAR_AT_RIGHT) {
+				Int2D tmpI2d = new Int2D(i2d.width
+						- LowVisionCommon.SCROLL_BAR_WIDTH, i2d.height);
+				for (int j = 0; j < tmpI2d.height; j++) {
+					for (int i = 0; i < tmpI2d.width; i++) {
+						tmpI2d.data[j][i] = i2d.data[j][i];
+					}
+				}
+				i2d = tmpI2d;
+			}
+			if (LowVisionCommon.REMOVE_SCROLL_BAR_AT_BOTTOM) {
+				Int2D tmpI2d = new Int2D(i2d.width, i2d.height
+						- LowVisionCommon.SCROLL_BAR_WIDTH);
+				for (int j = 0; j < tmpI2d.height; j++) {
+					for (int i = 0; i < tmpI2d.width; i++) {
+						tmpI2d.data[j][i] = i2d.data[j][i];
+					}
+				}
+				i2d = tmpI2d;
+			}
+		} else {
+			i2d = _i2d;
+		}
+
+		pixel = i2d.deepCopy();
+		i2d = null;
+	}
+
+	public void init(BufferedImage _bi) throws ImageException {
+		pixel = ImageUtil.bufferedImageToInt2D(_bi);
+	}
+
+	// for debug
+	public static PageImage readFromFile(String _fileName)
+			throws LowVisionIOException {
+		BufferedImage bi = ImageReader.readBufferedImage(_fileName);
+		// PageImage pi = new PageImage( bi );
+		Int2D i2d = new Int2D(bi);
+		PageImage pi = new PageImage(i2d);
+		return (pi);
+	}
+
+	public int getWidth() {
+		return (pixel.width);
+	}
+
+	public int getHeight() {
+		return (pixel.height);
+	}
+
+	public int[][] getPixelData() {
+		return (pixel.data);
+	}
+
+	public BufferedImage getBufferedImage() {
+		return (ImageUtil.int2DToBufferedImage(pixel));
+	}
+
+	public Int2D getInt2D() {
+		return (pixel);
+	}
+
+	public void disposeInt2D() {
+		pixel = new Int2D(0, 0);
+	}
+
+	public int getNumContainers() {
+		return (numContainers);
+	}
+
+	public Container[] getContainers() {
+		return (containers);
+	}
+
+	public int getNumSMCharacters() {
+		return (numNonContainedCharacters);
+	}
+
+	public CharacterSM[] getSMCharacters() {
+		return (nonContainedCharacters);
+	}
+
+	public int getNumNonContainedCharacters() {
+		return numNonContainedCharacters;
+	}
+
+	public CharacterSM[] getNonContainedCharacters() {
+		return nonContainedCharacters;
+	}
+
+	public void setWriter(PrintWriter _pw) {
+		writer = _pw;
+	}
+
+	public ImagePositionInfo[] getInteriorImagePosition() {
+		return (imagePositions);
+	}
+
+	public void setInteriorImagePosition(ImagePositionInfo[] infoArray) {
+		if (infoArray != null) {
+			imagePositions = infoArray;
+		}
+	}
+
+	public boolean isInteriorImageArraySet() {
+		if (interiorImageArray == null || interiorImageArray.length == 0) {
+			return (false);
+		} else {
+			return (true);
+		}
+	}
+
+	/*
+	 * Estimate character/image positions in the PageImage.
+	 */
+	public void extractCharacters() throws ImageException {
+		if (DO_CHECK_CHARACTERS) {
+			extractAllCharacters();
+		}
+
+		if (DO_CHECK_IMAGES && imagePositions != null
+				&& imagePositions.length > 0) {
+			useImagePositions = true;
+
+			// for memory (create InteriorImages for each time (degrade
+			// performance))
+
+			// extractInteriorImages();
+		}
+	}
+
+	/*
+	 * Extract all images in the page by using position info from DOM.
+	 * 
+	 */
+	private void extractInteriorImages() {
+		if (imagePositions == null)
+			return;
+		int numImages = imagePositions.length;
+		Vector<InteriorImage> imageVector = new Vector<InteriorImage>();
+
+		if (LowVisionCommon.REMOVE_SURROUNDINGS) {
+			for (int k = 0; k < numImages; k++) {
+				ImagePositionInfo pos = imagePositions[k];
+				pos.setX(pos.getX() - LowVisionCommon.SURROUNDINGS_WIDTH);
+				if (pos.getX() < 0) {
+					pos.setX(0);
+				}
+				pos.setY(pos.getY() - LowVisionCommon.SURROUNDINGS_WIDTH);
+				if (pos.getY() < 0) {
+					pos.setY(0);
+				}
+			}
+		}
+
+		for (int k = 0; k < numImages; k++) {
+			ImagePositionInfo curPos = imagePositions[k];
+
+			// InteriorImagePosition contains all image info in the Web page.
+			// However, PageImage only contains a part of Web page in the case
+			// of partial image dump. So, select images within the dumped image.
+			if (!isFullyContained(curPos)) {
+				continue;
+			}
+
+			InteriorImage curIm = new InteriorImage(this, curPos);
+			imageVector.addElement(curIm);
+		}
+		int size = imageVector.size();
+		if (size > 0) {
+			interiorImageArray = new InteriorImage[size];
+			for (int k = 0; k < size; k++) {
+				interiorImageArray[k] = (InteriorImage) (imageVector
+						.elementAt(k));
+			}
+		}
+	}
+
+	private boolean isFullyContained(ImagePositionInfo _pos) {
+		if (_pos.getX() + _pos.getWidth() > this.getWidth()) {
+			return (false);
+		}
+		if (_pos.getY() + _pos.getHeight() > this.getHeight()) {
+			return (false);
+		}
+		return (true);
+	}
+
+	private void extractAllCharacters() throws ImageException {
+		if (extractedFlag) {
+			return;
+		}
+
+		// TODO more improvement
+
+		int numProcessedColors = 0;
+
+		containerMap = new int[pixel.height][pixel.width];
+
+		ColorHistogram histogram = ColorHistogram.makeColorHistogram(pixel);
+
+		/*
+		 * (1) estimate content type (container, char, etc.) from image by using
+		 * connected components (each major color)
+		 */
+		int len = histogram.getSize();
+		numProcessedColors = len;
+		ColorHistogramBin[] histoArray = histogram.getSortedArrayByOccurrence();
+		for (int i = 0; i < len; i++) {
+			if (histoArray[i].occurrence < THRESHOLD_MIN_OCCURRENCES) {
+				numProcessedColors = i;
+				break;
+			}
+		}
+
+		for (int i = 0; i < numProcessedColors; i++) {
+			int curColor = histoArray[i].color;
+			BinaryImage binaryByColor = new BinaryImage(pixel,
+					BinaryImage.METHOD_SPECIFY_FOREGROUND, curColor);
+
+			// connected components
+			LabeledImage curLabeledImage = new LabeledImage(binaryByColor,
+					LabeledImage.METHOD_8_CONNECTIVITY);
+
+			int numComponents = curLabeledImage.numComponents;
+			ConnectedComponent[] components = curLabeledImage.components;
+
+			for (int j = 0; j < numComponents; j++) {
+				ConnectedComponent cc = components[j];
+
+				short type = DecisionMaker.judgeComponentType(cc, this, true);
+
+				if (type == PageComponent.CONTAINER_TYPE) {
+					Container tmpContainer = new Container(this,
+							currentContainerID, cc, curColor);
+					containerVector.addElement(tmpContainer);
+					paintContainerMap(currentContainerID, cc);
+					currentContainerID++;
+				} else if (type == PageComponent.CANDIDATE_CHARACTER_TYPE) {
+					CandidateCharacter tmpC = new CandidateCharacter(this, cc,
+							curColor);
+					candidateCharacterVector.addElement(tmpC);
+				} else if (type == PageComponent.CANDIDATE_UNDERLINED_CHARACTER_TYPE) {
+					CandidateUnderlinedCharacter tmpU = new CandidateUnderlinedCharacter(
+							this, cc, curColor);
+					candidateUnderlinedCharacterVector.addElement(tmpU);
+				} else if (type == PageComponent.OTHER_TYPE) {
+					;
+				} else {
+					throw new ImageException("Unexpected type = " + type);
+				}
+			}
+		}
+
+		// end (1)
+
+		// mark out containerMap
+		fillContainerMap(currentContainerID);
+
+		/*
+		 * (2) Assign CharacterCandidates to Container
+		 */
+		int numCandChar = candidateCharacterVector.size();
+		for (int k = numCandChar - 1; k >= 0; k--) {
+			CandidateCharacter cChar = (CandidateCharacter) (candidateCharacterVector
+					.elementAt(k));
+			int w = cChar.cc.shape.width;
+			int i = 0;
+			for (; i < w; i++) {
+				if (cChar.cc.shape.data[0][i] != 0) {
+					break;
+				}
+			}
+			int id = containerMap[cChar.cc.top][cChar.cc.left + i];
+			if (id > 0) {// id of Container starts from 1
+
+				Container parentCont = containerVector.elementAt(id - 1);
+				cChar.setContainer(parentCont);
+				parentCont.candidateCharacterVector.addElement(cChar);
+				candidateCharacterVector.removeElementAt(k);
+			} // (id = 0) = does not belong to Container (= SM Char)
+		}
+		int numCandUnderChar = candidateUnderlinedCharacterVector.size();
+		for (int k = numCandUnderChar - 1; k >= 0; k--) {
+			CandidateUnderlinedCharacter cuChar = candidateUnderlinedCharacterVector
+					.elementAt(k);
+			int w = cuChar.cc.shape.width;
+			int i = 0;
+			for (; i < w; i++) {
+				if (cuChar.cc.shape.data[0][i] != 0) {
+					break;
+				}
+			}
+			int id = containerMap[cuChar.cc.top][cuChar.cc.left + i];
+			if (id > 0) {// id of Container starts from 1
+				Container parentCont = containerVector.elementAt(id - 1);
+				cuChar.setContainer(parentCont);
+				parentCont.candidateUnderlinedCharacterVector
+						.addElement(cuChar);
+				candidateUnderlinedCharacterVector.removeElementAt(k);
+			}// (id = 0) = does not belong to Container (= SM Char)
+		}
+
+		/*
+		 * Other character candidates (do not belong to Container)
+		 */
+		Vector tmpSMCharacterVector = makeSMCharacterVector(
+				candidateCharacterVector, candidateUnderlinedCharacterVector);
+		this.candidateCharacterVector.removeAllElements();
+		this.candidateUnderlinedCharacterVector.removeAllElements();
+		int tmpTmpSMVecSize = tmpSMCharacterVector.size();
+		for (int k = tmpTmpSMVecSize - 1; k >= 0; k--) {
+			CharacterSM tmpSM = (CharacterSM) (tmpSMCharacterVector
+					.elementAt(k));
+			if (!(DecisionMaker.isSMCharacter(tmpSM))) {
+				tmpSMCharacterVector.removeElementAt(k);
+			}
+		}
+		this.numNonContainedCharacters = tmpSMCharacterVector.size();
+		this.nonContainedCharacters = new CharacterSM[numNonContainedCharacters];
+		for (int k = 0; k < numNonContainedCharacters; k++) {
+			nonContainedCharacters[k] = (CharacterSM) (tmpSMCharacterVector
+					.elementAt(k));
+		}
+		tmpSMCharacterVector.removeAllElements();
+		tmpSMCharacterVector = null;
+
+		/*
+		 * (3) Container
+		 */
+		int numContainer = containerVector.size();
+		for (int k = 0; k < numContainer; k++) {
+			Container curCont = containerVector.elementAt(k);
+			int contW = curCont.cc.shape.width;
+			int contH = curCont.cc.shape.height;
+			int contX = curCont.cc.left;
+			int contY = curCont.cc.top;
+			int contColor = curCont.getColor();
+			BinaryImage contBin = new BinaryImage(contW, contH);
+
+			// Container (filled hole)
+			BinaryImage filledContBin = new BinaryImage(contW, contH);
+
+			// HashMap contMap = new HashMap();
+			// HashMap nonContMap = new HashMap();
+			// Object dummy = new Object();
+			for (int j = 0; j < contH; j++) {
+				for (int i = 0; i < contW; i++) {
+					int curPixel = pixel.data[j + contY][i + contX];
+					// distinguishable from container color?
+					try {
+						if (curPixel == contColor) {// same
+							contBin.data[j][i] = 1;
+						}
+						/*
+						 * //TODO recover this? else{ Integer curInt = new
+						 * Integer( curPixel ); if( contMap.get(curInt) != null ){ //
+						 * similar contBin.data[j][i] = 1; continue; } if(
+						 * nonContMap.get(curInt) != null ){ // differ continue; }
+						 * //first time if(DecisionMaker.distinguishableColors(
+						 * curPixel, contColor ) ){ // differ nonContMap.put(
+						 * curInt, dummy ); } else{ // similar
+						 * 
+						 * contBin.data[j][i] = 1; contMap.put( curInt, dummy ); } }
+						 */
+					} catch (Exception e) {
+						// e.printStackTrace();
+						throw new ImageException(
+								"An error occurred while making contBin.");
+					}
+
+					if (containerMap[j + contY][i + contX] == k + 1) {
+						filledContBin.data[j][i] = 1;
+					}
+				}
+			}
+			BinaryImage fgBin = BinaryImage.subtract(filledContBin, contBin);
+
+			// Find connected component
+			LabeledImage curLabImg = new LabeledImage(fgBin,
+					LabeledImage.METHOD_8_CONNECTIVITY);
+			int numComponents = curLabImg.numComponents;
+			if (numComponents == 0) {
+				continue;
+			}
+			ConnectedComponent[] components = curLabImg.components;
+
+			for (int l = numComponents - 1; l >= 0; l--) {
+				ConnectedComponent cc2 = components[l];
+				// convert to relative coordinates (Page)
+				cc2.setLeft(cc2.getLeft() + contX);
+				cc2.setTop(cc2.getTop() + contY);
+				if (collateCandidates(curCont, cc2)) {
+					// SS Char (or with underline)
+					continue;
+					// nothing to do here (already done in collateCandidates)
+				} else if (DecisionMaker.isMSCharacter(cc2)) {
+					int fg = -1;
+					if ((fg = getForegroundColor(cc2)) == -1) {
+						CharacterMS msc = new CharacterMS(this, cc2, curCont,
+								pixel);
+						curCont.msCharacterVector.addElement(msc);
+					} else {
+						/*
+						 * to handle character written by using minor color in
+						 * histogram
+						 */
+						short ssType = DecisionMaker.judgeComponentType(cc2,
+								this);
+						if (ssType == PageComponent.CANDIDATE_CHARACTER_TYPE) {
+							CharacterSS ssc = new CharacterSS(this, cc2,
+									curCont, fg);
+							curCont.ssCharacterVector.addElement(ssc);
+						} else if (ssType == PageComponent.CANDIDATE_UNDERLINED_CHARACTER_TYPE) {
+							CandidateUnderlinedCharacter cuc = new CandidateUnderlinedCharacter(
+									this, cc2, fg);
+							cuc.setContainer(curCont);
+							Vector sscVec = removeUnderlineAndGenerateSS(cuc);
+							for (int m = 0; m < sscVec.size(); m++) {
+								curCont.ssCharacterVector
+										.addElement((CharacterSS) (sscVec
+												.elementAt(m)));
+							}
+							sscVec.removeAllElements();
+						}
+					}
+				}
+			}
+
+			// remaining candidates -> SM Character
+			// TODO check more
+			Vector tmpVec = makeSMCharacterVector(
+					curCont.candidateCharacterVector,
+					curCont.candidateUnderlinedCharacterVector);
+			curCont.candidateCharacterVector.removeAllElements();
+			curCont.candidateUnderlinedCharacterVector.removeAllElements();
+			int tmpVecSize = tmpVec.size();
+			for (int l = tmpVecSize - 1; l >= 0; l--) {
+				CharacterSM smc = (CharacterSM) (tmpVec.elementAt(l));
+				if (smc.getForegroundColor() == curCont.getColor()) {
+					// remove elements (same color with Container)
+					// (e.g., hole of 'A','R' etc.)
+					tmpVec.removeElementAt(l);
+				} else if (includingMSCharacter(smc, curCont) != null) {
+					// remove elements contained in MS Char (*)
+					tmpVec.removeElementAt(l);
+				} else {
+					// check SS Character which has similar fg/bg color
+					// ((1)->OK but (3)->NG)
+					if (getBackgroundColor(smc.cc) > -1) {
+						CharacterSS ssc = new CharacterSS(this, smc.cc,
+								smc.container, smc.getForegroundColor());
+						curCont.ssCharacterVector.addElement(ssc);
+						tmpVec.removeElementAt(l);
+					}
+				}
+			}
+
+			/*
+			 * Check very small MS Char. Need to do it after (*)
+			 */
+			int msVecSize = curCont.msCharacterVector.size();
+			for (int l = msVecSize - 1; l >= 0; l--) {
+				CharacterMS curMS = (CharacterMS) (curCont.msCharacterVector
+						.elementAt(l));
+				if (DecisionMaker.isTooSmallThinedMSCharacter(curMS)) {
+					curCont.msCharacterVector.removeElementAt(l);
+				}
+			}
+
+			curCont.ssVector2Array(); // ssCharacterVector->ssCharacters
+
+			curCont.msVector2Array(); // msCharacterVector->msCharacters
+
+			int tmptmpVecSize = tmpVec.size();
+			for (int l = tmptmpVecSize - 1; l >= 0; l--) {
+				CharacterSM tmpSM = (CharacterSM) (tmpVec.elementAt(l));
+				if (!(DecisionMaker.isSMCharacter(tmpSM))) {
+					tmpVec.removeElementAt(l);
+				}
+			}
+
+			curCont.numSMCharacters = tmpVec.size();
+			curCont.smCharacters = new CharacterSM[curCont.numSMCharacters];
+			for (int l = 0; l < curCont.numSMCharacters; l++) {
+				curCont.smCharacters[l] = (CharacterSM) (tmpVec.elementAt(l));
+			}
+			tmpVec.removeAllElements();
+			tmpVec = null;
+		}
+		// end (3)
+
+		// remove Containers without Character
+		for (int k = numContainer - 1; k >= 0; k--) {
+			Container curCont = containerVector.elementAt(k);
+			if (curCont.numSSCharacters == 0 && curCont.numMSCharacters == 0
+					&& curCont.numSMCharacters == 0) {
+				containerVector.removeElementAt(k);
+			}
+		}
+		numContainers = containerVector.size();
+		containers = new Container[numContainers];
+		for (int k = 0; k < numContainers; k++) {
+			containers[k] = containerVector.elementAt(k);
+		}
+		containerVector.removeAllElements();
+
+		extractedFlag = true;
+
+	}
+
+	// paint Container into ContainerMap
+	private void paintContainerMap(int _id, ConnectedComponent _cc) {
+		int w = _cc.shape.width;
+		int h = _cc.shape.height;
+		for (int j = 0; j < h; j++) {
+			for (int i = 0; i < w; i++) {
+				if (_cc.shape.data[j][i] != 0) {
+					containerMap[_cc.top + j][_cc.left + i] = _id;
+				}
+			}
+		}
+	}
+
+	/*
+	 * fill hole of ContainerMap
+	 */
+	private void fillContainerMap(int _lastID) throws ImageException {
+		// ID=0 -> not in Container
+		for (int i = 1; i < _lastID; i++) {// Container ID starts from 1
+			fillOneContainer(i);
+		}
+	}
+
+	private void fillOneContainer(int _id) throws ImageException {
+		Container curCont = (Container) (containerVector.elementAt(_id - 1));
+		int curX0 = curCont.cc.left;
+		int curY0 = curCont.cc.top;
+		int curX1 = curX0 + curCont.cc.shape.width;
+		int curY1 = curY0 + curCont.cc.shape.height;
+
+		// left boundary=1,
+		// right boundary=2,
+		// both (1 pixel line)=3,
+		// others=0
+		int[][] workMap = new int[pixel.height][pixel.width];
+
+		for (int j = curY0; j < curY1; j++) {
+			// left boundary
+			boolean mostLeftFound = false;
+			boolean otherContainerLeft = false;
+			for (int i = curX0; i < curX1; i++) {
+				if (containerMap[j][i] == _id) {
+					if (!mostLeftFound) {
+						workMap[j][i] = 1;
+						mostLeftFound = true;
+						otherContainerLeft = false;
+					} else if (otherContainerLeft) {
+						workMap[j][i] = 1;
+						otherContainerLeft = false;
+					}
+				} else if (containerMap[j][i] > 0) {
+					otherContainerLeft = true;
+				}
+			}
+			// right boundary
+			boolean mostRightFound = false;
+			boolean otherContainerRight = false;
+			for (int i = curX1 - 1; i >= curX0; i--) {
+				if (containerMap[j][i] == _id) {
+					if (!mostRightFound) {
+						if (workMap[j][i] != 1) {
+							workMap[j][i] = 2;
+						} else {
+							workMap[j][i] = 3;
+						}
+						mostRightFound = true;
+						otherContainerRight = false;
+					} else if (otherContainerRight) {
+						if (workMap[j][i] != 1) {
+							workMap[j][i] = 2;
+						} else {
+							workMap[j][i] = 3;
+						}
+						otherContainerRight = false;
+					}
+				} else if (containerMap[j][i] > 0) {
+					otherContainerRight = true;
+				}
+			}
+
+			// fill between left/right boundary
+			boolean inTheContainer = false;
+			for (int i = curX0; i < curX1; i++) {
+				if (workMap[j][i] == 0 && inTheContainer) {
+					// debug (TBD remove this if sentence)
+					if (containerMap[j][i] != 0 && containerMap[j][i] != _id) {
+						DebugUtil.outMsg(this, "i = " + i + ", j = " + j);
+						DebugUtil.outMsg(this, "Dumping containerMap");
+						for (int k = 0; k < pixel.width; k++) {
+							System.err.print("" + containerMap[j][k]);
+						}
+						System.err.println("");
+						DebugUtil.outMsg(this, "Dumping workMap");
+						for (int k = 0; k < pixel.width; k++) {
+							System.err.print("" + workMap[j][k]);
+						}
+						System.err.println("");
+						throw new ImageException("filling error 0: id = " + _id);
+					}
+					containerMap[j][i] = _id;
+				} else if (workMap[j][i] == 1) {
+					// debug (TBD remove this if sentence)
+					if (inTheContainer) {
+						throw new ImageException("filling error 1: id = " + _id);
+					}
+					inTheContainer = true;
+				} else if (workMap[j][i] == 2) {
+					inTheContainer = false;
+				}
+			}
+		}
+	}
+
+	/*
+	 * Collate candidates from (1) and (3) (-> SS Character)
+	 */
+	private boolean collateCandidates(Container _cont, ConnectedComponent _cc)
+			throws ImageException {
+		int numCand = _cont.candidateCharacterVector.size();
+		for (int k = numCand - 1; k >= 0; k--) {
+			CandidateCharacter cChar = _cont.candidateCharacterVector
+					.elementAt(k);
+			if (_cc.equals(cChar.cc)) {
+				// (confirmed) SS Character
+				CharacterSS ssc = new CharacterSS(cChar);
+				_cont.ssCharacterVector.addElement(ssc);
+				_cont.candidateCharacterVector.removeElementAt(k);
+				return (true);
+			}
+		}
+		int numUCand = _cont.candidateUnderlinedCharacterVector.size();
+		for (int k = numUCand - 1; k >= 0; k--) {
+			CandidateUnderlinedCharacter cuChar = _cont.candidateUnderlinedCharacterVector
+					.elementAt(k);
+			if (_cc.equals(cuChar.cc)) {
+				// (confirmed) Underlined SS Character
+				Vector sscVec = removeUnderlineAndGenerateSS(cuChar);
+				for (int l = 0; l < sscVec.size(); l++) {
+					_cont.ssCharacterVector.addElement((CharacterSS) (sscVec
+							.elementAt(l)));
+				}
+				_cont.candidateUnderlinedCharacterVector.removeElementAt(k);
+				return (true);
+			}
+		}
+		return (false);
+	}
+
+	/*
+	 * Returns fg color of connected component (int) color: single fg color -1:
+	 * multiple fg color/no fg color
+	 */
+	private int getForegroundColor(ConnectedComponent _cc) {
+		int fg = -1;
+		for (int j = 0; j < _cc.shape.height; j++) {
+			for (int i = 0; i < _cc.shape.width; i++) {
+				if (_cc.shape.data[j][i] != 0) {
+					if (fg == -1) {
+						fg = pixel.data[j + _cc.top][i + _cc.left];
+					} else if (fg != pixel.data[j + _cc.top][i + _cc.left]) {
+						return (-1);
+					}
+				}
+			}
+		}
+		return (fg);
+	}
+
+	/*
+	 * Returns bg color of connected component (int) color: single bg color -1:
+	 * multiple bg color/no bg color
+	 */
+	private int getBackgroundColor(ConnectedComponent _cc) {
+		int bg = -1;
+		for (int j = 0; j < _cc.shape.height; j++) {
+			for (int i = 0; i < _cc.shape.width; i++) {
+				if (_cc.shape.data[j][i] == 0) {
+					if (bg == -1) {
+						bg = pixel.data[j + _cc.top][i + _cc.left];
+					} else if (bg != pixel.data[j + _cc.top][i + _cc.left]) {
+						return (-1);
+					}
+				}
+			}
+		}
+		return (bg);
+	}
+
+	// Create SM Characters from candidateCharacter/candidateUnderlinedCharacter
+	private Vector makeSMCharacterVector(Vector<CandidateCharacter> _cVec,
+			Vector<CandidateUnderlinedCharacter> _uVec) throws ImageException {
+		Vector<CharacterSM> tmpVec = new Vector<CharacterSM>();
+		int numRemainingChar = _cVec.size();
+		for (int k = 0; k < numRemainingChar; k++) {
+			CandidateCharacter cChar = _cVec.elementAt(k);
+			CharacterSM smc = new CharacterSM(cChar, pixel);
+			tmpVec.addElement(smc);
+		}
+
+		int numRemainingUnderlinedChar = _uVec.size();
+		for (int k = 0; k < numRemainingUnderlinedChar; k++) {
+			CandidateUnderlinedCharacter cuChar = _uVec.elementAt(k);
+			Vector smcVec = removeUnderlineAndGenerateSM(cuChar);
+			for (int l = 0; l < smcVec.size(); l++) {
+				tmpVec.addElement((CharacterSM) (smcVec.elementAt(l)));
+			}
+		}
+
+		return (tmpVec);
+	}
+
+	// target SM Char is contained within MS Char in the Container?
+	private CharacterMS includingMSCharacter(CharacterSM _smc, Container _cont) {
+		for (int k = 0; k < _cont.msCharacterVector.size(); k++) {
+			CharacterMS curMS = (CharacterMS) (_cont.msCharacterVector
+					.elementAt(k));
+			if (_smc.cc.isIncludedBy(curMS.cc)) {
+				return (curMS);
+			}
+		}
+		return (null);
+	}
+
+	public LowVisionProblemGroup[] checkCharacters(LowVisionType _lvType)
+			throws ImageException, LowVisionProblemException {
+		LowVisionProblemGroup[] charProblemGroupArray = null;
+		LowVisionProblemGroup[] imgProblemGroupArray = null;
+		LowVisionProblemGroup[] answerArray = null;
+
+		if (DO_CHECK_CHARACTERS) {
+			CharacterChecker charChecker = new CharacterChecker(this);
+			charProblemGroupArray = charChecker.checkAllCharacters(_lvType);
+		}
+
+		if (DO_CHECK_IMAGES && useImagePositions) {
+
+			// for memory (create InteriorImages for each time (degrade
+			// performance))
+			extractInteriorImages();
+
+			imgProblemGroupArray = checkInteriorImages(_lvType);
+
+			// for memory
+			interiorImageArray = null;
+		}
+
+		if (charProblemGroupArray == null) {
+			if (imgProblemGroupArray == null) {
+				answerArray = new LowVisionProblemGroup[0];
+			} else {
+				answerArray = imgProblemGroupArray;
+			}
+		} else {
+			if (imgProblemGroupArray == null) {
+				answerArray = charProblemGroupArray;
+			} else {
+				int charLen = charProblemGroupArray.length;
+				int imgLen = imgProblemGroupArray.length;
+				int allLen = charLen + imgLen;
+				LowVisionProblemGroup[] allProblemGroupArray = new LowVisionProblemGroup[allLen];
+				for (int i = 0; i < charLen; i++) {
+					allProblemGroupArray[i] = charProblemGroupArray[i];
+				}
+				for (int i = 0; i < imgLen; i++) {
+					allProblemGroupArray[charLen + i] = imgProblemGroupArray[i];
+				}
+				answerArray = allProblemGroupArray;
+			}
+		}
+
+		return (answerArray);
+	}
+
+	private LowVisionProblemGroup[] checkInteriorImages(LowVisionType _lvType)
+			throws ImageException {
+		if (!useImagePositions) {
+			return (new LowVisionProblemGroup[0]);
+		}
+
+		Vector<LowVisionProblemGroup> problemVector = new Vector<LowVisionProblemGroup>();
+
+		int numInteriorImages = 0;
+		if (interiorImageArray != null && interiorImageArray.length > 0) {
+			numInteriorImages = interiorImageArray.length;
+		}
+		for (int k = 0; k < numInteriorImages; k++) {
+			InteriorImage curIm = interiorImageArray[k];
+
+			LowVisionProblemGroup[] probArray = curIm.checkColors(_lvType);
+			if (probArray != null) {
+				int numProb = probArray.length;
+				for (int l = 0; l < numProb; l++) {
+					problemVector.addElement(probArray[l]);
+				}
+			}
+		}
+
+		int size = problemVector.size();
+		if (size > 0) {
+			LowVisionProblemGroup[] allProbArray = new LowVisionProblemGroup[size];
+			for (int k = 0; k < size; k++) {
+				allProbArray[k] = problemVector.elementAt(k);
+			}
+			problemVector = null;
+			return (allProbArray);
+		} else {
+			problemVector = null;
+			return (new LowVisionProblemGroup[0]);
+		}
+	}
+
+	private LabeledImage removeUnderlineAndCCL(
+			CandidateUnderlinedCharacter _cuChar) throws ImageException {
+		BinaryImage origImage = _cuChar.cc.shape;
+		BinaryImage lineImage = origImage.drawUnderline();
+
+		BinaryImage removedImage = origImage.subtract(lineImage);
+		LabeledImage li = new LabeledImage(removedImage,
+				LabeledImage.METHOD_8_CONNECTIVITY);
+
+		return (li);
+	}
+
+	private Vector removeUnderlineAndGenerateSS(
+			CandidateUnderlinedCharacter _cuChar) throws ImageException {
+		Vector<CharacterSS> ssVec = new Vector<CharacterSS>();
+		int offsetX = _cuChar.cc.left;
+		int offsetY = _cuChar.cc.top;
+		short conn = _cuChar.cc.connectivity;
+		LabeledImage li = removeUnderlineAndCCL(_cuChar);
+		int numCC = li.numComponents;
+		for (int k = 0; k < numCC; k++) {
+			ConnectedComponent cc = li.components[k];
+			cc.left += offsetX;
+			cc.top += offsetY;
+			cc.connectivity = conn;
+			if (DecisionMaker.judgeComponentType(cc, this) == PageComponent.CANDIDATE_CHARACTER_TYPE) {
+				CharacterSS ssc = new CharacterSS(this, cc, _cuChar.container,
+						_cuChar.getForegroundColor());
+				ssVec.addElement(ssc);
+			}
+		}
+		return (ssVec);
+	}
+
+	private Vector removeUnderlineAndGenerateSM(
+			CandidateUnderlinedCharacter _cuChar) throws ImageException {
+		Vector<CharacterSM> smVec = new Vector<CharacterSM>();
+		int offsetX = _cuChar.cc.left;
+		int offsetY = _cuChar.cc.top;
+		short conn = _cuChar.cc.connectivity;
+		LabeledImage li = removeUnderlineAndCCL(_cuChar);
+		int numCC = li.numComponents;
+		for (int k = 0; k < numCC; k++) {
+			ConnectedComponent cc = li.components[k];
+			cc.left += offsetX;
+			cc.top += offsetY;
+			cc.connectivity = conn;
+			if (DecisionMaker.judgeComponentType(cc, this) == PageComponent.CANDIDATE_CHARACTER_TYPE) {
+				CharacterSM smc = new CharacterSM(this, cc, _cuChar.container,
+						_cuChar.getForegroundColor(), pixel);
+				smVec.addElement(smc);
+			}
+		}
+		return (smVec);
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/PageImageDebugUtil.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/PageImageDebugUtil.java
new file mode 100644
index 0000000..122ec05
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/PageImageDebugUtil.java
@@ -0,0 +1,175 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision.image;
+
+import org.eclipse.actf.visualization.engines.lowvision.character.CharacterSS;
+import org.eclipse.actf.visualization.engines.lowvision.color.ColorUtil;
+import org.eclipse.actf.visualization.engines.lowvision.internal.util.DebugUtil;
+
+public class PageImageDebugUtil {
+	private PageImage pageImage;
+	
+	PageImageDebugUtil(PageImage pageImage){
+		this.pageImage = pageImage;
+	}
+
+	public void paintOnePageComponent(PageComponent _com, int[][] _image,
+			int _color) {
+		int startX = _com.cc.left;
+		int startY = _com.cc.top;
+		int paintW = _com.cc.shape.width;
+		int paintH = _com.cc.shape.height;
+
+		for (int j = 0; j < paintH; j++) {
+			for (int i = 0; i < paintW; i++) {
+				if (_com.cc.shape.data[j][i] != 0) {
+					_image[j + startY][i + startX] = _color;
+				}
+			}
+		}
+	}
+
+	public int[][] paintContainers(int[][] _image, int _color) {
+		if (pageImage.numContainers == 0) {
+			DebugUtil.errMsg(this, "There are no containers.");
+			return (null);
+		}
+		DebugUtil.debugMsg(null, "# of containers = " + pageImage.numContainers,
+				"CONTAINER");
+		for (int i = 0; i < pageImage.numContainers; i++) {
+			Container curContainer = pageImage.containers[i];
+			paintOnePageComponent(curContainer, _image, _color);
+		}
+
+		return (_image);
+	}
+
+	public Int2D showRepaintedContainerMap() {
+		Int2D i2d = new Int2D(pageImage.pixel.width, pageImage.pixel.height);
+		for (int j = 0; j < pageImage.pixel.height; j++) {
+			for (int i = 0; i < pageImage.pixel.width; i++) {
+				i2d.data[j][i] = ColorUtil
+						.distinguishableColor(pageImage.containerMap[j][i]);
+			}
+		}
+		return (i2d);
+	}
+
+	public Int2D showAllSSCharacters() {
+		return (showAllSSCharacters(0x00ff0000));
+	}
+
+	public Int2D showAllSSCharacters(int _color) {
+		Int2D i2d = new Int2D(pageImage.pixel.width, pageImage.pixel.height);
+		for (int k = 0; k < pageImage.containerVector.size(); k++) {
+			i2d = showSSCharactersInOneContainer(i2d, k, _color);
+		}
+
+		return (i2d);
+	}
+
+	public Int2D showSSCharactersInOneContainer(Int2D _i2d, int _contIndex,
+			int _color) {
+		Container curCont = (Container) (pageImage.containerVector.elementAt(_contIndex));
+		for (int l = 0; l < curCont.ssCharacterVector.size(); l++) {
+			CharacterSS ssc = (CharacterSS) (curCont.ssCharacterVector
+					.elementAt(l));
+			ConnectedComponent cc = ssc.cc;
+			for (int j = 0; j < cc.shape.height; j++) {
+				for (int i = 0; i < cc.shape.width; i++) {
+					if (cc.shape.data[j][i] != 0) {
+						_i2d.data[j + cc.top][i + cc.left] = _color;
+					}
+				}
+			}
+		}
+		return (_i2d);
+	}
+
+	public Int2D showAllCharacters() {
+		return (showAllCharacters(0x00ff0000, 0x0000ff00, 0x000000ff,
+				0x00ffff00));
+	}
+
+	public Int2D showAllCharacters(int _ssColor, int _msColor, int _smColor1,
+			int _smColor2) {
+		Int2D i2d = new Int2D(pageImage.pixel.width, pageImage.pixel.height);
+		DebugUtil.debugMsg(this, "numContainers = " + pageImage.numContainers,
+				"CONTAINER");
+		for (int k = 0; k < pageImage.numContainers; k++) {
+			Container cont = pageImage.containers[k];
+			i2d = showCharactersInOneContainer(i2d, cont, _ssColor, _msColor,
+					_smColor1);
+		}
+
+		for (int k = 0; k < pageImage.numNonContainedCharacters; k++) {
+			i2d = pageImage.nonContainedCharacters[k].cc.drawShape(i2d, _smColor2);
+		}
+
+		return (i2d);
+	}
+
+	public Int2D showCharactersInOneContainer(Int2D _i2d, Container _cont,
+			int _ssColor, int _msColor, int _smColor) {
+		for (int l = 0; l < _cont.numSSCharacters; l++) {
+			_i2d = _cont.ssCharacters[l].cc.drawShape(_i2d, _ssColor);
+		}
+		for (int l = 0; l < _cont.numMSCharacters; l++) {
+			_i2d = _cont.msCharacters[l].cc.drawShape(_i2d, _msColor);
+		}
+		for (int l = 0; l < _cont.numSMCharacters; l++) {
+			_i2d = _cont.smCharacters[l].cc.drawShape(_i2d, _smColor);
+		}
+		return (_i2d);
+	}
+
+	public Int2D showAllThinedCharacters() throws ImageException {
+		return (showAllThinedCharacters(0x00ff0000, 0x0000ff00, 0x000000ff,
+				0x00ffff00));
+	}
+
+	public Int2D showAllThinedCharacters(int _ssColor, int _msColor,
+			int _smColor1, int _smColor2) throws ImageException {
+		Int2D i2d = new Int2D(pageImage.pixel.width, pageImage.pixel.height);
+		DebugUtil.debugMsg(this, "numContainers = " + pageImage.numContainers,
+				"CONTAINER");
+		for (int k = 0; k < pageImage.numContainers; k++) {
+			Container cont = pageImage.containers[k];
+			i2d = showThinedCharactersInOneContainer(i2d, cont, _ssColor,
+					_msColor, _smColor1);
+		}
+
+		for (int k = 0; k < pageImage.numNonContainedCharacters; k++) {
+			i2d = pageImage.nonContainedCharacters[k].cc.thinning().drawShape(i2d,
+					_smColor2);
+		}
+
+		return (i2d);
+	}
+
+	public Int2D showThinedCharactersInOneContainer(Int2D _i2d,
+			Container _cont, int _ssColor, int _msColor, int _smColor)
+			throws ImageException {
+		for (int l = 0; l < _cont.numSSCharacters; l++) {
+			_i2d = _cont.ssCharacters[l].cc.thinning()
+					.drawShape(_i2d, _ssColor);
+		}
+		for (int l = 0; l < _cont.numMSCharacters; l++) {
+			_i2d = _cont.msCharacters[l].cc.thinning()
+					.drawShape(_i2d, _msColor);
+		}
+		for (int l = 0; l < _cont.numSMCharacters; l++) {
+			_i2d = _cont.smCharacters[l].cc.thinning()
+					.drawShape(_i2d, _smColor);
+		}
+		return (_i2d);
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/SimulatedPageImage.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/SimulatedPageImage.java
new file mode 100644
index 0000000..a543752
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/SimulatedPageImage.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.image;
+
+import java.awt.image.BufferedImage;
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+
+import org.eclipse.actf.visualization.engines.lowvision.LowVisionException;
+import org.eclipse.actf.visualization.engines.lowvision.LowVisionType;
+import org.eclipse.actf.visualization.engines.lowvision.io.ImageReader;
+import org.eclipse.actf.visualization.engines.lowvision.io.LowVisionIOException;
+import org.eclipse.actf.visualization.engines.lowvision.operator.LowVisionFilter;
+
+/*
+ * Contain simulation result
+ */
+public class SimulatedPageImage extends PageImage {
+	PageImage original = null; // original image
+
+	LowVisionType type = null; // type of simulation
+
+	public SimulatedPageImage(PageImage _pi, LowVisionType _type)
+			throws ImageException {
+		original = _pi;
+		type = _type;
+		LowVisionFilter lvFilter = new LowVisionFilter(type);
+		BufferedImage bi = null;
+		try {
+			BufferedImage tmpBufIm = original.getBufferedImage();
+			bi = lvFilter.filter(tmpBufIm, null);
+			tmpBufIm = null;
+		} catch (LowVisionException lve) {
+			// lve.printStackTrace();
+			throw new ImageException(
+					"The original PageImage cannot be filtered.");
+		}
+		init(bi);
+		bi = null;
+	}
+
+	// for debug
+	public static SimulatedPageImage readFromFile(
+			String _originalImageFilePath, String _sequenceFilePath)
+			throws ImageException, LowVisionIOException {
+		Int2D i2d = ImageUtil.bufferedImageToInt2D(ImageReader
+				.readBufferedImage(_originalImageFilePath));
+		PageImage pi = new PageImage(i2d);
+		FileReader fr = null;
+		try {
+			fr = new FileReader(_sequenceFilePath);
+		} catch (FileNotFoundException fnfe) {
+			// fnfe.printStackTrace();
+			throw new LowVisionIOException("File: " + _sequenceFilePath
+					+ " cannot be found.");
+		}
+		SimulatedPageImage spi = null;
+		try {
+			LowVisionType lvType = new LowVisionType(new BufferedReader(fr));
+			spi = new SimulatedPageImage(pi, lvType);
+		} catch (LowVisionException se) {
+			// se.printStackTrace();
+			throw new ImageException(
+					"SequenceException occurred in readFromFile()");
+		}
+		return (spi);
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/Topology.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/Topology.java
new file mode 100644
index 0000000..7e45133
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/Topology.java
@@ -0,0 +1,373 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision.image;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.util.Vector;
+
+/*
+ * Show topology of connected component (thinning, 8 connected)
+ */
+public class Topology{
+    // type of node
+    static final short TYPE_INTERIOR = 0; 
+    static final short TYPE_EDGE = 1; 
+    static final short TYPE_CONNECTED = 2; 
+    static final short TYPE_BRANCHING = 3; 
+    static final short TYPE_CROSSING = 4; 
+
+    // Left side of 'A' might have 2/3 connected component
+    //  #      #
+    //  #      #
+    //  2##     3##
+    // #       #
+    // #      #
+    //
+    // So, use crossing number to detect shape change.
+    
+    ConnectedComponent component;
+    int width;
+    int height;
+    int numNodes = 0;     // number of nodes (connection 0,1,3,4 ( +2(edge)))
+    Node[] nodes = null;  // node array (connection 0,1,3,4)
+    int numInterior = 0;  
+    int numEdges = 0;     
+    int numBranches = 0;  
+    int numCrosses = 0;   
+    int[][] distance = null;     
+    int count = 0; // number of fg pixel
+
+    public Topology( ConnectedComponent _cc ) throws ImageException{
+    	this( _cc, false );
+    }
+
+    public Topology( ConnectedComponent _cc, boolean _calcDistance ) throws ImageException{
+		component = _cc;
+		width = component.shape.width;
+		height = component.shape.height;
+		BinaryImage bi = component.shape;
+	
+		Vector<Node> tmpNodes = new Vector<Node>();
+		int topPosition = -1;    
+		int bottomPosition = -1; 
+		for( int j=0; j<height; j++ ){
+		    for( int i=0; i<width; i++ ){
+				if( bi.data[j][i] != 0 ){
+					count++; 
+				    if( topPosition == -1 ) 
+						topPosition = j;
+				    bottomPosition = j;
+				    Neighbor nei = new Neighbor( bi, i, j );
+				    // int cn = nei.connectivityNumber8(); 
+					int cn = nei.crossingNumber(); 
+				    if( cn == 1 ){
+						numNodes++;
+						numEdges++;
+						Node n = new Node( i, j, TYPE_EDGE );
+						tmpNodes.addElement( n );
+				    }
+				    else if( cn == 3 ){
+						numNodes++;
+						numBranches++;
+						Node n = new Node( i, j, TYPE_BRANCHING );
+						tmpNodes.addElement( n );
+				    }
+				    else if( cn == 4 ){
+						numNodes++;
+						numCrosses++;
+						Node n = new Node( i, j, TYPE_CROSSING );
+						tmpNodes.addElement( n );
+				    }
+				    else if( cn == 0 ){ 
+						numNodes++;
+						numInterior++;
+						Node n = new Node( i, j, TYPE_INTERIOR );
+						tmpNodes.addElement( n );
+				    }
+				}
+		    }
+		}
+
+		if( topPosition == -1 ){
+			return;
+		}
+	
+		// add top/bottom node (to support chars like 'O')
+		boolean existTop = false;
+		boolean existBottom = false;
+		for( int i=0; i<numNodes; i++ ){
+		    Node n = (Node)(tmpNodes.elementAt(i));
+		    if( n.y == topPosition )
+				existTop = true;
+		    if( n.y == bottomPosition )
+				existBottom = true;
+		}
+		Node topNode = null;
+		Node bottomNode = null;
+		if( !existTop ){
+		    for( int i=0; i<width; i++ ){
+				if( bi.data[topPosition][i] != 0 ){
+				    Neighbor nei = new Neighbor( bi, i, topPosition );
+				    // int cn = nei.connectivityNumber8();
+					int cn = nei.crossingNumber();
+				    if( cn == 2 ){
+						numNodes++;
+						topNode = new Node( i, topPosition, TYPE_CONNECTED );
+						break;
+				    }
+				    else{
+						throw new ImageException( "Unknown type" );
+				    }
+				}
+		    }
+		}
+		if( !existBottom ){
+		    for( int i=width-1; i>=0; i-- ){
+				if( bi.data[bottomPosition][i] != 0 ){
+				    Neighbor nei = new Neighbor( bi, i, bottomPosition );
+				    // int cn = nei.connectivityNumber8();
+					int cn = nei.crossingNumber();
+				    if( cn == 2 ){
+						numNodes++;
+						bottomNode = new Node( i, bottomPosition, TYPE_CONNECTED );
+						break;
+				    }
+				    else{
+						throw new ImageException( "Unknown type" );
+				    }
+				}
+		    }
+		}
+	
+		nodes = new Node[numNodes];
+		int offset = 0;
+		if( topNode != null ){
+		    nodes[0] = topNode;
+		    offset = 1;
+		}
+		for( int i=0; i<tmpNodes.size(); i++ )
+		    nodes[i+offset] = (Node)(tmpNodes.elementAt(i));
+		if( bottomNode != null )
+		    nodes[numNodes-1] = bottomNode;
+	
+		if( _calcDistance ){
+			distance = new int[numNodes][numNodes];
+			for( int i=0; i<numNodes-1; i++ ){
+				int[][] map = getDistanceMap( new Coord( nodes[i].x, nodes[i].y ) );
+				for( int j=i+1; j<numNodes; j++ ){
+					distance[i][j] = map[nodes[j].y][nodes[j].x];
+					distance[j][i] = distance[i][j];
+				}
+			}
+		}
+    }
+
+	public static boolean match( Topology _t1, Topology _t2 ){
+		if( _t1.numInterior != _t2.numInterior ){
+			return( false );
+		}
+		if( _t1.numEdges != _t2.numEdges ){
+			return( false );
+		}
+		if( _t1.numBranches != _t2.numBranches ){
+			return( false );
+		}
+		if( _t1.numCrosses != _t2.numCrosses ){
+			return( false );
+		}
+		return( true );
+	}
+	
+	public boolean match( Topology _t ){
+		return( match( this, _t ) );
+	}
+
+    private int[][] getDistanceMap( Coord _co ){
+    	//TODO check component != null
+		int[][] map = new int[height][width];
+		BinaryImage bi = component.shape;
+		Vector currentNodes = null;
+		Vector<Coord> nextNodes = new Vector<Coord>();
+		nextNodes.addElement( _co );
+	
+		int currentDistance = 1;
+		int size = nextNodes.size();
+		while( size > 0 ){
+		    currentNodes = nextNodes;
+		    nextNodes = new Vector<Coord>();
+	
+		    for( int i=0; i<size; i++ ){
+				Coord co = (Coord)(currentNodes.elementAt(i));
+				int x = co.x;
+				int y = co.y;
+				if( x>0 && bi.data[y][x-1] != 0 ){ 
+				    checkAndSetDistance( x-1, y, map, currentDistance, nextNodes );
+				}
+				if( y>0 && bi.data[y-1][x] != 0 ){ 
+				    checkAndSetDistance( x, y-1, map, currentDistance, nextNodes );
+				}
+				if( x<width-1 && bi.data[y][x+1] != 0 ){ 
+				    checkAndSetDistance( x+1, y, map, currentDistance, nextNodes );
+				}
+				if( y<height-1 && bi.data[y+1][x] != 0 ){ 
+				    checkAndSetDistance( x, y+1, map, currentDistance, nextNodes );
+				}
+				if( x>0 && y>0 && bi.data[y-1][x-1] != 0 ){ 
+				    checkAndSetDistance( x-1, y-1, map, currentDistance, nextNodes );
+				}
+				if( x<width-1 && y>0 && bi.data[y-1][x+1] != 0 ){ 
+				    checkAndSetDistance( x+1, y-1, map, currentDistance, nextNodes );
+				}
+				if( x>0 && y<height-1 && bi.data[y+1][x-1] != 0 ){ 
+				    checkAndSetDistance( x-1, y+1, map, currentDistance, nextNodes );
+				}
+				if( x<width-1 && y<height-1 && bi.data[y+1][x+1] != 0 ){ 
+				    checkAndSetDistance( x+1, y+1, map, currentDistance, nextNodes );
+				}
+		    } 
+	
+		    size = nextNodes.size();
+		    currentDistance++;
+		} 
+		return( map );
+    } 
+
+
+    private void checkAndSetDistance( int _x, int _y, int[][] _map, int _distance, Vector<Coord> _next ){
+		if( _map[_y][_x] == 0 ){
+		    _map[_y][_x] = _distance;
+		    _next.addElement( new Coord( _x, _y ) );
+		}
+    }
+
+	public int getNumNodes() {
+		return (numNodes);
+	}
+
+	public int getNumInterior() {
+		return (numInterior);
+	}
+
+	public int getNumEdges() {
+		return (numEdges);
+	}
+
+	public int getNumBranches() {
+		return (numBranches);
+	}
+
+	public int getNumCrosses() {
+		return (numCrosses);
+	}
+
+	public int getCount() {
+		return (count);
+	}
+
+
+    class Node {
+    	//TBD use Coord class?
+		int x; 
+		int y;
+		short type;
+
+		public Node(int _x, int _y, short _type) {
+			x = _x;
+			y = _y;
+			type = _type;
+		}
+	}
+
+	public void showNodes(PrintStream _ps) {
+		PrintWriter pw = new PrintWriter(_ps, true);
+		showNodes(pw);
+	}
+
+	public void showNodes(PrintWriter _pw) {
+		_pw.println("-------------------------------");
+		_pw.println("Dumping nodes");
+		char[][] cimage = new char[height][width];
+		for (int j = 0; j < height; j++) {
+			for (int i = 0; i < width; i++) {
+				if (component.shape.data[j][i] != 0)
+					cimage[j][i] = '#';
+				else
+					cimage[j][i] = '.';
+			}
+		}
+		for (int i = 0; i < numNodes; i++) {
+			Node n = nodes[i];
+			if (n.type == TYPE_EDGE)
+				cimage[n.y][n.x] = '1';
+			else if (n.type == TYPE_CONNECTED)
+				cimage[n.y][n.x] = '2';
+			else if (n.type == TYPE_BRANCHING)
+				cimage[n.y][n.x] = '3';
+			else if (n.type == TYPE_CROSSING)
+				cimage[n.y][n.x] = '4';
+			else if (n.type == TYPE_INTERIOR)
+				cimage[n.y][n.x] = '0';
+		}
+		for (int j = 0; j < height; j++) {
+			_pw.println(new String(cimage[j]));
+		}
+		_pw.println("-------------------------------");
+	}
+
+	public void showDistances(PrintStream _ps) {
+		if (distance == null) {
+			return;
+		}
+		PrintWriter pw = new PrintWriter(_ps, true);
+		showDistances(pw);
+	}
+
+	public void showDistances(PrintWriter _pw) {
+		if (distance == null) {
+			return;
+		}
+		_pw.println("-------------------------------");
+		_pw.println("Showing distances");
+
+		StringBuffer top = new StringBuffer();
+		top.append("    ");
+		StringBuffer bar = new StringBuffer();
+		bar.append("----");
+		for (int i = 0; i < numNodes; i++) {
+			top.append("|" + numberFormat4(i));
+			bar.append("+----");
+		}
+		_pw.println(top.toString());
+		_pw.println(bar.toString());
+		for (int i = 0; i < numNodes; i++) {
+			StringBuffer sb = new StringBuffer();
+			sb.append(numberFormat4(i) + "|");
+			for (int j = 0; j < numNodes - 1; j++) {
+				sb.append(numberFormat4(distance[i][j]) + "|");
+			}
+			sb.append(numberFormat4(distance[i][numNodes - 1]));
+			_pw.println(sb.toString());
+		}
+		_pw.println("-------------------------------");
+	}
+
+	private String numberFormat4(int _i) {
+		if (0 <= _i && _i <= 9)
+			return ("   " + _i);
+		else if (10 <= _i && _i <= 99)
+			return ("  " + _i);
+		else if (100 <= _i && _i <= 999)
+			return (" " + _i);
+		else
+			return ("" + _i);
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/Vector3D.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/Vector3D.java
new file mode 100644
index 0000000..560fb63
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/image/Vector3D.java
@@ -0,0 +1,132 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.image;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+public class Vector3D {
+	double x;
+
+	double y;
+
+	double z;
+
+	public Vector3D(double _x, double _y, double _z) {
+		x = _x;
+		y = _y;
+		z = _z;
+	}
+
+	public static boolean isZeroVector(Vector3D _a) {
+		if (_a.x == 0.0 && _a.y == 0.0 && _a.z == 0.0) {
+			return (true);
+		} else {
+			return (false);
+		}
+	}
+
+	public boolean isZeroVector() {
+		return (isZeroVector(this));
+	}
+
+	public static double magnitude2(Vector3D _a) {
+		return (_a.x * _a.x + _a.y * _a.y + _a.z * _a.z);
+	}
+
+	public double magnitude2() {
+		return (magnitude2(this));
+	}
+
+	public static double magnitude(Vector3D _a) {
+		return (Math.sqrt(magnitude2(_a)));
+	}
+
+	public double magnitude() {
+		return (magnitude(this));
+	}
+
+	// a+b
+	public static Vector3D add(Vector3D _a, Vector3D _b) {
+		return (new Vector3D(_a.x + _b.x, _a.y + _b.y, _a.z + _b.z));
+	}
+
+	public Vector3D add(Vector3D _a) {
+		return (add(this, _a));
+	}
+
+	// a-b
+	public static Vector3D subtract(Vector3D _a, Vector3D _b) {
+		return (new Vector3D(_a.x - _b.x, _a.y - _b.y, _a.z - _b.z));
+	}
+
+	public Vector3D subtractFrom(Vector3D _a) {
+		return (subtract(_a, this));
+	}
+
+	public Vector3D subtractedBy(Vector3D _b) {
+		return (subtract(this, _b));
+	}
+
+	public static double innerProduct(Vector3D _a, Vector3D _b) {
+		return (_a.x * _b.x + _a.y * _b.y + _a.z * _b.z);
+	}
+
+	public static double cosine(Vector3D _a, Vector3D _b) throws ImageException {
+		if (isZeroVector(_a) || isZeroVector(_b)) {
+			throw new ImageException("Cannot calculate cosine of zero-vectors");
+		}
+		double answer = innerProduct(_a, _b) / (magnitude(_a) * magnitude(_b));
+		if (answer < -1.0) {
+			answer = -1.0;
+		} else if (1.0 < answer) {
+			answer = 1.0;
+		}
+		return (answer);
+	}
+
+	public double cosine(Vector3D _a) throws ImageException {
+		return (cosine(this, _a));
+	}
+
+	public static double angle(Vector3D _a, Vector3D _b) throws ImageException {
+		return (Math.acos(cosine(_a, _b)));
+	}
+
+	public double angle(Vector3D _a) throws ImageException {
+		return (angle(this, _a));
+	}
+
+	public static double sine(Vector3D _a, Vector3D _b) throws ImageException {
+		return (Math.sin(angle(_a, _b)));
+	}
+
+	public double sine(Vector3D _a) throws ImageException {
+		return (sine(this, _a));
+	}
+
+	public String toString() {
+		return ("(" + x + ", " + y + ", " + z + ")");
+	}
+
+	public void dump(PrintStream _ps) {
+		PrintWriter pw = new PrintWriter(_ps, true);
+		dump(pw);
+	}
+
+	public void dump(PrintWriter _pw) {
+		_pw.println("-----");
+		_pw.println("dumping Vector3D");
+		_pw.println("(x,y,z) = ( " + x + ", " + y + ", " + z + ")");
+		_pw.println("-----");
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/Messages.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/Messages.java
new file mode 100644
index 0000000..ba5f150
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/Messages.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.internal;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+	private static final String BUNDLE_NAME = "org.eclipse.actf.visualization.engines.lowvision.internal.messages"; //$NON-NLS-1$
+
+	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+			.getBundle(BUNDLE_NAME);
+
+	private Messages() {
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/io/BMPReader.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/io/BMPReader.java
new file mode 100644
index 0000000..42a6cc7
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/io/BMPReader.java
@@ -0,0 +1,520 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision.internal.io;
+
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBufferInt;
+import java.awt.image.WritableRaster;
+import java.io.BufferedInputStream;
+import java.io.DataInputStream;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.eclipse.actf.visualization.engines.lowvision.image.Int2D;
+import org.eclipse.actf.visualization.engines.lowvision.internal.util.DebugUtil;
+import org.eclipse.actf.visualization.engines.lowvision.internal.util.DosUtil;
+import org.eclipse.actf.visualization.engines.lowvision.io.LowVisionIOException;
+
+public class BMPReader {
+	
+	//TODO remove redundancy
+	
+	public static Int2D readInt2D(String _fileName) throws LowVisionIOException {
+		FileInputStream fis = null;
+		try {
+			fis = new FileInputStream(_fileName);
+		} catch (FileNotFoundException e) {
+			e.printStackTrace();
+			throw new LowVisionIOException("The file was not found: "
+					+ _fileName);
+		}
+		return (readInt2D(fis));
+	}
+
+	public static BufferedImage readBufferedImage(String _fileName)
+			throws LowVisionIOException {
+		FileInputStream fis = null;
+		try {
+			fis = new FileInputStream(_fileName);
+		} catch (FileNotFoundException e) {
+			e.printStackTrace();
+			throw new LowVisionIOException("The file was not found: "
+					+ _fileName);
+		}
+		return (readBufferedImage(fis));
+	}
+
+	public static int getBitCount(String _fileName) throws LowVisionIOException {
+		FileInputStream fis = null;
+		try {
+			fis = new FileInputStream(_fileName);
+		} catch (FileNotFoundException e) {
+			e.printStackTrace();
+			throw new LowVisionIOException("The file was not found: "
+					+ _fileName);
+		}
+		return (getBitCount(fis));
+	}
+
+	public static int getBitCount(InputStream _is) throws LowVisionIOException {
+		short bitCount;
+
+		DataInputStream dis = new DataInputStream(new BufferedInputStream(_is));
+
+		// // read header
+		try {
+			// magic number "BM"
+			int magic1 = dis.readByte();
+			int magic2 = dis.readByte();
+			if (magic1 != 0x42 || magic2 != 0x4d) {
+				throw new LowVisionIOException("Bad magic characters: "
+						+ magic1 + " and " + magic2);
+			}
+
+			/* fileSize = */DosUtil.upsideDownInt(dis.readInt());
+
+			// skip reserved byte
+			dis.skipBytes(4);
+
+			/* offSet = */DosUtil.upsideDownInt(dis.readInt());
+
+			// second struct size
+			/* structSize = */DosUtil.upsideDownInt(dis.readInt());
+
+			/* imageWidth = */DosUtil.upsideDownInt(dis.readInt());
+			/* imageHeight = */DosUtil.upsideDownInt(dis.readInt());
+
+			// 1
+			dis.skipBytes(2);
+
+			// support 8/16/24/32 bit image
+			bitCount = DosUtil.upsideDownShort(dis.readShort());
+			if (bitCount != 8 && bitCount != 16 && bitCount != 24
+					&& bitCount != 32) {
+				throw new LowVisionIOException(
+						"Current version processes 8-bit/16-bit/24-bit/32-bit images only. The image's bitcount = "
+								+ bitCount);
+			}
+			return (bitCount);
+		} catch (IOException e) {
+			e.printStackTrace();
+			throw new LowVisionIOException(
+					"IO error occurred when reading the header.");
+		}
+	}
+
+	public static BufferedImage readBufferedImage(InputStream _is)
+			throws LowVisionIOException {
+		int fileSize;
+		int offSet;
+		// int structSize;
+		int imageWidth;
+		int imageHeight;
+		short bitCount;
+		// int imageSize;
+		int linePadding;
+
+		DataInputStream dis = new DataInputStream(new BufferedInputStream(_is));
+
+		try {
+			// magic number "BM"
+			int magic1 = dis.readByte();
+			int magic2 = dis.readByte();
+			if (magic1 != 0x42 || magic2 != 0x4d) {
+				throw new LowVisionIOException("Bad magic characters: "
+						+ magic1 + " and " + magic2);
+			}
+
+			fileSize = DosUtil.upsideDownInt(dis.readInt());
+
+			// skip reserved byte
+			dis.skipBytes(4);
+
+			offSet = DosUtil.upsideDownInt(dis.readInt());
+
+			/* structSize = */DosUtil.upsideDownInt(dis.readInt());
+
+			imageWidth = DosUtil.upsideDownInt(dis.readInt());
+			imageHeight = DosUtil.upsideDownInt(dis.readInt());
+
+			// 1
+			dis.skipBytes(2);
+
+			// support 8/16/24/32 bit images
+			bitCount = DosUtil.upsideDownShort(dis.readShort());
+			if (bitCount != 8 && bitCount != 16 && bitCount != 24
+					&& bitCount != 32) {
+				throw new LowVisionIOException(
+						"Current version processes 8-bit/16-bit/24-bit/32-bit images only. The image's bitcount = "
+								+ bitCount);
+			}
+
+			dis.skipBytes(4);
+
+			/* imageSize = */DosUtil.upsideDownInt(dis.readInt());
+			linePadding = 0;
+			if (bitCount == 24) {
+				int res = imageWidth * 3 % 4;
+				if (res != 0)
+					linePadding = 4 - res;
+			} else if (bitCount == 16 && (imageWidth % 2 == 1)) { // 2004/12(2)
+				linePadding = 2;
+			}
+
+			if (bitCount == 8 && imageWidth * imageHeight + offSet != fileSize) {
+				DebugUtil.errMsg(null, "WARNING!!  Bad file size. imageWidth="
+						+ imageWidth + ", linePadding=" + linePadding
+						+ ", imageHeight=" + imageHeight + ", offSet=" + offSet
+						+ ", fileSize=" + fileSize);
+			}
+			if (bitCount == 24
+					&& (imageWidth * 3 + linePadding) * imageHeight + offSet != fileSize) {
+				DebugUtil.errMsg(null, "WARNING!!  Bad file size. imageWidth="
+						+ imageWidth + ", linePadding=" + linePadding
+						+ ", imageHeight=" + imageHeight + ", offSet=" + offSet
+						+ ", fileSize=" + fileSize);
+			}
+			if (bitCount == 32
+					&& imageWidth * 4 * imageHeight + offSet != fileSize) {
+				DebugUtil.errMsg(null, "WARNING!!  Bad file size. imageWidth="
+						+ imageWidth + ", linePadding=" + linePadding
+						+ ", imageHeight=" + imageHeight + ", offSet=" + offSet
+						+ ", fileSize=" + fileSize);
+			}
+			// TODO 16bit check
+
+			dis.skipBytes(16);
+
+		} catch (IOException e) {
+			e.printStackTrace();
+			throw new LowVisionIOException(
+					"IO error occurred when reading the header.");
+		}
+
+		int[] colorTable = null;
+		if (bitCount == 8) {
+			try {
+				byte[] byteTable = new byte[1024];
+				int readNum = dis.read(byteTable);
+				if (readNum != 1024) {
+					throw new LowVisionIOException(
+							"Amount of the image data is not enough.");
+				}
+				colorTable = new int[256];
+				for (int k = 0; k < 256; k++) {
+					int b = byteTable[4 * k];
+					int g = byteTable[4 * k + 1];
+					int r = byteTable[4 * k + 2];
+					colorTable[k] = (r << 16) + (g << 8) + b;
+				}
+			} catch (Exception e) {
+				e.printStackTrace();
+			}
+		}
+
+		/*
+		 * (1)start from bottom left (2)B->G->R (24 bit format)
+		 */
+
+		int bytesPerLine = 0;
+		if (bitCount == 8) {
+			bytesPerLine = imageWidth;
+		} else if (bitCount == 16) { // 2004/12(3)
+			bytesPerLine = imageWidth * 2;
+		} else if (bitCount == 24) {
+			bytesPerLine = imageWidth * 3;
+		} else if (bitCount == 32) {
+			bytesPerLine = imageWidth * 4;
+		}
+		byte[][] srcArray = new byte[imageHeight][bytesPerLine];
+
+		BufferedImage destImage = new BufferedImage(imageWidth, imageHeight,
+				BufferedImage.TYPE_INT_RGB);
+		WritableRaster destRaster = destImage.copyData(null);
+		DataBufferInt destBufInt = (DataBufferInt) (destRaster.getDataBuffer());
+		int[] destArray = destBufInt.getData();
+
+		try {
+			for (int j = 0; j < imageHeight; j++) {
+				int readNum = dis.read(srcArray[j]);
+				if (readNum != bytesPerLine) {
+					throw new LowVisionIOException(
+							"Amount of the image data is not enough.");
+				}
+				dis.skipBytes(linePadding);
+			}
+
+			int destIndex = 0;
+			if (bitCount == 8) {
+				for (int j = imageHeight - 1; j >= 0; j--) {
+					for (int i = 0; i < imageWidth; i++) {
+						destArray[destIndex] = colorTable[srcArray[j][i]];
+						destIndex++;
+					}
+				}
+			} else if (bitCount == 16) { // 2004/12(4)
+				for (int j = imageHeight - 1; j >= 0; j--) {
+					for (int i = 0; i < imageWidth; i++) {
+						int i16 = ((int) (srcArray[j][i * 2 + 1]) << 8)
+								| (srcArray[j][i * 2] & 0xff);
+						int b = i16 & 0x1f;
+						int g = (i16 >> 5) & 0x1f;
+						int r = (i16 >> 10) & 0x1f;
+						int pixel = r << 19 | g << 11 | b << 3;
+						destArray[destIndex] = pixel;
+						destIndex++;
+					}
+				}
+			} else if (bitCount == 24) {
+				for (int j = imageHeight - 1; j >= 0; j--) {
+					for (int i = 0; i < imageWidth; i++) {
+						int pixel = 0;
+						pixel |= ((int) (srcArray[j][i * 3]) & 0xff); // b
+						pixel |= ((int) (srcArray[j][i * 3 + 1]) & 0xff) << 8; // g
+						pixel |= ((int) (srcArray[j][i * 3 + 2]) & 0xff) << 16; // r
+						destArray[destIndex] = pixel;
+						destIndex++;
+					}
+				}
+			} else if (bitCount == 32) {
+				for (int j = imageHeight - 1; j >= 0; j--) {
+					for (int i = 0; i < imageWidth; i++) {
+						int pixel = 0;
+						pixel |= ((int) (srcArray[j][i * 4]) & 0xff); // b
+						pixel |= ((int) (srcArray[j][i * 4 + 1]) & 0xff) << 8; // g
+						pixel |= ((int) (srcArray[j][i * 4 + 2]) & 0xff) << 16; // r
+						destArray[destIndex] = pixel;
+						destIndex++;
+					}
+				}
+			}
+		} catch (IOException e) {
+			e.printStackTrace();
+			throw new LowVisionIOException(
+					"IO error occurred when reading the image data.");
+		}
+		srcArray = null;
+
+		destImage.setData(destRaster);
+
+		try {
+			dis.close();
+			_is.close();
+		} catch (IOException e) {
+			e.printStackTrace();
+			throw new LowVisionIOException(
+					"IO error occurred when closing the input streams.");
+		}
+
+		return (destImage);
+	}
+
+	public static Int2D readInt2D(InputStream _is) throws LowVisionIOException {
+		int fileSize;
+		int offSet;
+		// int structSize;
+		int imageWidth;
+		int imageHeight;
+		short bitCount;
+		// int imageSize;
+		int linePadding;
+
+		DataInputStream dis = new DataInputStream(new BufferedInputStream(_is));
+
+		try {
+			int magic1 = dis.readByte();
+			int magic2 = dis.readByte();
+			if (magic1 != 0x42 || magic2 != 0x4d) {
+				throw new LowVisionIOException("Bad magic characters: "
+						+ magic1 + " and " + magic2);
+			}
+
+			fileSize = DosUtil.upsideDownInt(dis.readInt());
+
+			dis.skipBytes(4);
+
+			offSet = DosUtil.upsideDownInt(dis.readInt());
+
+			/* structSize = */DosUtil.upsideDownInt(dis.readInt());
+
+			imageWidth = DosUtil.upsideDownInt(dis.readInt());
+			imageHeight = DosUtil.upsideDownInt(dis.readInt());
+
+			dis.skipBytes(2);
+
+			bitCount = DosUtil.upsideDownShort(dis.readShort());
+			// if( bitCount != 8 && bitCount != 24 && bitCount != 32 ){
+			if (bitCount != 8 && bitCount != 16 && bitCount != 24
+					&& bitCount != 32) {
+				throw new LowVisionIOException(
+						"Current version processes 8-bit/24-bit/32-bit images only. The image's bitcount = "
+								+ bitCount);
+			}
+
+			dis.skipBytes(4);
+
+			/* imageSize = */DosUtil.upsideDownInt(dis.readInt());
+			linePadding = 0;
+			if (bitCount == 24) {
+				int res = imageWidth * 3 % 4;
+				if (res != 0)
+					linePadding = 4 - res;
+			} else if (bitCount == 16 && (imageWidth % 2 == 1)) { // 2004/12(2)
+				linePadding = 2;
+			}
+
+			if (bitCount == 8 && imageWidth * imageHeight + offSet != fileSize) {
+				// throw new LowVisionIOException( "Bad file size. imageWidth="
+				// + imageWidth + ", linePadding=" + linePadding + ",
+				// imageHeight=" + imageHeight + ", offSet=" + offSet + ",
+				// fileSize=" + fileSize );
+				DebugUtil.errMsg(null, "WARNING!!  Bad file size. imageWidth="
+						+ imageWidth + ", linePadding=" + linePadding
+						+ ", imageHeight=" + imageHeight + ", offSet=" + offSet
+						+ ", fileSize=" + fileSize);
+			}
+			if (bitCount == 24
+					&& (imageWidth * 3 + linePadding) * imageHeight + offSet != fileSize) {
+				// throw new LowVisionIOException( "Bad file size. imageWidth="
+				// + imageWidth + ", linePadding=" + linePadding + ",
+				// imageHeight=" + imageHeight + ", offSet=" + offSet + ",
+				// fileSize=" + fileSize );
+				DebugUtil.errMsg(null, "WARNING!!  Bad file size. imageWidth="
+						+ imageWidth + ", linePadding=" + linePadding
+						+ ", imageHeight=" + imageHeight + ", offSet=" + offSet
+						+ ", fileSize=" + fileSize);
+			}
+			if (bitCount == 32
+					&& imageWidth * 4 * imageHeight + offSet != fileSize) {
+				// throw new LowVisionIOException( "Bad file size. imageWidth="
+				// + imageWidth + ", linePadding=" + linePadding + ",
+				// imageHeight=" + imageHeight + ", offSet=" + offSet + ",
+				// fileSize=" + fileSize );
+				DebugUtil.errMsg(null, "WARNING!!  Bad file size. imageWidth="
+						+ imageWidth + ", linePadding=" + linePadding
+						+ ", imageHeight=" + imageHeight + ", offSet=" + offSet
+						+ ", fileSize=" + fileSize);
+			}
+			// TODO 16bit check
+
+			dis.skipBytes(16);
+
+		} catch (IOException e) {
+			e.printStackTrace();
+			throw new LowVisionIOException(
+					"IO error occurred when reading the header.");
+		}
+
+		int[] colorTable = null;
+		if (bitCount == 8) {
+			try {
+				byte[] byteTable = new byte[1024];
+				int readNum = dis.read(byteTable);
+				if (readNum != 1024) {
+					throw new LowVisionIOException(
+							"Amount of the image data is not enough.");
+				}
+				colorTable = new int[256];
+				for (int k = 0; k < 256; k++) {
+					int b = byteTable[4 * k];
+					int g = byteTable[4 * k + 1];
+					int r = byteTable[4 * k + 2];
+					colorTable[k] = (r << 16) + (g << 8) + b;
+				}
+			} catch (Exception e) {
+				e.printStackTrace();
+			}
+		}
+
+		int bytesPerLine = 0;
+		if (bitCount == 8) {
+			bytesPerLine = imageWidth;
+		} else if (bitCount == 16) { // 2004/12(3)
+			bytesPerLine = imageWidth * 2;
+		} else if (bitCount == 24) {
+			bytesPerLine = imageWidth * 3;
+		} else if (bitCount == 32) {
+			bytesPerLine = imageWidth * 4;
+		}
+		byte[][] srcArray = new byte[imageHeight][bytesPerLine];
+
+		Int2D destImage = new Int2D(imageWidth, imageHeight);
+
+		try {
+			for (int j = 0; j < imageHeight; j++) {
+				int readNum = dis.read(srcArray[j]);
+				if (readNum != bytesPerLine) {
+					throw new LowVisionIOException(
+							"Amount of the image data is not enough.");
+				}
+				dis.skipBytes(linePadding);
+			}
+
+			if (bitCount == 8) {
+				for (int j = imageHeight - 1; j >= 0; j--) {
+					for (int i = 0; i < imageWidth; i++) {
+						destImage.data[imageHeight - j - 1][i] = colorTable[srcArray[j][i]];
+					}
+				}
+			} else if (bitCount == 16) { // 2004/12(4)
+				for (int j = imageHeight - 1; j >= 0; j--) {
+					for (int i = 0; i < imageWidth; i++) {
+						int i16 = ((int) (srcArray[j][i * 2 + 1]) << 8)
+								| (srcArray[j][i * 2] & 0xff);
+						int b = i16 & 0x1f;
+						int g = (i16 >> 5) & 0x1f;
+						int r = (i16 >> 10) & 0x1f;
+						int pixel = r << 19 | g << 11 | b << 3;
+						destImage.data[imageHeight - j - 1][i] = pixel;
+					}
+				}
+			} else if (bitCount == 24) {
+				for (int j = imageHeight - 1; j >= 0; j--) {
+					for (int i = 0; i < imageWidth; i++) {
+						int pixel = 0;
+						pixel |= ((int) (srcArray[j][i * 3]) & 0xff); // b
+						pixel |= ((int) (srcArray[j][i * 3 + 1]) & 0xff) << 8; // g
+						pixel |= ((int) (srcArray[j][i * 3 + 2]) & 0xff) << 16; // r
+						destImage.data[imageHeight - j - 1][i] = pixel;
+					}
+				}
+			} else if (bitCount == 32) {
+				for (int j = imageHeight - 1; j >= 0; j--) {
+					for (int i = 0; i < imageWidth; i++) {
+						int pixel = 0;
+						pixel |= ((int) (srcArray[j][i * 4]) & 0xff); // b
+						pixel |= ((int) (srcArray[j][i * 4 + 1]) & 0xff) << 8; // g
+						pixel |= ((int) (srcArray[j][i * 4 + 2]) & 0xff) << 16; // r
+						destImage.data[imageHeight - j - 1][i] = pixel;
+					}
+				}
+			}
+		} catch (IOException e) {
+			e.printStackTrace();
+			throw new LowVisionIOException(
+					"IO error occurred when reading the image data.");
+		}
+		srcArray = null;
+
+		try {
+			dis.close();
+			_is.close();
+		} catch (IOException e) {
+			e.printStackTrace();
+			throw new LowVisionIOException(
+					"IO error occurred when closing the input streams.");
+		}
+
+		return (destImage);
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/io/BMPWriter.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/io/BMPWriter.java
new file mode 100644
index 0000000..1f66945
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/io/BMPWriter.java
@@ -0,0 +1,181 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision.internal.io;
+
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBufferInt;
+import java.awt.image.WritableRaster;
+import java.io.DataOutputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.eclipse.actf.visualization.engines.lowvision.image.ImageUtil;
+import org.eclipse.actf.visualization.engines.lowvision.image.Int2D;
+import org.eclipse.actf.visualization.engines.lowvision.internal.util.DosUtil;
+import org.eclipse.actf.visualization.engines.lowvision.io.LowVisionIOException;
+
+public class BMPWriter {
+	private static final int DEFAULT_BITCOUNT = 24;
+
+	public static void writeInt2D(Int2D _i2d, String _fileName, int _bitCount)
+			throws LowVisionIOException {
+		writeBufferedImage(ImageUtil.int2DToBufferedImage(_i2d), _fileName,
+				_bitCount);
+	}
+
+	public static void writeInt2D(Int2D _i2d, String _fileName)
+			throws LowVisionIOException {
+		writeBufferedImage(ImageUtil.int2DToBufferedImage(_i2d), _fileName);
+	}
+
+	public static void writeInt2D(Int2D _i2d, OutputStream _os, int _bitCount)
+			throws LowVisionIOException {
+		writeBufferedImage(ImageUtil.int2DToBufferedImage(_i2d), _os, _bitCount);
+	}
+
+	public static void writeInt2D(Int2D _i2d, OutputStream _os)
+			throws LowVisionIOException {
+		writeBufferedImage(ImageUtil.int2DToBufferedImage(_i2d), _os);
+	}
+
+	public static void writeBufferedImage(BufferedImage _bi, String _fileName,
+			int _bitCount) throws LowVisionIOException {
+		FileOutputStream fos = null;
+		try {
+			fos = new FileOutputStream(_fileName);
+		} catch (FileNotFoundException e) {
+			e.printStackTrace();
+			throw new LowVisionIOException("The file was not found: "
+					+ _fileName);
+		}
+		writeBufferedImage(_bi, fos, _bitCount);
+	}
+
+	public static void writeBufferedImage(BufferedImage _bi, String _fileName)
+			throws LowVisionIOException {
+		writeBufferedImage(_bi, _fileName, DEFAULT_BITCOUNT);
+	}
+
+	public static void writeBufferedImage(BufferedImage _bi, OutputStream _os)
+			throws LowVisionIOException {
+		writeBufferedImage(_bi, _os, DEFAULT_BITCOUNT);
+	}
+
+	public static void writeBufferedImage(BufferedImage _bi, OutputStream _os,
+			int _bitCount) throws LowVisionIOException {
+		// only for BufferedImage.TYPE_INT_RGB
+
+		if (_bitCount != 16 && _bitCount != 24) {
+			throw new LowVisionIOException("Invalid bitCount: " + _bitCount);
+		}
+
+		int imageWidth = _bi.getWidth();
+		int imageHeight = _bi.getHeight();
+		int residual = 0;
+		if (_bitCount == 24) {
+			residual = imageWidth * 3 % 4; // 24bit
+		} else if (_bitCount == 16) {
+			residual = imageWidth * 2 % 4; // 16bit
+		}
+		int linePadding = 0;
+		if (residual > 0)
+			linePadding = 4 - residual;
+		int imageSize = 0;
+		if (_bitCount == 24) {
+			imageSize = (imageWidth * 3 + linePadding) * imageHeight;
+		} else if (_bitCount == 16) {
+			imageSize = (imageWidth * 2 + linePadding) * imageHeight;
+		}
+		int fileSize = imageSize + 54;
+
+		DataOutputStream dos = new DataOutputStream(_os);
+
+		try {
+			// magic number "BM"
+			dos.writeByte(0x42);
+			dos.writeByte(0x4d);
+			dos.writeInt(DosUtil.upsideDownInt(fileSize));
+			dos.writeInt(0);
+			dos.writeInt(DosUtil.upsideDownInt(54));
+			dos.writeInt(DosUtil.upsideDownInt(40));
+			dos.writeInt(DosUtil.upsideDownInt(imageWidth));
+			dos.writeInt(DosUtil.upsideDownInt(imageHeight));
+			dos.writeShort(DosUtil.upsideDownShort((short) 1));
+			dos.writeShort(DosUtil.upsideDownShort((short) _bitCount));
+			dos.writeInt(DosUtil.upsideDownInt(0));
+			dos.writeInt(DosUtil.upsideDownInt(imageSize));
+			dos.writeInt(DosUtil.upsideDownInt(4724));
+			dos.writeInt(DosUtil.upsideDownInt(4724));
+			dos.writeInt(DosUtil.upsideDownInt(0));
+			dos.writeInt(DosUtil.upsideDownInt(0));
+		} catch (IOException e) {
+			e.printStackTrace();
+			throw new LowVisionIOException(
+					"IO error occurred when writing header.");
+		}
+
+		WritableRaster srcRaster = _bi.copyData(null);
+		DataBufferInt srcBufInt = (DataBufferInt) (srcRaster.getDataBuffer());
+		int[] srcArray = srcBufInt.getData();
+
+		byte[][] destArray2d = null;
+		int srcIndex = 0;
+		if (_bitCount == 24) {
+			destArray2d = new byte[imageHeight][imageWidth * 3];
+			for (int j = imageHeight - 1; j >= 0; j--) {
+				for (int i = 0; i < imageWidth; i++) {
+					int rgb = srcArray[srcIndex];
+					destArray2d[j][i * 3] = (byte) (rgb & 0xff); // b
+					destArray2d[j][i * 3 + 1] = (byte) (rgb >> 8 & 0xff); // g
+					destArray2d[j][i * 3 + 2] = (byte) (rgb >> 16 & 0xff); // r
+					srcIndex++;
+				}
+			}
+		} else if (_bitCount == 16) {
+			destArray2d = new byte[imageHeight][imageWidth * 2];
+			for (int j = imageHeight - 1; j >= 0; j--) {
+				for (int i = 0; i < imageWidth; i++) {
+					int rgb = srcArray[srcIndex];
+					int r = (rgb >> 19) & 0x1f;
+					int g = (rgb >> 11) & 0x1f;
+					int b = (rgb >> 3) & 0x1f;
+					destArray2d[j][i * 2] = (byte) (((g & 0x7) << 5) | b);
+					destArray2d[j][i * 2 + 1] = (byte) ((r << 2) | ((g >> 3) & 0x3));
+					srcIndex++;
+				}
+			}
+		}
+
+		try {
+			for (int j = 0; j < imageHeight; j++) {
+				dos.write(destArray2d[j]);
+				for (int i = 0; i < linePadding; i++) {
+					dos.writeByte(0);
+				}
+			}
+		} catch (IOException e) {
+			e.printStackTrace();
+			throw new LowVisionIOException(
+					"IO error occurred while writing image data.");
+		}
+
+		try {
+			dos.close();
+			_os.close();
+		} catch (IOException e) {
+			e.printStackTrace();
+			throw new LowVisionIOException(
+					"IO error occurred when closing output streams.");
+		}
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/io/ImageFileReader.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/io/ImageFileReader.java
new file mode 100644
index 0000000..a43725c
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/io/ImageFileReader.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.internal.io;
+
+import java.awt.image.BufferedImage;
+
+/*
+ * Image file reader for gif/png (also can use for jpeg)
+ */
+public class ImageFileReader {
+
+	// TODO use javax.imageio
+
+	public static BufferedImage readBufferedImage(String _fileName) {
+		ImageFileReaderController cont = new ImageFileReaderController(
+				_fileName);
+		BufferedImage bufIm = cont.getImage();
+		return (bufIm);
+
+		// return( (new ImageFileReaderController(_fileName)).getImage() );
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/io/ImageFileReaderController.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/io/ImageFileReaderController.java
new file mode 100644
index 0000000..93ab55e
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/io/ImageFileReaderController.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.internal.io;
+
+import java.awt.image.BufferedImage;
+import java.util.Date;
+
+import org.eclipse.actf.visualization.engines.lowvision.internal.util.DebugUtil;
+
+class ImageFileReaderController {
+	private static final long MAX_TIME_TO_GET = 30000; // msec
+
+	private String fileName = null;
+
+	private boolean gottenFlag = false;
+
+	private BufferedImage image = null;
+
+	private ImageFileReaderGetter getter = null;
+
+	ImageFileReaderController(String _fileName) {
+		fileName = _fileName;
+		// timer = new ImageFileReaderTimer( this, MAX_TIME_TO_GET );
+		getter = new ImageFileReaderGetter(this, _fileName);
+		// timer.start();
+		getter.setDaemon(true);
+		getter.start();
+		waitForData();
+	}
+
+	BufferedImage getImage() {
+		return (image);
+	}
+
+	private void waitForData() {
+		try {
+			for (long st = (new Date()).getTime(); (new Date()).getTime() - st <= MAX_TIME_TO_GET; Thread
+					.sleep(50)) {
+				if (gottenFlag /* || timeOutFlag */) {
+					getter.interrupt();
+					return;
+				}
+			}
+			DebugUtil.outMsg(null, "Thread for getting \"" + fileName
+					+ "\" was timed out.");
+		} catch (InterruptedException ie) {
+			ie.printStackTrace();
+		} finally {
+			getter.interrupt();
+		}
+	}
+
+	void setGottenFlag(boolean _b) {
+		gottenFlag = _b;
+	}
+
+	void setBufferedImage(BufferedImage _bi) {
+		image = _bi;
+
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/io/ImageFileReaderGetter.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/io/ImageFileReaderGetter.java
new file mode 100644
index 0000000..d9f2b66
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/io/ImageFileReaderGetter.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.internal.io;
+
+import java.awt.Component;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.MediaTracker;
+import java.awt.Toolkit;
+import java.awt.image.BufferedImage;
+
+import org.eclipse.actf.visualization.engines.lowvision.internal.util.DebugUtil;
+
+class ImageFileReaderGetter extends Thread {
+	ImageFileReaderController caller = null;
+
+	String fileName = null;
+
+	BufferedImage image = null;
+
+	ImageFileReaderGetter(ImageFileReaderController _caller, String _fileName) {
+		caller = _caller;
+		fileName = _fileName;
+	}
+
+	public void run() {
+		Toolkit tk = Toolkit.getDefaultToolkit();
+		Image im = tk.getImage(fileName);
+		Component comp = new Component() {
+		};
+		MediaTracker tracker = new MediaTracker(comp);
+		tracker.addImage(im, 0);
+
+		try {
+			tracker.waitForID(0);
+		} catch (InterruptedException ie) {
+			DebugUtil.outMsg(this, "Thread for getting \"" + fileName
+					+ "\" was interrupted.");
+			// ie.printStackTrace();
+		}
+
+		int w = im.getWidth(null);
+		int h = im.getHeight(null);
+		// DebugUtil.outMsg( this, "width = " + w + ", height = " + h );
+
+		if (w > 0 && h > 0) {
+			// DebugUtil.outMsg( this, "BufferedImage will be created." );
+			image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
+			Graphics gr = image.getGraphics();
+			gr.drawImage(im, 0, 0, null);
+		}
+		if (image == null) {
+			DebugUtil.outMsg(this, "BufferedImage is null.");
+		}
+
+		caller.setBufferedImage(image);
+		// DebugUtil.outMsg( null, "checkAll() =" + tracker.checkAll() );
+		// tracker.removeImage(im,0);
+		// try{
+		// Thread.sleep(50);
+		// }catch( InterruptedException e ){
+		// }
+
+		caller.setGottenFlag(true);
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/io/JPEGReader.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/io/JPEGReader.java
new file mode 100644
index 0000000..a99446d
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/io/JPEGReader.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision.internal.io;
+
+import java.awt.image.BufferedImage;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+import org.eclipse.actf.visualization.engines.lowvision.io.LowVisionIOException;
+
+import com.sun.image.codec.jpeg.JPEGCodec;
+import com.sun.image.codec.jpeg.JPEGImageDecoder;
+
+public class JPEGReader {
+	public static BufferedImage readBufferedImage(String _fileName)
+			throws LowVisionIOException {
+		FileInputStream fis = null;
+		try {
+			fis = new FileInputStream(_fileName);
+		} catch (FileNotFoundException e) {
+			e.printStackTrace();
+			throw new LowVisionIOException("The file was not found: "
+					+ _fileName);
+		}
+
+		JPEGImageDecoder dec = null;
+		try {
+			dec = JPEGCodec.createJPEGDecoder(fis);
+			BufferedImage bi = dec.decodeAsBufferedImage();
+			fis.close();
+			return (bi);
+		} catch (IOException e) {
+			e.printStackTrace();
+			throw new LowVisionIOException(
+					"IO error occurred while decoding JPEG file.");
+		}
+	} 
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/io/JPEGWriter.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/io/JPEGWriter.java
new file mode 100644
index 0000000..266f29b
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/io/JPEGWriter.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision.internal.io;
+
+import java.awt.image.BufferedImage;
+import java.io.BufferedOutputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.eclipse.actf.visualization.engines.lowvision.io.LowVisionIOException;
+
+import com.sun.image.codec.jpeg.JPEGCodec;
+import com.sun.image.codec.jpeg.JPEGImageEncoder;
+
+public class JPEGWriter {
+	public static void writeBufferedImage(BufferedImage _bi, String _fileName)
+			throws LowVisionIOException {
+		BufferedOutputStream bos = null;
+		try {
+			bos = new BufferedOutputStream(new FileOutputStream(_fileName));
+		} catch (FileNotFoundException e) {
+			e.printStackTrace();
+			throw new LowVisionIOException("The file was not found: "
+					+ _fileName);
+		}
+
+		try {
+			JPEGImageEncoder enc = JPEGCodec.createJPEGEncoder(bos);
+			enc.encode(_bi);
+			bos.close();
+		} catch (IOException e) {
+			e.printStackTrace();
+			throw new LowVisionIOException(
+					"IO error occurred while decoding/closing.");
+		}
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/io/PBMReader.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/io/PBMReader.java
new file mode 100644
index 0000000..6983a92
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/io/PBMReader.java
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision.internal.io;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.actf.visualization.engines.lowvision.image.BinaryImage;
+import org.eclipse.actf.visualization.engines.lowvision.io.LowVisionIOException;
+
+
+public class PBMReader{
+    public static BinaryImage readBinaryImage( String _fileName ) throws LowVisionIOException{
+		FileInputStream fis = null;
+		try{
+	    	fis = new FileInputStream( _fileName );
+		}catch( FileNotFoundException e ){
+	    	e.printStackTrace();
+	    	throw new LowVisionIOException( "The file was not found: " + _fileName );
+		}
+		BufferedReader br = new BufferedReader( new InputStreamReader( fis ) );
+
+		try{
+	    	char magic1 = (char)(br.read());
+	    	char magic2 = (char)(br.read());
+	    	// support "P1" (not "P4")
+	    	if( magic1 != 'P' || magic2 != '1' ){
+			throw new LowVisionIOException( "Bad magic number: " + magic1 + magic2 + "\n\"P4\" cannot be treated in this version.\n(Only \"P1\" is accepted.)" );
+	    	}
+		}catch( IOException e ){
+	    	throw new LowVisionIOException( "IOException occurred while reading the magic number." );
+		}
+
+		StringBuffer sb = new StringBuffer();
+		try{
+			// remove comments, etc.
+	    	String oneLine = null;
+	    	while( (oneLine=br.readLine()) != null ){
+			int index = oneLine.indexOf("#");
+			if( index == -1 )
+		    	sb.append( oneLine + "\n" );
+			else
+		    	sb.append( oneLine.substring( 0, index ) + "\n" );
+	    	}
+		}catch( IOException e ){
+	    	e.printStackTrace();
+	    	throw new LowVisionIOException( "IO error occurred when reading." );
+		}
+
+		String content = sb.toString();
+		if( !Character.isWhitespace( content.charAt(0) ) ){
+	    	throw new LowVisionIOException( "The magic number must be followed by a white space." );
+		}
+		content = content.substring(1);
+
+		Pattern pat = Pattern.compile( "(\\d+)\\s(\\d+)\\s([01\\s]+)" );
+		Matcher mat = pat.matcher( content );
+		if( !(mat.find()) ){
+			throw new LowVisionIOException( "Invalid data format (1)." );
+		}
+		int count = mat.groupCount();
+		if( count != 3 ){
+			throw new LowVisionIOException( "Invalid data format (2). count = " + count );
+		}
+		int width = Integer.parseInt(mat.group(1));
+		int height = Integer.parseInt(mat.group(2));
+		String dataStr = mat.group(3);
+		Pattern pat2 = Pattern.compile( "\\s+" );
+		Matcher mat2 = pat2.matcher( dataStr );
+		String data = mat2.replaceAll( "" );
+
+		if( data.length() != width*height ){
+	    	throw new LowVisionIOException( "Data size does not equal to width*height" );
+		}
+
+		BinaryImage bi = new BinaryImage( width, height );
+		byte[][] bidata = bi.getData();
+		int k=0;
+		for( int j=0; j<height; j++ ){
+	    	for( int i=0; i<width; i++ ){
+				if( data.charAt(k) == '1' )
+		    	bidata[j][i] = 1;
+				k++;
+	    	}
+		}
+
+		return( bi );
+    }
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/io/PBMWriter.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/io/PBMWriter.java
new file mode 100644
index 0000000..3160d50
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/io/PBMWriter.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision.internal.io;
+
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.PrintWriter;
+
+import org.eclipse.actf.visualization.engines.lowvision.image.BinaryImage;
+import org.eclipse.actf.visualization.engines.lowvision.io.LowVisionIOException;
+
+/*
+ * write PBM file ("P1")
+ */
+public class PBMWriter {
+	private static final int LINE_LENGTH = 64;
+
+	public static void writeBinaryImage(BinaryImage _bi, String _fileName)
+			throws LowVisionIOException {
+		FileOutputStream fos = null;
+		try {
+			fos = new FileOutputStream(_fileName);
+		} catch (FileNotFoundException e) {
+			e.printStackTrace();
+			throw new LowVisionIOException("The file was not found: "
+					+ _fileName);
+		}
+		PrintWriter pw = new PrintWriter(fos, true);
+
+		int width = _bi.getWidth();
+		int height = _bi.getHeight();
+
+		pw.println("P1");
+		pw.print("" + width + " " + height);
+		int lineLength = LINE_LENGTH;
+		if (width < lineLength)
+			lineLength = width;
+		StringBuffer sb = new StringBuffer("");
+		byte[][] bidata = _bi.getData();
+		int k = 0;
+		for (int j = 0; j < height; j++) {
+			for (int i = 0; i < width; i++) {
+				if (k % lineLength == 0) {
+					pw.println(sb.toString());
+					sb = new StringBuffer();
+				}
+				k++;
+				if (bidata[j][i] == 0)
+					sb.append("0");
+				else
+					sb.append("1");
+			}
+		}
+		pw.println(sb.toString());
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/messages.properties b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/messages.properties
new file mode 100644
index 0000000..153576b
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/messages.properties
@@ -0,0 +1,39 @@
+###############################################################################
+# Copyright (c) 2007, 2008 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#     IBM Corporation - initial API and implementation
+###############################################################################
+#
+# lowvision.problem
+# 
+BlurProblem.It_is_difficult_for_weak-sighted_to_read_these_characters._1=It is difficult for weak-sighted to read these characters.
+ChangableFontRecommendation.Do_not_use_fixed-size_font._1=Do not use fixed-size font.
+ColorProblem.Foreground_and_background_colors_are_too_close._1=Foreground and background colors are too close.
+DontRelyOnColorRecommendation.Don__t_rely_only_on_color._1=Don\'t rely only on color.
+EnlargeLineRecommendation.Enlarge_the_line_height._1=Enlarge the line height.
+EnlargeTextRecommendation.Enlarge_the_text._1=Enlarge the text.
+EnoughContrastRecommendation.Provide_enough_contrast_between_foreground_and_background_colors._1=Provide enough contrast between foreground and background colors.
+FixedSizeFontProblem.Fixed-size_font_is_used._1=Fixed-size font is used.
+FixedSmallFontProblem.This_text_is_too_small_and_its_font_size_is_fixed._1=This text is too small and its font size is fixed.
+ImageColorProblem.This_image_has_two_or_more_components_whose_colors_are_too_close._1=This image has two or more components whose colors are too close.
+SmallFontProblem.This_text_is_too_small._1=This text is too small.
+UseAllowedColorRecommendation.Use_a_color_allowed_by_the_design_guideline._1=Use a color allowed by the design guideline.
+ProhibitedBothColorsProblem.Both_of_the_foreground_and_background_colors_are_not_allowed_by_the_design_guideline._1=Both foreground and background colors are not allowed by the design guideline.
+ProhibitedForegroundColorProblem.The_foreground_color_is_not_allowed_by_the_design_guideline._1=The foreground color is not allowed by the design guideline.
+ProhibitedBackgroundColorProblem.The_background_color_is_not_allowed_by_the_design_guideline._1=The background color is not allowed by the design guideline.
+#
+# lowvision.ScoreUtil
+#
+PageEvaluation.Bad=Unsatisfactory (needs modification)
+PageEvaluation.Excellent=Excellent
+PageEvaluation.Good=Good
+PageEvaluation.Poor=Passes minimum requirements
+#
+# lowvision.io.ImageDumpUtil
+#
+ImageDumpUtil.TrueColor = Please use 'True Color' (24bit/32bit) display.
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/messages_ja.properties b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/messages_ja.properties
new file mode 100644
index 0000000..ceeef4a
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/messages_ja.properties
@@ -0,0 +1,39 @@
+###############################################################################
+# Copyright (c) 2007, 2008 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#     IBM Corporation - initial API and implementation
+###############################################################################
+#
+# lowvision.problem
+# 
+BlurProblem.It_is_difficult_for_weak-sighted_to_read_these_characters._1 = \u3053\u306e\u6587\u5b57\u306f\u5c0f\u3055\u3059\u304e\u307e\u3059
+ChangableFontRecommendation.Do_not_use_fixed-size_font._1 = \u56fa\u5b9a\u30b5\u30a4\u30ba\u306e\u30d5\u30a9\u30f3\u30c8\u306f\u4f7f\u308f\u306a\u3044\u3067\u304f\u3060\u3055\u3044
+ColorProblem.Foreground_and_background_colors_are_too_close._1 = \u6587\u5b57\u8272\u3068\u80cc\u666f\u8272\u306e\u533a\u5225\u304c\u3064\u304d\u306b\u304f\u304f\u306a\u3063\u3066\u3044\u307e\u3059
+DontRelyOnColorRecommendation.Don__t_rely_only_on_color._1 = \u8272\u4ee5\u5916\u306e\u624b\u6bb5\u3067\u3082\u60c5\u5831\u3092\u4f1d\u3048\u308b\u3088\u3046\u306b\u3057\u3066\u304f\u3060\u3055\u3044
+EnlargeLineRecommendation.Enlarge_the_line_height._1 = \u884c\u9593\u3092\u5e83\u3052\u3066\u304f\u3060\u3055\u3044
+EnlargeTextRecommendation.Enlarge_the_text._1 = \u6587\u5b57\u3092\u5927\u304d\u304f\u3057\u3066\u304f\u3060\u3055\u3044
+EnoughContrastRecommendation.Provide_enough_contrast_between_foreground_and_background_colors._1 = \u6587\u5b57\u8272\u3068\u80cc\u666f\u8272\u306b\u5341\u5206\u306a\u30b3\u30f3\u30c8\u30e9\u30b9\u30c8\u3092\u4e0e\u3048\u3066\u304f\u3060\u3055\u3044
+FixedSizeFontProblem.Fixed-size_font_is_used._1 = \u56fa\u5b9a\u30b5\u30a4\u30ba\u306e\u30d5\u30a9\u30f3\u30c8\u304c\u4f7f\u308f\u308c\u3066\u3044\u307e\u3059
+FixedSmallFontProblem.This_text_is_too_small_and_its_font_size_is_fixed._1 = \u3053\u306e\u6587\u5b57\u306f\u5c0f\u3055\u3059\u304e\u307e\u3059\u3002\u3055\u3089\u306b\u56fa\u5b9a\u30b5\u30a4\u30ba\u306e\u30d5\u30a9\u30f3\u30c8\u304c\u4f7f\u308f\u308c\u3066\u3044\u307e\u3059
+ImageColorProblem.This_image_has_two_or_more_components_whose_colors_are_too_close._1 = \u3053\u306e\u753b\u50cf\u306b\u306f\u533a\u5225\u3057\u3065\u3089\u3044\u8272\u304c\u542b\u307e\u308c\u3066\u3044\u307e\u3059
+SmallFontProblem.This_text_is_too_small._1 = \u3053\u306e\u6587\u5b57\u306f\u5c0f\u3055\u3059\u304e\u307e\u3059\u3002
+UseAllowedColorRecommendation.Use_a_color_allowed_by_the_design_guideline._1 = \u30c7\u30b6\u30a4\u30f3\u30ac\u30a4\u30c9\u30e9\u30a4\u30f3\u3067\u5b9a\u3081\u3089\u308c\u305f\u8272\u3092\u4f7f\u3063\u3066\u304f\u3060\u3055\u3044
+ProhibitedBothColorsProblem.Both_of_the_foreground_and_background_colors_are_not_allowed_by_the_design_guideline._1 = \u6587\u5b57\u8272\u3068\u80cc\u666f\u8272\u306e\u4e21\u65b9\u306b\u30ac\u30a4\u30c9\u30e9\u30a4\u30f3\u3067\u8a31\u3055\u308c\u3066\u3044\u306a\u3044\u8272\u304c\u4f7f\u308f\u308c\u3066\u3044\u307e\u3059
+ProhibitedForegroundColorProblem.The_foreground_color_is_not_allowed_by_the_design_guideline._1 = \u6587\u5b57\u8272\u306b\u30ac\u30a4\u30c9\u30e9\u30a4\u30f3\u3067\u8a31\u3055\u308c\u3066\u3044\u306a\u3044\u8272\u304c\u4f7f\u308f\u308c\u3066\u3044\u307e\u3059
+ProhibitedBackgroundColorProblem.The_background_color_is_not_allowed_by_the_design_guideline._1 = \u80cc\u666f\u8272\u306b\u30ac\u30a4\u30c9\u30e9\u30a4\u30f3\u3067\u8a31\u3055\u308c\u3066\u3044\u306a\u3044\u8272\u304c\u4f7f\u308f\u308c\u3066\u3044\u307e\u3059
+#
+# lowvision.ScoreUtil
+#
+PageEvaluation.Bad=\u8981\u4fee\u6b63
+PageEvaluation.Excellent=\u975e\u5e38\u306b\u826f\u3044
+PageEvaluation.Good=\u826f\u3044
+PageEvaluation.Poor=\u5229\u7528\u56f0\u96e3
+#
+# lowvision.io.ImageDumpUtil
+#
+ImageDumpUtil.TrueColor = \u753b\u9762\u306e\u8272\u3092'\u6700\u9ad8'\uff0832\u30d3\u30c3\u30c8 \u3082\u3057\u304f\u306f 24\u30d3\u30c3\u30c8\uff09\u306b\u3057\u3066\u304f\u3060\u3055\u3044\u3002\r\uff08\u753b\u9762\u306e\u30d7\u30ed\u30d1\u30c6\u30a3\u304b\u3089\u5909\u66f4\u51fa\u6765\u307e\u3059\uff09
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/util/DebugUtil.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/util/DebugUtil.java
new file mode 100644
index 0000000..baa0fe3
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/util/DebugUtil.java
@@ -0,0 +1,204 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision.internal.util;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+import java.util.Vector;
+
+public class DebugUtil {
+	// the string for expressing directories
+	private static final String DRIVE_DELIM = ":"; // for DOS related OSs
+
+	// *************************************************************
+	// to be changed according to the debugging phase
+	// public static String DEBUG_STRING = "style-addcss-page-post-cache-diff";
+	// private static final String DEBUG_STRING =
+	// "post-genRE-infoSet-diff-cache";
+	private static final String DEBUG_STRING = "TRACE";
+
+	// private static final String DEBUG_STRING =
+	// "TRACE_HISTOGRAM_CONTAINER_EXTRACT_PROBLEM_COMPONENT_REPORT";
+
+	// (1)print utilities
+	public static void errMsg(Object o, String s) {
+		printMsg(o, s, System.err, 0);
+	}
+
+	public static void errMsg(Object o, String s, int level) {
+		printMsg(o, s, System.err, level);
+	}
+
+	public static void outMsg(Object o, String s) {
+		printMsg(o, s, System.out, 0);
+	}
+
+	public static void outMsg(Object o, String s, int level) {
+		printMsg(o, s, System.out, level);
+	}
+
+	public static void debugMsg(Object o, String s, String debugType) {
+		if (DEBUG_STRING.indexOf(debugType) > -1) {
+			printMsg(o, s, System.out, 0);
+		}
+	}
+
+	public static void debugMsg(Object o, String s, String debugType, int level) {
+		if (DEBUG_STRING.indexOf(debugType) > -1) {
+			printMsg(o, s, System.out, level);
+		}
+	}
+
+	public static void fileMsg(Object o, String s, String fileName)
+			throws FileNotFoundException {
+		fileMsg(o, s, "", fileName, 0, false);
+	}
+
+	public static void fileMsg(Object o, String s, String debugType,
+			String fileName) throws FileNotFoundException {
+		fileMsg(o, s, debugType, fileName, 0, true);
+	}
+
+	public static void fileMsg(Object o, String s, String debugType,
+			String fileName, int level) throws FileNotFoundException {
+		fileMsg(o, s, debugType, fileName, level, true);
+	}
+
+	public static void fileMsg(Object o, String s, String debugType,
+			String fileName, int level, boolean checkString)
+			throws FileNotFoundException {
+		if (checkString && DEBUG_STRING.indexOf(debugType) == -1) {
+			return;
+		}
+
+		String pathName = "";
+		if (isAbsolutePath(fileName)) {
+			pathName = fileName;
+		} else {
+			errMsg(o, "Please provide log file name in absolute path.");
+			return;
+		}
+		File logFile = new File(pathName);
+
+		// checking the condition of the log file
+		if (logFile.exists()) {
+			if (!logFile.canWrite()) {
+				errMsg(o, "Cannot create the log file: " + pathName, 1);
+				return;
+			}
+		} else { // the log file doesn't exist
+			String parent = logFile.getParent();
+			if (parent == null)
+				parent = System.getProperty("user.dir");
+			File dir = new File(parent);
+			if (!dir.exists()) {
+				errMsg(o,
+						"Cannot create log files in the directory(does not exist): "
+								+ parent, 1);
+				return;
+			}
+			if (dir.isFile()) {
+				errMsg(o,
+						"Cannot create log files in the directory(it is a file): "
+								+ parent, 1);
+				return;
+			}
+			if (!dir.canWrite()) {
+				errMsg(o,
+						"Cannot create log files in the directory(unwritable): "
+								+ parent, 1);
+				return;
+			}
+		}
+
+		PrintStream ps = new PrintStream(new FileOutputStream(pathName, true),
+				true);
+		printMsg(o, s, ps, level);
+	}
+
+	public static void printMsg(Object o, String s, PrintStream ps, int level) {
+		if (level != 0) {
+			ps.println("--------------------------------");
+		}
+		if (o != null) {
+			ps.println(o.getClass().getName() + ": " + s);
+		} else {
+			ps.println(s);
+		}
+		if (level != 0) {
+			ps.println("--------------------------------");
+		}
+		ps.flush();
+	}
+
+	public static void printArray(Object o, Object[] array, String s,
+			PrintStream ps) {
+		ps.println("----- printing an array (from here) -----");
+		int count = array.length;
+		if (o != null) {
+			ps.print(o.getClass().getName() + ": ");
+		}
+		ps.print(s + ": ");
+		ps.println("length= " + count);
+		for (int i = 0; i < count; i++) {
+			ps.println(array[i].toString());
+		}
+		ps.println("----- printing an array (to here) -----");
+	}
+
+	public static void outArray(Object o, Object[] array, String s) {
+		printArray(o, array, s, System.out);
+	}
+
+	public static void errArray(Object o, Object[] array, String s) {
+		printArray(o, array, s, System.err);
+	}
+
+	public static void printVector(Object o, Vector vector, String s,
+			PrintStream ps) {
+		ps.println("----- printing a Vector (from here) -----");
+		int count = vector.size();
+		if (o != null) {
+			ps.print(o.getClass().getName() + ": ");
+		}
+		ps.print(s + ": ");
+		ps.println("size= " + count);
+		for (int i = 0; i < count; i++) {
+			ps.println(vector.elementAt(i).toString());
+		}
+		ps.println("----- printing a Vector (to here) -----");
+	}
+
+	public static void outVector(Object o, Vector vector, String s) {
+		printVector(o, vector, s, System.out);
+	}
+
+	public static void errVectir(Object o, Vector vector, String s) {
+		printVector(o, vector, s, System.err);
+	}
+
+	private static boolean isAbsolutePath(String pathName) {
+		// "/a/..."
+		if (pathName.startsWith(File.separator)) {
+			return (true);
+		}
+		// "c:\\..."
+		if (Character.isLetter(pathName.charAt(0))
+				&& pathName.indexOf(DRIVE_DELIM) == 1
+				&& pathName.indexOf(File.separator) == 2) {
+			return (true);
+		}
+		return (false);
+	}
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/util/DosUtil.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/util/DosUtil.java
new file mode 100644
index 0000000..23987ae
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/util/DosUtil.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision.internal.util;
+
+/*
+ * to handle byte sequence in DOS
+ */
+public class DosUtil{
+    public static int upsideDownInt( int _i ){
+	return(
+	       ((_i>>24)&0x000000ff) |
+	       ((_i>>8)&0x0000ff00) |
+	       ((_i<<8)&0x00ff0000) |
+	       ((_i<<24)&0xff000000)
+	       );
+    }
+
+    public static short upsideDownShort( short _s ){
+	return(
+	       (short)
+	       (((_s>>8)&0x00ff) |
+		((_s<<8)&0xff00))
+	       );
+    }
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/util/LowVisionProblemConverter.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/util/LowVisionProblemConverter.java
new file mode 100644
index 0000000..82c1311
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/util/LowVisionProblemConverter.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.internal.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.actf.visualization.engines.lowvision.problem.ColorProblem;
+import org.eclipse.actf.visualization.engines.lowvision.problem.LowVisionProblem;
+import org.eclipse.actf.visualization.engines.lowvision.problem.LowVisionProblemGroup;
+import org.eclipse.actf.visualization.eval.problem.IProblemItem;
+import org.eclipse.actf.visualization.eval.problem.ProblemItemLV;
+
+
+
+public class LowVisionProblemConverter {
+
+    public static List<IProblemItem> convert(LowVisionProblemGroup[] target, String urlS, int frameId) {
+
+        ArrayList<IProblemItem> result = new ArrayList<IProblemItem>();
+
+        for (int i = 0; i < target.length; i++) {
+
+            ProblemItemLV tmp = new ProblemItemLV("L_" + target[i].getLowVisionProblemType());
+            tmp.setSubType(target[i].getLowVisionProblemType());
+            try {
+                tmp.setDescription(target[i].getDescription());
+            } catch (Exception e) {
+                tmp.setDescription("unknown");
+            }
+            tmp.setCanHighlight(true);
+
+
+            tmp.setFrameId(frameId);
+            tmp.setFrameUrlS(urlS);
+
+            tmp.setSeverityLV(target[i].getIntProbability());
+            tmp.setForegroundS(getLVProblemColorString(target[i], true));
+            tmp.setBackgroundS(getLVProblemColorString(target[i], false));
+            tmp.setX(target[i].getX());
+            tmp.setY(target[i].getY());
+            tmp.setWidth(target[i].getWidth());
+            tmp.setHeight(target[i].getHeight());
+            tmp.setArea(target[i].getWidth() * target[i].getHeight());
+
+            //TODO recommendation            
+            result.add(tmp);
+        }
+
+        return (result);
+    }
+
+    private static String getLVProblemColorString(LowVisionProblemGroup problem, boolean isFore) {
+        short probType;
+        int origAll;
+        int origR;
+        int origG;
+        int origB;
+
+        probType = problem.getLowVisionProblemType();
+
+        if (probType == LowVisionProblem.LOWVISION_COLOR_PROBLEM) {
+            ColorProblem cp = (ColorProblem) (problem.getRepresentative());
+            if (isFore) {
+                origAll = cp.getForegroundColor();
+            } else {
+                origAll = cp.getBackgroundColor();
+            }
+            origR = origAll >> 16 & 0xff;
+            origG = origAll >> 8 & 0xff;
+            origB = origAll & 0xff;
+            return origR + "," + origG + "," + origB;
+        } else {
+            return " ";
+        }
+    }
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/util/ScoreUtil.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/util/ScoreUtil.java
new file mode 100644
index 0000000..debdf95
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/internal/util/ScoreUtil.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.internal.util;
+
+import org.eclipse.actf.visualization.Constants;
+import org.eclipse.actf.visualization.engines.lowvision.internal.Messages;
+
+
+
+public class ScoreUtil {
+
+	static final double MIN_OVERALL_SCORE_A = 5.0;
+
+	static final double MIN_OVERALL_SCORE_B = 30.0;
+
+	static final double VERY_GOOD = 5.0;
+
+	static final double GOOD = 20.0;
+
+	static final double POOR = 30.0;
+        
+	public static String getScoreString(double _score) {
+		if (_score <= VERY_GOOD) {
+			return (Messages.getString("PageEvaluation.Excellent"));
+		} else if (_score <= GOOD) {
+			return (Messages.getString("PageEvaluation.Good"));
+		} else if (_score <= POOR) {
+			return (Messages.getString("PageEvaluation.Poor"));
+		} else {
+			return (Messages.getString("PageEvaluation.Bad"));
+		}
+
+	}
+
+	public static String getScoreImageString(double _score) {
+		if (_score <= VERY_GOOD) {
+			return (Constants.RATING_V_GOOD );
+		} else if (_score <= GOOD) {
+			return (Constants.RATING_GOOD );
+		} else if (_score <= POOR) {
+			return (Constants.RATING_POOR );
+		} else {
+			return (Constants.RATING_BAD);
+		}
+	}
+
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/io/ImageDumpUtil.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/io/ImageDumpUtil.java
new file mode 100644
index 0000000..2086c14
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/io/ImageDumpUtil.java
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.io;
+
+import org.eclipse.actf.visualization.engines.lowvision.image.Int2D;
+import org.eclipse.actf.visualization.engines.lowvision.image.PageImage;
+import org.eclipse.actf.visualization.engines.lowvision.internal.Messages;
+import org.eclipse.actf.visualization.engines.lowvision.internal.io.BMPReader;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.MessageBox;
+import org.eclipse.swt.widgets.Shell;
+
+public class ImageDumpUtil {
+
+	private static boolean LV16BIT = false;
+
+	public static synchronized PageImage joinPageImages(String saveFileName,
+			PageImage[] targets) {
+		Int2D int2dWhole = new Int2D(0, 0);
+		int iWholeWidth = 0;
+		int iWholeHeight = 0;
+
+		if (targets != null && saveFileName != null) {
+			for (int i = 0; i < targets.length; i++) {
+				Int2D tmpInt2d;
+				tmpInt2d = targets[i].getInt2D();
+				if (iWholeWidth < tmpInt2d.width)
+					iWholeWidth = tmpInt2d.width;
+				iWholeHeight += tmpInt2d.height;
+			}
+
+			int2dWhole = new Int2D(iWholeWidth, iWholeHeight);
+
+			try {
+
+				int iDrawY = 0;
+				for (int i = 0; i < targets.length; i++) {
+					Int2D tmpInt2d = targets[i].getInt2D();
+					for (int k = 0; k < tmpInt2d.height; k++) {
+						System.arraycopy(tmpInt2d.data[k], 0,
+								int2dWhole.data[iDrawY + k], 0, tmpInt2d.width);
+					}
+					iDrawY += tmpInt2d.height;
+				}
+
+				int2dWhole.writeToBMPFile(saveFileName);
+			} catch (Exception e) {
+				e.printStackTrace();
+			}
+		}
+		return (new PageImage(int2dWhole));
+	}
+
+	static public PageImage createPageImage(String bmpFileName, Shell _shell) {
+
+		// TODO without file
+		Int2D int2dWhole = new Int2D(0, 0);
+
+		try {
+			int2dWhole = Int2D.readFromBMPFile(bmpFileName);
+			PageImage result = new PageImage(int2dWhole);
+			int2dWhole = null;
+
+			try {
+				LV16BIT = BMPReader.getBitCount(bmpFileName) == 16;
+			} catch (Exception e2) {
+				// TODO
+				LV16BIT = true;
+			}
+
+			return (result);
+		} catch (Exception e) {
+			MessageBox box1 = new MessageBox(_shell, SWT.OK | SWT.ICON_WARNING);
+			box1.setMessage(Messages.getString("ImageDumpUtil.TrueColor"));
+			box1.open();
+		}
+
+		return (null);
+	}
+
+	public static boolean isLV16BIT() {
+		return LV16BIT;
+	}
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/io/ImageReader.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/io/ImageReader.java
new file mode 100644
index 0000000..3073ef7
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/io/ImageReader.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision.io;
+
+import java.awt.image.BufferedImage;
+
+import org.eclipse.actf.visualization.engines.lowvision.image.BinaryImage;
+import org.eclipse.actf.visualization.engines.lowvision.image.ImageException;
+import org.eclipse.actf.visualization.engines.lowvision.image.ImageUtil;
+import org.eclipse.actf.visualization.engines.lowvision.image.Int2D;
+import org.eclipse.actf.visualization.engines.lowvision.internal.io.BMPReader;
+import org.eclipse.actf.visualization.engines.lowvision.internal.io.ImageFileReader;
+import org.eclipse.actf.visualization.engines.lowvision.internal.io.JPEGReader;
+import org.eclipse.actf.visualization.engines.lowvision.internal.io.PBMReader;
+
+public class ImageReader {
+	public static BufferedImage readBufferedImage(String _fileName)
+			throws LowVisionIOException {
+		short type = IoUtil.getFileType(_fileName);
+		if (type != IoUtil.TYPE_UNKNOWN)
+			return (readBufferedImage(_fileName, type));
+		else
+			throw new LowVisionIOException("Unknown image format: _fileName");
+	}
+
+	public static BufferedImage readBufferedImage(String _fileName, short _type)
+			throws LowVisionIOException {
+		BufferedImage bufIm = null;
+		if (_type == IoUtil.TYPE_BMP) {
+			bufIm = BMPReader.readBufferedImage(_fileName);
+		} else if (_type == IoUtil.TYPE_JPEG) {
+			bufIm = JPEGReader.readBufferedImage(_fileName);
+		} else if (_type == IoUtil.TYPE_GIF) {
+			bufIm = ImageFileReader.readBufferedImage(_fileName);
+		} else if (_type == IoUtil.TYPE_PNG) {
+			bufIm = ImageFileReader.readBufferedImage(_fileName);
+		} else {
+			throw new LowVisionIOException("Unknown image format: _fileName");
+		}
+
+		if (bufIm == null) {
+			throw new LowVisionIOException("The image file cannot be read: "
+					+ _fileName);
+		}
+		return (bufIm);
+	}
+
+	public static Int2D readInt2D(String _fileName) throws LowVisionIOException {
+		try {
+			return (ImageUtil
+					.bufferedImageToInt2D(readBufferedImage(_fileName)));
+		} catch (ImageException e) {
+			e.printStackTrace();
+			throw new LowVisionIOException(
+					"ImageException occurred while converting BufferedImage into Int2D.");
+		}
+	}
+
+	public static Int2D readInt2D(String _fileName, short _type)
+			throws LowVisionIOException {
+		try {
+			return (ImageUtil.bufferedImageToInt2D(readBufferedImage(_fileName,
+					_type)));
+		} catch (ImageException e) {
+			e.printStackTrace();
+			throw new LowVisionIOException(
+					"ImageException occurred while converting BufferedImage into Int2D.");
+		}
+	}
+
+	public static BinaryImage readBinaryImage(String _fileName)
+			throws LowVisionIOException {
+		short type = IoUtil.getFileType(_fileName);
+		if (type != IoUtil.TYPE_UNKNOWN)
+			return (readBinaryImage(_fileName, type));
+		else
+			throw new LowVisionIOException("Unknown image format.");
+	}
+
+	public static BinaryImage readBinaryImage(String _fileName, short _type)
+			throws LowVisionIOException {
+		if (_type == IoUtil.TYPE_PBM)
+			return (PBMReader.readBinaryImage(_fileName));
+		else
+			throw new LowVisionIOException("Unknown image format.");
+	}
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/io/ImageReader14.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/io/ImageReader14.java
new file mode 100644
index 0000000..de97b87
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/io/ImageReader14.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision.io;
+
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+
+import org.eclipse.actf.visualization.engines.lowvision.image.BinaryImage;
+import org.eclipse.actf.visualization.engines.lowvision.image.ImageException;
+import org.eclipse.actf.visualization.engines.lowvision.image.ImageUtil;
+import org.eclipse.actf.visualization.engines.lowvision.image.Int2D;
+import org.eclipse.actf.visualization.engines.lowvision.internal.io.BMPReader;
+import org.eclipse.actf.visualization.engines.lowvision.internal.io.PBMReader;
+
+public class ImageReader14 {
+
+	// TBD ImageType conversion for BufferdImage (gif: ImageIO.read() ->
+	// BufferedImage (TYPE_BYTE_INDEXED))
+
+	public static BufferedImage readBufferedImage(String _fileName)
+			throws LowVisionIOException {
+		short type = IoUtil.getFileType(_fileName);
+		if (type != IoUtil.TYPE_UNKNOWN)
+			return (readBufferedImage(_fileName, type));
+		else
+			throw new LowVisionIOException("Unknown image format: _fileName");
+	}
+
+	public static BufferedImage readBufferedImage(String _fileName, short _type)
+			throws LowVisionIOException {
+		BufferedImage bufIm = null;
+		if (_type == IoUtil.TYPE_BMP) {
+			bufIm = BMPReader.readBufferedImage(_fileName);
+		} else if (_type == IoUtil.TYPE_JPEG) {
+			try {
+				bufIm = ImageIO.read(new File(_fileName));
+			} catch (IOException ioe) {
+				throw new LowVisionIOException("File \"" + _fileName
+						+ "\" cannot be read.");
+			}
+		} else if (_type == IoUtil.TYPE_GIF) {
+			try {
+				bufIm = ImageIO.read(new File(_fileName));
+			} catch (IOException ioe) {
+				throw new LowVisionIOException("File \"" + _fileName
+						+ "\" cannot be read.");
+			}
+		} else if (_type == IoUtil.TYPE_PNG) {
+			try {
+				bufIm = ImageIO.read(new File(_fileName));
+			} catch (IOException ioe) {
+				throw new LowVisionIOException("File \"" + _fileName
+						+ "\" cannot be read.");
+			}
+		} else {
+			throw new LowVisionIOException("Unknown image format: _fileName");
+		}
+
+		if (bufIm == null) {
+			throw new LowVisionIOException("The image file cannot be read: "
+					+ _fileName);
+		}
+		return (bufIm);
+	} 
+
+	public static Int2D readInt2D(String _fileName) throws LowVisionIOException {
+		try {
+			return (ImageUtil
+					.bufferedImageToInt2D(readBufferedImage(_fileName)));
+		} catch (ImageException e) {
+			e.printStackTrace();
+			throw new LowVisionIOException(
+					"ImageException occurred while converting BufferedImage into Int2D.");
+		}
+	}
+
+	public static Int2D readInt2D(String _fileName, short _type)
+			throws LowVisionIOException {
+		try {
+			return (ImageUtil.bufferedImageToInt2D(readBufferedImage(_fileName,
+					_type)));
+		} catch (ImageException e) {
+			e.printStackTrace();
+			throw new LowVisionIOException(
+					"ImageException occurred while converting BufferedImage into Int2D.");
+		}
+	}
+
+	public static BinaryImage readBinaryImage(String _fileName)
+			throws LowVisionIOException {
+		short type = IoUtil.getFileType(_fileName);
+		if (type != IoUtil.TYPE_UNKNOWN)
+			return (readBinaryImage(_fileName, type));
+		else
+			throw new LowVisionIOException("Unknown image format.");
+	}
+
+	public static BinaryImage readBinaryImage(String _fileName, short _type)
+			throws LowVisionIOException {
+		if (_type == IoUtil.TYPE_PBM)
+			return (PBMReader.readBinaryImage(_fileName));
+		else
+			throw new LowVisionIOException("Unknown image format."); 
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/io/ImageWriter.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/io/ImageWriter.java
new file mode 100644
index 0000000..bc535e7
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/io/ImageWriter.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision.io;
+
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+
+import org.eclipse.actf.visualization.engines.lowvision.image.BinaryImage;
+import org.eclipse.actf.visualization.engines.lowvision.image.ImageUtil;
+import org.eclipse.actf.visualization.engines.lowvision.image.Int2D;
+import org.eclipse.actf.visualization.engines.lowvision.internal.io.BMPWriter;
+import org.eclipse.actf.visualization.engines.lowvision.internal.io.JPEGWriter;
+import org.eclipse.actf.visualization.engines.lowvision.internal.io.PBMWriter;
+
+public class ImageWriter {
+	public static void writeBufferedImage(BufferedImage _bi, String _fileName)
+			throws LowVisionIOException {
+		short type = IoUtil.getFileType(_fileName);
+		if (type != IoUtil.TYPE_UNKNOWN)
+			writeBufferedImage(_bi, _fileName, type);
+		else
+			throw new LowVisionIOException("Unknown image format.");
+	}
+
+	public static void writeBufferedImage(BufferedImage _bi, String _fileName,
+			short _type) throws LowVisionIOException {
+		if (_type == IoUtil.TYPE_BMP)
+			BMPWriter.writeBufferedImage(_bi, _fileName);
+		else if (_type == IoUtil.TYPE_JPEG)
+			JPEGWriter.writeBufferedImage(_bi, _fileName);
+		else if (_type == IoUtil.TYPE_GIF) {
+			File outFile = new File(_fileName);
+			boolean result = true;
+			try {
+				result = ImageIO.write(_bi, "GIF", outFile);
+			} catch (IOException ioe) {
+				ioe.printStackTrace();
+				throw new LowVisionIOException(
+						"An error occurs while writing a GIF image.");
+			}
+			if (!result) {
+				throw new LowVisionIOException(
+						"No appropriate writer is found while writing a GIF image.");
+			}
+			// throw new LowVisionIOException("This file format cannot be
+			// written out.");
+		} else if (_type == IoUtil.TYPE_PNG) {
+			File outFile = new File(_fileName);
+			boolean result = true;
+			try {
+				result = ImageIO.write(_bi, "PNG", outFile);
+			} catch (IOException ioe) {
+				ioe.printStackTrace();
+				throw new LowVisionIOException(
+						"An error occurs while writing a PNG image.");
+			}
+			if (!result) {
+				throw new LowVisionIOException(
+						"No appropriate writer is found while writing a PNG image.");
+			}
+			// throw new LowVisionIOException("This file format cannot be
+			// written out.");
+		} else
+			throw new LowVisionIOException("Unknown image format.");
+	}
+
+	public static void writeInt2D(Int2D _i2d, String _fileName)
+			throws LowVisionIOException {
+		writeBufferedImage(ImageUtil.int2DToBufferedImage(_i2d), _fileName);
+	}
+
+	public static void writeInt2D(Int2D _i2d, String _fileName, short _type)
+			throws LowVisionIOException {
+		writeBufferedImage(ImageUtil.int2DToBufferedImage(_i2d), _fileName,
+				_type);
+	}
+
+	public static void writeBinaryImage(BinaryImage _bi, String _fileName)
+			throws LowVisionIOException {
+		short type = IoUtil.getFileType(_fileName);
+		if (type != IoUtil.TYPE_UNKNOWN)
+			writeBinaryImage(_bi, _fileName, type);
+		else
+			throw new LowVisionIOException("Unknown image format.");
+	}
+
+	public static void writeBinaryImage(BinaryImage _bi, String _fileName,
+			short _type) throws LowVisionIOException {
+		if (_type == IoUtil.TYPE_PBM)
+			PBMWriter.writeBinaryImage(_bi, _fileName);
+		else
+			throw new LowVisionIOException("Unknown image format.");
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/io/IoUtil.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/io/IoUtil.java
new file mode 100644
index 0000000..4b2ce19
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/io/IoUtil.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.io;
+
+public class IoUtil {
+	public static final short TYPE_UNKNOWN = 0;
+
+	public static final short TYPE_BMP = 1;
+
+	public static final short TYPE_DIB = 1; // same as BMP
+
+	public static final short TYPE_JPEG = 2;
+
+	public static final short TYPE_PBM = 3; // Magic number = "P1"
+
+	// public static final short TYPE_PBMRAW = 4; // Magic number = "P4"
+	
+	public static final short TYPE_GIF = 5;
+
+	public static final short TYPE_PNG = 6;
+
+	public static short getFileType(String _fileName) {
+		if (_fileName == null)
+			return (TYPE_UNKNOWN);
+		int ind = _fileName.lastIndexOf(".");
+		if (ind == -1)
+			return (TYPE_UNKNOWN);
+		String ext = _fileName.substring(ind + 1).toLowerCase();
+		if (ext.equals("bmp"))
+			return (TYPE_BMP);
+		else if (ext.equals("dib"))
+			return (TYPE_BMP);
+		else if (ext.equals("jpg") || ext.equals("jpeg"))
+			return (TYPE_JPEG);
+		else if (ext.equals("pbm"))
+			return (TYPE_PBM);
+		else if (ext.equals("gif"))
+			return (TYPE_GIF);
+		else if (ext.equals("png"))
+			return (TYPE_PNG);
+		else
+			return (TYPE_UNKNOWN);
+	}
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/io/LowVisionIOException.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/io/LowVisionIOException.java
new file mode 100644
index 0000000..25e121f
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/io/LowVisionIOException.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.io;
+
+public class LowVisionIOException extends Exception{
+	private static final long serialVersionUID = 5761285571988623445L;
+
+	public LowVisionIOException(){
+		super();
+	}
+	public LowVisionIOException( String _s ){
+		super(_s);
+	}
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/operator/BlurOp.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/operator/BlurOp.java
new file mode 100644
index 0000000..7b588a4
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/operator/BlurOp.java
@@ -0,0 +1,164 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *    Daisuke SATO - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision.operator;
+
+import java.awt.image.BufferedImage;
+import java.awt.image.ConvolveOp;
+import java.awt.image.Kernel;
+import java.awt.image.Raster;
+import java.awt.image.WritableRaster;
+
+import org.eclipse.actf.visualization.engines.lowvision.LowVisionType;
+
+public class BlurOp implements ILowVisionOperator {
+	private ConvolveOp cop = null;
+
+	public BlurOp(LowVisionType _lvType) {
+		double pixel = _lvType.getEyesightPixel();
+
+		int cPixel = (int) (Math.ceil(pixel));
+		int fPixel = (int) (Math.floor(pixel));
+
+		// ---square---
+
+		int arrayWidth = 2 * (cPixel) + 1;
+		double[][] blurArray = new double[arrayWidth][arrayWidth];
+		if (cPixel == fPixel) {
+			double area = (double) (arrayWidth * arrayWidth);
+			for (int j = 0; j < arrayWidth; j++) {
+				for (int i = 0; i < arrayWidth; i++) {
+					blurArray[j][i] = 1.0 / area;
+				}
+			}
+		} else if (cPixel == fPixel + 1) {
+			double dicimal = pixel - fPixel;
+			double area = (double) ((2.0 * pixel + 1.0) * (2.0 * pixel + 1.0));
+
+			double centerValue = 1.0 / area;
+			for (int j = 1; j < arrayWidth - 1; j++) {
+				for (int i = 1; i < arrayWidth - 1; i++) {
+					blurArray[j][i] = centerValue;
+				}
+			}
+
+			double edgeValue = dicimal / area;
+			for (int j = 1; j < arrayWidth - 1; j++) {
+				blurArray[j][0] = edgeValue;
+				blurArray[j][arrayWidth - 1] = edgeValue;
+				blurArray[0][j] = edgeValue;
+				blurArray[arrayWidth - 1][j] = edgeValue;
+			}
+
+			double cornerValue = dicimal * dicimal / area;
+			blurArray[0][0] = cornerValue;
+			blurArray[0][arrayWidth - 1] = cornerValue;
+			blurArray[arrayWidth - 1][0] = cornerValue;
+			blurArray[arrayWidth - 1][arrayWidth - 1] = cornerValue;
+
+			// ---square---
+
+			// use octagon
+			double temp = blurArray[0][0] * 4;
+			double cornerHalf = 0;// blurArray[0][0] / 2.0;
+			blurArray[0][0] = cornerHalf;
+			blurArray[0][arrayWidth - 1] = cornerHalf;
+			blurArray[arrayWidth - 1][0] = cornerHalf;
+			blurArray[arrayWidth - 1][arrayWidth - 1] = cornerHalf;
+			blurArray[arrayWidth / 2][arrayWidth / 2] += temp;
+			// (cornerHalf * 4.0);
+		} else {
+			// assert
+		}
+
+		float[] element = new float[arrayWidth * arrayWidth];
+		int k = 0;
+		for (int j = 0; j < arrayWidth; j++) {
+			for (int i = 0; i < arrayWidth; i++) {
+				element[k] = (float) (blurArray[j][i]);
+				k++;
+			}
+		}
+		Kernel kernel = new Kernel(arrayWidth, arrayWidth, element);
+		cop = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
+
+	}
+
+	public BufferedImage filter(BufferedImage _src, BufferedImage _dest) {
+		return newFilter(_src, _dest); // by daisuke
+		// return (cop.filter(_src, _dest)); // by maeda
+	}
+
+	private BufferedImage newFilter(BufferedImage _src, BufferedImage _dest) {
+		if (_dest == null) {
+			_dest = new BufferedImage(_src.getWidth(), _src.getHeight(), _src
+					.getType());
+		}
+
+		Kernel karnel = cop.getKernel();
+		int w = karnel.getWidth();
+		int h = karnel.getHeight();
+		float[] d = new float[w * h];
+		karnel.getKernelData(d);
+
+		int width = _src.getWidth();
+		int height = _src.getHeight();
+
+		double N = 1.005;
+
+		double[] pow = new double[256];
+		for (int i = 0; i < pow.length; i++) {
+			pow[i] = Math.pow(N, i);
+		}
+		double logN = Math.log(N);
+
+		for (int x = 0; x < width; x++) {
+			for (int y = 0; y < height; y++) {
+				double dr = 0, dg = 0, db = 0;
+
+				for (int xx = 0; xx < w; xx++) {
+					for (int yy = 0; yy < h; yy++) {
+						int xxx = x + xx - w / 2;
+						int yyy = y + yy - h / 2;
+						xxx = xxx > 0 ? xxx : 0;
+						xxx = xxx >= width ? width - 1 : xxx;
+						yyy = yyy > 0 ? yyy : 0;
+						yyy = yyy >= height ? height - 1 : yyy;
+
+						int rgb = _src.getRGB(xxx, yyy);
+						int ir = (rgb & 0xFF0000) >> 16;
+						int ig = (rgb & 0x00FF00) >> 8;
+						int ib = (rgb & 0x0000FF);
+
+						dr += pow[ir] * d[xx * w + yy];
+						dg += pow[ig] * d[xx * w + yy];
+						db += pow[ib] * d[xx * w + yy];
+					}
+				}
+				int ir = (int) (Math.log(dr) / logN);
+				int ig = (int) (Math.log(dg) / logN);
+				int ib = (int) (Math.log(db) / logN);
+
+				ir = ir > 255 ? 255 : ir;
+				ig = ig > 255 ? 255 : ig;
+				ib = ib > 255 ? 255 : ib;
+
+				_dest.setRGB(x, y, (ir << 16) + (ig << 8) + ib);
+			}
+		}
+
+		return _dest;
+	}
+
+	public WritableRaster filter(Raster _src, WritableRaster _dest) {
+		return (cop.filter(_src, _dest));
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/operator/CVDOp.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/operator/CVDOp.java
new file mode 100644
index 0000000..f6e5182
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/operator/CVDOp.java
@@ -0,0 +1,238 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision.operator;
+
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBufferInt;
+import java.awt.image.WritableRaster;
+import java.util.HashMap;
+
+import org.eclipse.actf.visualization.engines.lowvision.LowVisionException;
+import org.eclipse.actf.visualization.engines.lowvision.color.ColorException;
+import org.eclipse.actf.visualization.engines.lowvision.color.ColorIRGB;
+import org.eclipse.actf.visualization.engines.lowvision.color.ColorSRGB;
+import org.eclipse.actf.visualization.engines.lowvision.color.ColorYXY;
+import org.eclipse.actf.visualization.engines.lowvision.image.Int2D;
+
+/*
+ * simulate color vision deficiency
+ */
+public class CVDOp implements ILowVisionOperator{
+	// keep Y(0.299R+0.587G+0.114B) in sRGB (I in HSI) or not
+	// false is better
+    private static final boolean PRESERVE_SRGB_Y = false;
+
+    // see ColorValue.java
+    // these values are for (Y,x,y) (not for (x,y,z))
+    // (Y,x,y)space : (x,y,z)space
+    // Y(YY) : y
+    // x : x/(x+y+z)
+    // y : y/(x+y+z)
+
+    // sRGB->CIEXYZ->Yxy
+    @SuppressWarnings("unused")
+    private static final float R_YY = 0.21347046f, 
+    R_X  = 0.6524872f,  
+    R_Y  = 0.32519758f, 
+    G_YY = 0.71173096f, 
+    G_X  = 0.3305722f,  
+    G_Y  = 0.5944182f,  
+    B_YY = 0.07168579f, 
+    B_X  = 0.1482494f,  
+    B_Y  = 0.07736899f, 
+    W_YY = 0.9963379f,  
+    W_X  = 0.34579438f, 
+    W_Y  = 0.35854465f; 
+
+    private static final float C1_X = 0.747f;  // Protan line
+    private static final float C1_Y = 0.253f;  // 
+    private static final float C2_X = 1.080f;  // Deutan line
+    private static final float C2_Y = -0.080f; // 
+    private static final float C3_X = 0.171f;  // Tritan line
+    private static final float C3_Y = 0.000f;  // 
+
+	private static float BW_A = (B_Y-W_Y)/(B_X-W_X);// blue-white line in (x,y)
+	private static float BW_B = B_Y-BW_A*B_X;
+	// private static float BR_A = (B_Y-R_Y)/(B_X-R_X);//blue-red line in (x,y)
+	// private static float BR_B = B_Y-BR_A*B_X;
+	private static float BR_A = -0.5f;  // blue-red line (cross white)
+	private static float BR_B = 0.525f; //
+
+    private int type = 0; 
+
+    public CVDOp( int _type ){
+		type = _type;
+    }
+
+    public BufferedImage filter( BufferedImage _src, BufferedImage _dest ) throws LowVisionException{
+		if( type != 1 && type != 2 && type != 3 ){
+			throw new LowVisionException( "Invalid type: " + type );
+		}
+	
+		WritableRaster srcRaster = _src.copyData( null );
+		DataBufferInt srcBufInt = (DataBufferInt)(srcRaster.getDataBuffer());
+		int[] srcArray = srcBufInt.getData();
+		int srcSize = srcArray.length;
+	
+		BufferedImage destImage = _dest;
+		if( _dest == null ){
+		    destImage = new BufferedImage( _src.getWidth(), _src.getHeight(), BufferedImage.TYPE_INT_RGB );
+		}
+		WritableRaster destRaster = destImage.copyData( null );
+		DataBufferInt destBufInt = (DataBufferInt)(destRaster.getDataBuffer());
+		int[] destArray = destBufInt.getData();
+		int destSize = destArray.length;
+		if( srcSize != destSize ){
+		    throw new LowVisionException( "Sizes of src and dest images differ." );
+		}
+	
+		HashMap<Integer, Integer> pixelMap = new HashMap<Integer, Integer>();
+		for( int i=0; i<srcSize; i++ ){
+		    Integer srcPixel = new Integer( srcArray[i] );
+		    Integer destPixel = null;
+		    if( (destPixel=(Integer)(pixelMap.get(srcPixel))) == null ){
+		    	destPixel = new Integer( convertColor(srcArray[i],type) );
+				pixelMap.put( srcPixel, destPixel );
+		    }
+		    destArray[i] = destPixel.intValue();
+		}
+	
+		destImage.setData( destRaster );
+		return( destImage );
+    } // filter( BufferedImage, BufferedImage )
+
+	public Int2D filter( Int2D _src, Int2D _dest ) throws LowVisionException{
+		if( type != 1 && type != 2 && type != 3 ){
+			throw new LowVisionException( "Invalid type: " + type );
+		}
+		
+		Int2D destImage = _dest;
+		if( _dest == null ){
+			destImage = new Int2D( _src.width, _src.height );
+		}
+
+		HashMap<Integer, Integer> pixelMap = new HashMap<Integer, Integer>();
+		for( int j=0; j<_src.height; j++ ){
+			for( int i=0; i<_src.width; i++ ){
+				int srcColor =_src.data[j][i];
+				Integer srcPixel = new Integer( srcColor );
+				Integer destPixel  = (Integer)(pixelMap.get(srcPixel));
+				if( destPixel == null ){ 
+					int destColor = convertColor( srcColor, type );
+					destImage.data[j][i] = destColor;
+					pixelMap.put( srcPixel, new Integer(destColor) );
+				}
+				else{ 
+					destImage.data[j][i] = destPixel.intValue();
+				}
+			}
+		}
+		return( destImage );
+	} 
+
+	public static int convertColor( int _src, int _type ) throws LowVisionException{
+		try{
+			if( PRESERVE_SRGB_Y ){
+				ColorSRGB srgb = (new ColorIRGB( _src )).toSRGB();
+				// float preservedY = 0.299f*srgb.getR() + 0.587f*srgb.getG() +
+				// 0.114f*srgb.getB();
+				float preservedY = Math.max( srgb.getR(), Math.max( srgb.getG(), srgb.getB() ) );
+				ColorYXY yxy = srgb.toYXY();
+				// move (x,y) while keeping brightness (yy)
+				ColorYXY newYXY = moveXY( yxy, _type );
+				ColorSRGB newSRGB = newYXY.toSRGB();
+				float newR = newSRGB.getR();
+				float newG = newSRGB.getG();
+				float newB = newSRGB.getB();
+				// float newY = 0.299f*newR + 0.587f*newG + 0.114f*newB;
+				float newY = Math.max( newR, Math.max( newG, newB ) );
+				float ratio = 0.0f;
+				if( newY != 0.0f )
+					ratio = preservedY/newY;
+				else
+					ratio = 1.0f; // black
+				newSRGB.setR( newR*ratio );
+				newSRGB.setG( newG*ratio );
+				newSRGB.setB( newB*ratio );
+				return( newSRGB.toIRGB().toInt() );
+			}
+			else{
+				ColorIRGB irgb = new ColorIRGB( _src );
+				ColorYXY yxy = irgb.toYXY();
+				// move (x,y) while keeping brightness (yy)
+				ColorYXY newYXY = moveXY( yxy, _type );
+				ColorIRGB newIRGB = newYXY.toIRGB();				
+				return( newIRGB.toInt() );
+			}
+		}catch( ColorException ce ){
+			ce.printStackTrace();
+			throw new LowVisionException( "ColorException occurred while converting color.");
+		}
+	}
+
+	// move (x,y) while keeping brightness (yy)
+    private static ColorYXY moveXY( ColorYXY _src, int _type ) throws LowVisionException, ColorException{
+		float srcYY = _src.getYY();
+		float srcX = _src.getX();
+		float srcY = _src.getY();
+		float confuseX = 0.0f;
+		float confuseY = 0.0f;
+		float locusA = 0.0f;
+		float locusB = 0.0f;
+		if( _type == 1 ){      
+		    confuseX = C1_X;
+		    confuseY = C1_Y;
+		    locusA = BW_A;
+		    locusB = BW_B;
+		}
+		else if( _type == 2 ){ 
+		    confuseX = C2_X;
+		    confuseY = C2_Y;
+		    locusA = BW_A;
+		    locusB = BW_B;
+		}
+		else if( _type == 3 ){ 
+		    confuseX = C3_X;
+		    confuseY = C3_Y;
+		    locusA = BR_A;
+		    locusB = BR_B;
+		}
+		else{
+		    throw new LowVisionException( "Invalid type : " + _type );
+		}
+	
+		float destYY = srcYY;
+		float destX = 0.0f;
+		float destY = 0.0f;
+		if( confuseX != srcX ){ 
+		    float confuseA = (confuseY-srcY)/(confuseX-srcX); // slope
+		    float confuseB = confuseY - confuseA*confuseX;    // y-intercept
+
+		    if( confuseA != locusA ){ 
+			destX = (confuseB-locusB)/(locusA-confuseA);
+			destY = (locusA*confuseB-confuseA*locusB)/(locusA-confuseA);
+		    }
+		    else{                     
+		    	// TBD use polar coordinates, etc.
+   			    /*
+				 * destX = srcX; destY = srcY; debugUtil.errMsg( this, "(x,y) is
+				 * out of sRGB's range. (x,y) = " + srcX + ", " + srcY );
+				 */
+			throw new LowVisionException( "(x,y) is out of sRGB's range. (x,y) = " + srcX + ", " + srcY );
+		    }
+		} else{
+		    destX = confuseX;
+		    destY = confuseX*locusA + locusB;
+		}
+	
+		return( new ColorYXY( destYY, destX, destY ) );
+   } 
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/operator/ColorFilterOp.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/operator/ColorFilterOp.java
new file mode 100644
index 0000000..01aab11
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/operator/ColorFilterOp.java
@@ -0,0 +1,149 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision.operator;
+
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBufferInt;
+import java.awt.image.WritableRaster;
+import java.util.HashMap;
+
+import org.eclipse.actf.visualization.engines.lowvision.LowVisionException;
+import org.eclipse.actf.visualization.engines.lowvision.image.Int2D;
+
+/*
+ * simulate cataract (RGB)
+ */
+public class ColorFilterOp implements ILowVisionOperator {
+	private float redRatio = 1.0f; // [0.0, 1.0]
+	private float greenRatio = 0.9f; // [0.0, 1.0]
+	private float blueRatio = 0.6f; // [0.0, 1.0]
+
+	public float getRedRatio() {
+		return (redRatio);
+	}
+
+	public void setRedRatio(float _rf) throws LowVisionException {
+		if (_rf < 0.0f || 1.0f < _rf)
+			throw new LowVisionException("Ratio is out of range: " + _rf);
+		redRatio = _rf;
+	}
+
+	public float getGreenRatio() {
+		return (greenRatio);
+	}
+
+	public void setGreenRatio(float _gf) throws LowVisionException {
+		if (_gf < 0.0f || 1.0f < _gf)
+			throw new LowVisionException("Ratio is out of range: " + _gf);
+		greenRatio = _gf;
+	}
+
+	public float getBlueRatio() {
+		return (blueRatio);
+	}
+
+	public void setBlueRatio(float _bf) throws LowVisionException {
+		if (_bf < 0.0f || 1.0f < _bf)
+			throw new LowVisionException("Ratio is out of range: " + _bf);
+		blueRatio = _bf;
+	}
+
+	public void setRatio(float[] _rgb) throws LowVisionException {
+		if (_rgb.length < 3)
+			throw new LowVisionException("Array is to small.");
+		setRedRatio(_rgb[0]);
+		setGreenRatio(_rgb[1]);
+		setBlueRatio(_rgb[2]);
+	}
+
+	public BufferedImage filter(BufferedImage _src, BufferedImage _dest)
+			throws LowVisionException {
+		WritableRaster srcRaster = _src.copyData(null);
+		DataBufferInt srcBufInt = (DataBufferInt) (srcRaster.getDataBuffer());
+		int[] srcArray = srcBufInt.getData();
+		int srcSize = srcArray.length;
+
+		BufferedImage destImage = _dest;
+		if (_dest == null) {
+			destImage = new BufferedImage(_src.getWidth(), _src.getHeight(),
+					BufferedImage.TYPE_INT_RGB);
+		}
+		WritableRaster destRaster = destImage.copyData(null);
+		DataBufferInt destBufInt = (DataBufferInt) (destRaster.getDataBuffer());
+		int[] destArray = destBufInt.getData();
+		int destSize = destArray.length;
+		if (srcSize != destSize) {
+			throw new LowVisionException("Sizes of src and dest images differ.");
+		}
+
+		HashMap<Integer, Integer> pixelMap = new HashMap<Integer, Integer>();
+		for (int i = 0; i < srcSize; i++) {
+			Integer srcPixel = new Integer(srcArray[i]);
+			Integer destPixel = null;
+			if ((destPixel = (Integer) (pixelMap.get(srcPixel))) == null) {
+				destPixel = new Integer(convertColor(srcArray[i], redRatio,
+						greenRatio, blueRatio));
+				pixelMap.put(srcPixel, destPixel);
+			}
+			destArray[i] = destPixel.intValue();
+		}
+
+		destImage.setData(destRaster);
+		return (destImage);
+	} 
+
+	public Int2D filter(Int2D _src, Int2D _dest) throws LowVisionException {
+		Int2D destImage = _dest;
+		if (_dest == null) {
+			destImage = new Int2D(_src.width, _src.height);
+		}
+
+		HashMap<Integer, Integer> pixelMap = new HashMap<Integer, Integer>();
+		for (int j = 0; j < _src.height; j++) {
+			for (int i = 0; i < _src.width; i++) {
+				int srcColor = _src.data[j][i];
+				Integer srcPixel = new Integer(srcColor);
+				Integer destPixel = (Integer) (pixelMap.get(srcPixel));
+				if (destPixel == null) {
+					int destColor = convertColor(srcColor, redRatio,
+							greenRatio, blueRatio);
+					destImage.data[j][i] = destColor;
+					pixelMap.put(srcPixel, new Integer(destColor));
+				} else {
+					destImage.data[j][i] = destPixel.intValue();
+				}
+			}
+		}
+		return (destImage);
+	}
+
+	public static int convertColor(int _src, float _rRatio, float _gRatio,
+			float _bRatio) throws LowVisionException {
+		int pixel = _src;
+		int b = pixel & 0xff;
+		int newB = Math.round((float) b * _bRatio);
+		if (newB < 0 || 255 < newB)
+			throw new LowVisionException("New blue value is out of range: "
+					+ newB);
+		int g = pixel >> 8 & 0xff;
+		int newG = Math.round((float) g * _gRatio);
+		if (newG < 0 || 255 < newG)
+			throw new LowVisionException("New green value is out of range: "
+					+ newG);
+		int r = pixel >> 16 & 0xff;
+		int newR = Math.round((float) r * _rRatio);
+		if (newR < 0 || 255 < newR)
+			throw new LowVisionException("New red value is out of range: "
+					+ newR);
+		pixel = pixel & 0xff000000 | newR << 16 | newG << 8 | newB;
+		return (pixel);
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/operator/FieldOp.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/operator/FieldOp.java
new file mode 100644
index 0000000..646e15b
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/operator/FieldOp.java
@@ -0,0 +1,145 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision.operator;
+
+import java.awt.AlphaComposite;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBufferInt;
+import java.awt.image.WritableRaster;
+
+import org.eclipse.actf.visualization.engines.lowvision.LowVisionException;
+
+/*
+ * field of view
+ * 
+ */
+public class FieldOp implements ILowVisionOperator {
+	public static final short TYPE_CIRCLE_INT = 1; // number of pixels
+
+	public static final short TYPE_CIRCLE_FLOAT = 2; // ratio of circle to
+														// image
+
+	public static final float CIRCLE_WIDTH = 20.0f; // blur width
+
+	BufferedImage filterImage;
+
+	short type = 0;
+
+	int diameterInt;
+
+	float diameterFloat;
+
+	public FieldOp(short _type) {
+		type = _type;
+	}
+
+	public FieldOp(short _type, int _param1) throws LowVisionException {
+		this(_type);
+		if (type == TYPE_CIRCLE_INT) {
+			diameterInt = _param1;
+		} else {
+			throw new LowVisionException(
+					"The type is unknown, or the type and the parameter(s) do not match: type = "
+							+ _type + ", param = " + _param1);
+		}
+	}
+
+	public FieldOp(short _type, float _param1) throws LowVisionException {
+		this(_type);
+		if (type == TYPE_CIRCLE_FLOAT) {
+			diameterFloat = _param1;
+		} else {
+			throw new LowVisionException(
+					"The type is unknown, or the type and the parameter(s) do not match: type = "
+							+ _type + ", param = " + _param1);
+		}
+	}
+
+	public BufferedImage filter(BufferedImage _src, BufferedImage _dest)
+			throws LowVisionException {
+		int width = _src.getWidth();
+		int height = _src.getHeight();
+		createFilterImage(type, width, height);
+
+		BufferedImage destImage = _dest;
+		if (_dest == null)
+			destImage = new BufferedImage(width, height,
+					BufferedImage.TYPE_INT_RGB);
+		Graphics2D g2d = destImage.createGraphics();
+		g2d.drawImage(_src, null, 0, 0);
+		AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER);
+		g2d.setComposite(ac);
+		g2d.drawImage(filterImage, null, 0, 0);
+
+		return (destImage);
+	}
+
+	private void createFilterImage(short _type, int _width, int _height)
+			throws LowVisionException {
+		filterImage = new BufferedImage(_width, _height,
+				BufferedImage.TYPE_INT_ARGB);
+
+		WritableRaster filterRaster = filterImage.copyData(null);
+		DataBufferInt filterBufInt = (DataBufferInt) (filterRaster
+				.getDataBuffer());
+		int[] filterArray = filterBufInt.getData();
+		int[][] alphaField = null;
+
+		if (_type == TYPE_CIRCLE_INT) {
+			alphaField = getCircleAlphaField(_width, _height,
+					(float) diameterInt / (float) _width);
+		} else if (_type == TYPE_CIRCLE_FLOAT) {
+			alphaField = getCircleAlphaField(_width, _height, diameterFloat);
+		} else {
+			throw new LowVisionException("Unknown field type: " + _type);
+		}
+
+		int k = 0;
+		for (int j = 0; j < _height; j++) {
+			for (int i = 0; i < _width; i++) {
+				filterArray[k] = alphaField[j][i] << 24 & 0xff000000;
+				k++;
+			}
+		}
+
+		filterImage.setData(filterRaster);
+	}
+
+	// 0: transparent
+	// 255: block all
+	private int[][] getCircleAlphaField(int _width, int _height, float _diameter) {
+		int[][] field = new int[_height][_width];
+		float r = (float) _width * _diameter / 2.0f;
+		float r2 = 0.0f; // r for blur
+		if (r > CIRCLE_WIDTH)
+			r2 = r - CIRCLE_WIDTH;
+		float xc = (float) _width / 2.0f; // center of image(x)
+		// float yc = (float) _height / 2.0f; // center of image(y)
+
+		for (int j = 0; j < _height; j++) {
+			for (int i = 0; i < _width; i++) {
+				float x0 = (float) i - xc;
+				float y0 = (float) j - xc;
+				float r0 = (float) Math.sqrt((double) (x0 * x0 + y0 * y0));
+				int a = Math.round((r0 - r2) / (r - r2) * 255.0f);
+				if (a < 0)
+					a = 0;
+				else if (a > 255)
+					a = 255;
+
+				field[j][i] = a;
+			}
+		}
+
+		return (field);
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/operator/GlareOp.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/operator/GlareOp.java
new file mode 100644
index 0000000..6998744
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/operator/GlareOp.java
@@ -0,0 +1,110 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.operator;
+
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBufferInt;
+import java.awt.image.WritableRaster;
+import java.util.HashMap;
+
+import org.eclipse.actf.visualization.engines.lowvision.LowVisionException;
+import org.eclipse.actf.visualization.engines.lowvision.color.ColorUtil;
+
+public class GlareOp implements ILowVisionOperator {
+	private float glareDegree = 0.0f;// [0,1] original-white
+
+	public GlareOp() {
+	}
+
+	public GlareOp(float _deg) throws LowVisionException {
+		if (!checkDegree(_deg)) {
+			throw new LowVisionException("Glare Degree " + _deg
+					+ " is out of range.");
+		}
+		glareDegree = _deg;
+	}
+
+	public float getGlareDegree() {
+		return (glareDegree);
+	}
+
+	public void setGlareDegree(float _d) {
+		glareDegree = _d;
+	}
+
+	public BufferedImage filter(BufferedImage _src, BufferedImage _dest)
+			throws LowVisionException {
+		WritableRaster srcRaster = _src.copyData(null);
+		DataBufferInt srcBufInt = (DataBufferInt) (srcRaster.getDataBuffer());
+		int[] srcArray = srcBufInt.getData();
+		int srcSize = srcArray.length;
+
+		BufferedImage destImage = _dest;
+		if (_dest == null) {
+			destImage = new BufferedImage(_src.getWidth(), _src.getHeight(),
+					BufferedImage.TYPE_INT_RGB);
+		}
+		WritableRaster destRaster = destImage.copyData(null);
+		DataBufferInt destBufInt = (DataBufferInt) (destRaster.getDataBuffer());
+		int[] destArray = destBufInt.getData();
+		int destSize = destArray.length;
+		if (srcSize != destSize) {
+			throw new LowVisionException("Sizes of src and dest images differ.");
+		}
+
+		HashMap<Integer, Integer> pixelMap = new HashMap<Integer, Integer>();
+		for (int i = 0; i < srcSize; i++) {
+			Integer srcPixel = new Integer(srcArray[i]);
+			Integer destPixel = null;
+			if ((destPixel = (Integer) (pixelMap.get(srcPixel))) == null) {
+				destPixel = new Integer(convertColor(srcArray[i], glareDegree));
+				pixelMap.put(srcPixel, destPixel);
+			}
+			destArray[i] = destPixel.intValue();
+		}
+
+		destImage.setData(destRaster);
+		return (destImage);
+	}
+
+	public static int convertColor(int _color, float _degree)
+			throws LowVisionException {
+		if (!checkDegree(_degree)) {
+			throw new LowVisionException("Glare Degree " + _degree
+					+ " is out of range.");
+		}
+		int[] rgb = ColorUtil.intToRGB(_color);
+
+		int r = convertColorComponent(rgb[0], _degree);
+		int g = convertColorComponent(rgb[1], _degree);
+		int b = convertColorComponent(rgb[2], _degree);
+
+		return (ColorUtil.RGBToInt(r, g, b));
+	}
+
+	private static int convertColorComponent(int _component, float _degree) {
+		int answer = _component + Math.round(_degree * (255 - _component));
+		if (answer < 0)
+			return (0);
+		if (answer > 255)
+			return (255);
+		return (answer);
+	}
+
+	private static boolean checkDegree(float _degree) {
+		if (0.0f <= _degree && _degree <= 1.0f) {
+			return (true);
+		} else {
+			return (false);
+		}
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/operator/ILowVisionOperator.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/operator/ILowVisionOperator.java
new file mode 100644
index 0000000..1c65ee9
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/operator/ILowVisionOperator.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.operator;
+
+import java.awt.image.BufferedImage;
+
+import org.eclipse.actf.visualization.engines.lowvision.LowVisionException;
+
+interface ILowVisionOperator {
+	abstract BufferedImage filter( BufferedImage _src, BufferedImage _dest ) throws LowVisionException;
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/operator/LowVisionFilter.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/operator/LowVisionFilter.java
new file mode 100644
index 0000000..fe67952
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/operator/LowVisionFilter.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.operator;
+
+import java.awt.image.BufferedImage;
+import java.util.Vector;
+
+import org.eclipse.actf.visualization.engines.lowvision.LowVisionException;
+import org.eclipse.actf.visualization.engines.lowvision.LowVisionType;
+import org.eclipse.actf.visualization.engines.lowvision.color.ColorException;
+
+/*
+ * filter to generate simulation image
+ */
+public class LowVisionFilter {
+	LowVisionType type = null;
+
+	Vector<String> simVector = new Vector<String>();
+
+	public LowVisionFilter(LowVisionType _t) {
+		type = _t;
+		if (type.countTypes() > 0) {
+			if (type.getColorFilter()) {
+				simVector
+						.addElement(new String(LowVisionType.COLOR_FILTER_STR));
+			}
+			if (type.getGlare()) {
+				simVector.addElement(new String(LowVisionType.GLARE_STR));
+			}
+			if (type.getCVD()) {
+				simVector.addElement(new String(LowVisionType.CVD_STR));
+			}
+			if (type.getEyesight()) {
+				simVector.addElement(new String(LowVisionType.EYESIGHT_STR));
+			}
+		}
+	}
+
+	/*
+	 * generate simulation image
+	 */
+	public BufferedImage filter(BufferedImage _src, BufferedImage _dest)
+			throws LowVisionException {
+		if (type == null) {
+			throw new LowVisionException("LowVisionType must be provided.");
+		}
+		try {
+			int size = simVector.size();
+			if (size > 1) {
+				BufferedImage tmpImg = oneFilter(simVector.elementAt(0), _src,
+						null);
+				// keep ColorModel as in src
+				for (int i = 1; i < size - 1; i++) {
+					String curType = simVector.elementAt(i);
+					BufferedImage tmpImg2 = oneFilter(curType, tmpImg, null);
+					tmpImg = tmpImg2;
+				}
+				// change ColorModel to that of _dest
+				String curType = simVector.elementAt(size - 1);
+				return (oneFilter(curType, tmpImg, _dest));
+			} else if (size == 1) {
+				return (oneFilter(simVector.elementAt(0), _src, _dest));
+			} else { // count == 0
+				return (_src);
+			}
+		} catch (ColorException ce) {
+			ce.printStackTrace();
+			throw new LowVisionException(
+					"ColorException occurred while filtering.");
+		}
+
+	}
+
+	// do image simulation for _type
+	private BufferedImage oneFilter(String _type, BufferedImage _src,
+			BufferedImage _dest) throws LowVisionException, ColorException {
+		if (_type.equals(LowVisionType.COLOR_FILTER_STR)) {
+			ColorFilterOp cfop = new ColorFilterOp();
+			cfop.setRatio(type.getColorFilterRGB());
+			return (cfop.filter(_src, _dest));
+		} else if (_type.equals(LowVisionType.GLARE_STR)) {
+			// debug
+			// DebugUtil.errMsg( this, "Glare is invoked." );
+			GlareOp gop = new GlareOp(type.getGlareDegree());
+			return (gop.filter(_src, _dest));
+		} else if (_type.equals(LowVisionType.CVD_STR)) {
+			CVDOp cop = new CVDOp(type.getCVDType());
+			return (cop.filter(_src, _dest));
+		} else if (_type.equals(LowVisionType.EYESIGHT_STR)) {
+			BlurOp bop = new BlurOp(type);
+			return (bop.filter(_src, _dest));
+		} else {
+			throw new LowVisionException("Unknown type: " + _type);
+		}
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/BlurProblem.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/BlurProblem.java
new file mode 100644
index 0000000..e7b69fe
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/BlurProblem.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.problem;
+
+import org.eclipse.actf.visualization.engines.lowvision.LowVisionType;
+import org.eclipse.actf.visualization.engines.lowvision.PageElement;
+import org.eclipse.actf.visualization.engines.lowvision.image.PageComponent;
+import org.eclipse.actf.visualization.engines.lowvision.internal.Messages;
+
+public class BlurProblem extends LowVisionProblem {
+	public BlurProblem(PageComponent _pc, LowVisionType _lvType, double _proba)
+			throws LowVisionProblemException {
+		super(
+				LOWVISION_BLUR_PROBLEM,
+				_lvType,
+				Messages
+						.getString("BlurProblem.It_is_difficult_for_weak-sighted_to_read_these_characters._1"),
+				_pc, _proba);
+		setRecommendations();
+	}
+
+	public BlurProblem(PageElement _pe, LowVisionType _lvType, double _proba)
+			throws LowVisionProblemException {
+		super(
+				LOWVISION_BLUR_PROBLEM,
+				_lvType,
+				Messages
+						.getString("BlurProblem.It_is_difficult_for_weak-sighted_to_read_these_characters._1"),
+				_pe, _proba);
+		setRecommendations();
+	}
+
+	protected void setRecommendations() throws LowVisionProblemException {
+		numRecommendations = 2;
+		recommendations = new LowVisionRecommendation[numRecommendations];
+		recommendations[0] = new EnlargeTextRecommendation(this);
+		recommendations[1] = new EnlargeLineRecommendation(this);
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/ChangableFontRecommendation.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/ChangableFontRecommendation.java
new file mode 100644
index 0000000..4bdf28b
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/ChangableFontRecommendation.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.problem;
+
+import org.eclipse.actf.visualization.engines.lowvision.internal.Messages;
+
+public class ChangableFontRecommendation extends LowVisionRecommendation {
+	public ChangableFontRecommendation(LowVisionProblem _prob)
+			throws LowVisionProblemException {
+		super(
+				CHANGABLE_FONT_RECOMMENDATION,
+				_prob,
+				Messages
+						.getString("ChangableFontRecommendation.Do_not_use_fixed-size_font._1"));
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/ColorProblem.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/ColorProblem.java
new file mode 100644
index 0000000..1bdb5bd
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/ColorProblem.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.problem;
+
+import org.eclipse.actf.visualization.engines.lowvision.LowVisionType;
+import org.eclipse.actf.visualization.engines.lowvision.PageElement;
+import org.eclipse.actf.visualization.engines.lowvision.character.CharacterMS;
+import org.eclipse.actf.visualization.engines.lowvision.character.CharacterSM;
+import org.eclipse.actf.visualization.engines.lowvision.character.CharacterSS;
+import org.eclipse.actf.visualization.engines.lowvision.image.PageComponent;
+import org.eclipse.actf.visualization.engines.lowvision.internal.Messages;
+
+
+public class ColorProblem extends LowVisionProblem{
+	private int foregroundColor = -1;
+	private int backgroundColor = -1;
+
+	public ColorProblem( PageComponent _pc, LowVisionType _lvType, double _proba ) throws LowVisionProblemException{
+		super( LOWVISION_COLOR_PROBLEM, _lvType, Messages.getString("ColorProblem.Foreground_and_background_colors_are_too_close._1"), _pc, _proba );
+		setComponentColors();
+		setRecommendations();
+	}
+	
+	public ColorProblem( PageElement _pe, LowVisionType _lvType, double _proba ) throws LowVisionProblemException{
+		super( LOWVISION_COLOR_PROBLEM, _lvType, Messages.getString("ColorProblem.Foreground_and_background_colors_are_too_close._1"), _pe, _proba );
+		foregroundColor = _pe.getForegroundColor();
+		backgroundColor = _pe.getBackgroundColor();
+		setRecommendations();
+	}
+	
+	protected void setRecommendations() throws LowVisionProblemException{
+		numRecommendations = 1;
+		recommendations = new LowVisionRecommendation[numRecommendations];		
+		recommendations[0] = new EnoughContrastRecommendation( this, foregroundColor, backgroundColor );
+	}
+	
+	private void setComponentColors() throws LowVisionProblemException{
+		if( componentType == PageComponent.SS_CHARACTER_TYPE ){
+			foregroundColor = ((CharacterSS)pageComponent).getForegroundColor();
+			backgroundColor = ((CharacterSS)pageComponent).getBackgroundColor();
+		}
+		else if( componentType == PageComponent.MS_CHARACTER_TYPE ){
+			backgroundColor = ((CharacterMS)pageComponent).getBackgroundColor();
+			//use average color
+			foregroundColor = ((CharacterMS)pageComponent).getForegroundColor();
+		}
+		else if( componentType == PageComponent.SM_CHARACTER_TYPE ){
+			foregroundColor = ((CharacterSM)pageComponent).getForegroundColor();
+		}
+		else{
+			throw new LowVisionProblemException( "Invalid component type." ); //$NON-NLS-1$
+		}
+	}
+	
+	public String getDescription() throws LowVisionProblemException{
+		return( super.getDescription() );
+	}
+
+	public int getForegroundColor(){
+		return( foregroundColor );
+	}
+
+	public int getBackgroundColor(){
+		return( backgroundColor );
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/DontRelyOnColorRecommendation.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/DontRelyOnColorRecommendation.java
new file mode 100644
index 0000000..5201aaa
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/DontRelyOnColorRecommendation.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.problem;
+
+import org.eclipse.actf.visualization.engines.lowvision.internal.Messages;
+
+public class DontRelyOnColorRecommendation extends LowVisionRecommendation {
+
+	// TBD more detailed recommendation (border, hatchung, line type, etc.)
+
+	public DontRelyOnColorRecommendation(LowVisionProblem _prob)
+			throws LowVisionProblemException {
+		super(
+				DONT_RELY_ON_COLOR_RECOMMENDATION,
+				_prob,
+				Messages
+						.getString("DontRelyOnColorRecommendation.Don__t_rely_only_on_color._1"));
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/EnlargeLineRecommendation.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/EnlargeLineRecommendation.java
new file mode 100644
index 0000000..5638e44
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/EnlargeLineRecommendation.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.problem;
+
+import org.eclipse.actf.visualization.engines.lowvision.internal.Messages;
+
+public class EnlargeLineRecommendation extends LowVisionRecommendation {
+	public EnlargeLineRecommendation(LowVisionProblem _prob)
+			throws LowVisionProblemException {
+		super(
+				ENLARGE_LINE_RECOMMENDATION,
+				_prob,
+				Messages
+						.getString("EnlargeLineRecommendation.Enlarge_the_line_height._1"));
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/EnlargeTextRecommendation.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/EnlargeTextRecommendation.java
new file mode 100644
index 0000000..a3e8410
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/EnlargeTextRecommendation.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.problem;
+
+import org.eclipse.actf.visualization.engines.lowvision.internal.Messages;
+
+public class EnlargeTextRecommendation extends LowVisionRecommendation{
+	public EnlargeTextRecommendation( LowVisionProblem _prob ) throws LowVisionProblemException{
+		super( ENLARGE_TEXT_RECOMMENDATION, _prob, Messages.getString("EnlargeTextRecommendation.Enlarge_the_text._1") );
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/EnoughContrastRecommendation.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/EnoughContrastRecommendation.java
new file mode 100644
index 0000000..94bd7ea
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/EnoughContrastRecommendation.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.problem;
+
+import org.eclipse.actf.visualization.engines.lowvision.LowVisionCommon;
+import org.eclipse.actf.visualization.engines.lowvision.color.ColorException;
+import org.eclipse.actf.visualization.engines.lowvision.color.ColorIRGB;
+import org.eclipse.actf.visualization.engines.lowvision.color.ColorLAB;
+import org.eclipse.actf.visualization.engines.lowvision.internal.Messages;
+
+
+public class EnoughContrastRecommendation extends LowVisionRecommendation{
+	private int originalForegroundColor = -1;
+	private int originalBackgroundColor = -1;
+	private int recommendedForegroundColor = -1; 
+	private int recommendedBackgroundColor = -1;
+
+	public EnoughContrastRecommendation( LowVisionProblem _prob, int _fg, int _bg ) throws LowVisionProblemException{
+		super( ENOUGH_CONTRAST_RECOMMENDATION, _prob, Messages.getString("EnoughContrastRecommendation.Provide_enough_contrast_between_foreground_and_background_colors._1") );
+		originalForegroundColor = _fg;
+		originalBackgroundColor = _bg;
+		calcRecommendedColors();
+	}
+
+	// only fo SS Character, use original color
+	private void calcRecommendedColors() throws LowVisionProblemException{
+		if( originalForegroundColor == -1 || originalBackgroundColor == -1 ){
+			return;
+		}
+		try{
+			ColorLAB foreLAB = (new ColorIRGB(originalForegroundColor)).toXYZ().toLAB();
+			ColorLAB backLAB = (new ColorIRGB(originalBackgroundColor)).toXYZ().toLAB();
+			if( ColorLAB.deltaL(foreLAB, backLAB) >= LowVisionCommon.RECOMMENDED_DELTA_L_FOR_TEXT ){
+				recommendedForegroundColor = originalForegroundColor;
+				recommendedBackgroundColor = originalBackgroundColor;
+				return;
+			}
+			float foreL = foreLAB.getL();
+			float foreA = foreLAB.getA();
+			float foreB = foreLAB.getB();
+			float backL = backLAB.getL();
+			float backA = backLAB.getA();
+			float backB = backLAB.getB();
+			if( foreL > backL ){
+				if( backL >= LowVisionCommon.MID_L ){
+					backL = foreL - LowVisionCommon.RECOMMENDED_DELTA_L_FOR_TEXT;
+				}
+				else if( foreL <= LowVisionCommon.MID_L ){
+					foreL = backL + LowVisionCommon.RECOMMENDED_DELTA_L_FOR_TEXT;
+				}
+				else{
+					foreL = (foreL+backL+LowVisionCommon.RECOMMENDED_DELTA_L_FOR_TEXT)/2.0f;
+					backL = foreL - LowVisionCommon.RECOMMENDED_DELTA_L_FOR_TEXT;
+				}
+			}
+			else{ // (foreL <= backL)
+				if( foreL >= LowVisionCommon.MID_L ){
+					foreL = backL - LowVisionCommon.RECOMMENDED_DELTA_L_FOR_TEXT;
+				}
+				else if( backL <= LowVisionCommon.MID_L ){
+					backL = foreL + LowVisionCommon.RECOMMENDED_DELTA_L_FOR_TEXT;
+				}
+				else{
+					backL = (foreL+backL+LowVisionCommon.RECOMMENDED_DELTA_L_FOR_TEXT)/2.0f;
+					foreL = backL - LowVisionCommon.RECOMMENDED_DELTA_L_FOR_TEXT;
+				}
+			}
+			recommendedForegroundColor = (new ColorLAB(foreL, foreA, foreB)).toXYZ().toIRGB().toInt();
+			recommendedBackgroundColor = (new ColorLAB(backL, backA, backB)).toXYZ().toIRGB().toInt();
+		}catch( ColorException ce ){
+			ce.printStackTrace();
+			throw new LowVisionProblemException( "Error occurred while calculating recommended colors." ); //$NON-NLS-1$
+		}
+	}
+	
+	public int getOriginalForegroundColor(){
+		return( originalForegroundColor );
+	}
+	public int getOriginalBackgroundColor(){
+		return( originalBackgroundColor );
+	}
+	public int getRecommendedForegroundColor(){
+		return( recommendedForegroundColor );
+	}
+	public int getRecommendedBackgroundColor(){
+		return( recommendedBackgroundColor );
+	}
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/FixedSizeFontProblem.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/FixedSizeFontProblem.java
new file mode 100644
index 0000000..23790b5
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/FixedSizeFontProblem.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.problem;
+
+import org.eclipse.actf.visualization.engines.lowvision.LowVisionType;
+import org.eclipse.actf.visualization.engines.lowvision.PageElement;
+import org.eclipse.actf.visualization.engines.lowvision.internal.Messages;
+
+public class FixedSizeFontProblem extends LowVisionProblem{
+	public FixedSizeFontProblem( PageElement _pe, LowVisionType _lvType, double _proba ) throws LowVisionProblemException{
+		super( LOWVISION_FIXED_SIZE_FONT_PROBLEM, _lvType, Messages.getString("FixedSizeFontProblem.Fixed-size_font_is_used._1"), _pe, _proba );
+		// fontSize = _pe.getFontSize();
+		setRecommendations();
+	}
+
+	protected void setRecommendations() throws LowVisionProblemException{
+		numRecommendations = 1;
+		recommendations = new LowVisionRecommendation[numRecommendations];		
+		recommendations[0] = new ChangableFontRecommendation( this );
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/FixedSmallFontProblem.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/FixedSmallFontProblem.java
new file mode 100644
index 0000000..4786cd5
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/FixedSmallFontProblem.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.problem;
+
+import org.eclipse.actf.visualization.engines.lowvision.LowVisionType;
+import org.eclipse.actf.visualization.engines.lowvision.PageElement;
+import org.eclipse.actf.visualization.engines.lowvision.internal.Messages;
+
+//FixedSizeFontProblem and SmallFontProblem
+
+public class FixedSmallFontProblem extends LowVisionProblem{
+	public FixedSmallFontProblem( PageElement _pe, LowVisionType _lvType, double _proba ) throws LowVisionProblemException{
+		super( LOWVISION_FIXED_SMALL_FONT_PROBLEM, _lvType, Messages.getString("FixedSmallFontProblem.This_text_is_too_small_and_its_font_size_is_fixed._1"), _pe, _proba );
+		// fontSize = _pe.getFontSize();
+		setRecommendations();
+	}
+
+	protected void setRecommendations() throws LowVisionProblemException{
+		numRecommendations = 2;
+		recommendations = new LowVisionRecommendation[numRecommendations];		
+		recommendations[0] = new EnlargeTextRecommendation( this );
+		recommendations[1] = new ChangableFontRecommendation( this );
+	}
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/ImageColorProblem.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/ImageColorProblem.java
new file mode 100644
index 0000000..d799068
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/ImageColorProblem.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.problem;
+
+import org.eclipse.actf.visualization.engines.lowvision.LowVisionType;
+import org.eclipse.actf.visualization.engines.lowvision.image.BinaryImage;
+import org.eclipse.actf.visualization.engines.lowvision.image.ConnectedComponent;
+import org.eclipse.actf.visualization.engines.lowvision.image.Int2D;
+import org.eclipse.actf.visualization.engines.lowvision.image.InteriorImage;
+import org.eclipse.actf.visualization.engines.lowvision.image.InteriorImageComponent;
+import org.eclipse.actf.visualization.engines.lowvision.internal.Messages;
+
+
+public class ImageColorProblem extends LowVisionProblem{
+	// InteriorImage containerImage = null;
+	InteriorImageComponent imageComponent1 = null;
+	InteriorImageComponent imageComponent2 = null;
+
+	public ImageColorProblem( InteriorImage _ii, LowVisionType _lvType, double _prob, InteriorImageComponent _lc1, InteriorImageComponent _lc2 ) throws LowVisionProblemException{
+		super( LOWVISION_IMAGE_COLOR_PROBLEM, _lvType, Messages.getString("ImageColorProblem.This_image_has_two_or_more_components_whose_colors_are_too_close._1"), _ii, _prob );
+		left = _ii.getLeft();
+		top = _ii.getTop();
+		width = _ii.getWidth();
+		height = _ii.getHeight();
+		imageComponent1 = _lc1;
+		imageComponent2 = _lc2;
+		if( _lc1.getContainerImage() != _lc2.getContainerImage() ){
+			throw new LowVisionProblemException( "The two component come from different images." ); //$NON-NLS-1$
+		}
+		if( _lc1.getContainerImage() != _ii ){
+			throw new LowVisionProblemException( "The container of the components and the InteriorImage do not match." ); //$NON-NLS-1$
+		}
+		setRecommendations();
+	}
+
+	public InteriorImageComponent[] getInteriorImageComponentArray(){
+		InteriorImageComponent[] array = {imageComponent1, imageComponent2};
+		return( array );
+	}
+	public InteriorImage getContainerImage(){
+		return( imageComponent1.getContainerImage() );
+	}
+
+	protected void setRecommendations() throws LowVisionProblemException{
+		numRecommendations = 1;
+		recommendations = new LowVisionRecommendation[numRecommendations];
+		recommendations[0] = new DontRelyOnColorRecommendation( this );
+	}
+
+	//for debug
+	public Int2D showProblemImage(){
+		Int2D whiteI2d = null;
+		try{
+			InteriorImage ii = (InteriorImage)(this.pageComponent);
+			Int2D simI2d = ii.simulate(this.lowVisionType);
+			whiteI2d = new Int2D( simI2d.width, simI2d.height );
+			int numCC = imageComponent1.getNumConnectedComponents();
+			ConnectedComponent[] ccArray = imageComponent1.getConnectedComponents();
+			for( int k=0; k<numCC; k++ ){
+				ConnectedComponent cc = ccArray[k];
+				int ccLeft = cc.getLeft();
+				int ccTop = cc.getTop();
+				BinaryImage shape = cc.getShape();
+				int ccWidth = shape.getWidth();
+				int ccHeight = shape.getHeight();
+				byte[][] ccData = shape.getData();
+				for( int j=0; j<ccHeight; j++ ){
+					for( int i=0; i<ccWidth; i++ ){
+						if( ccData[j][i] != 0 ){
+							whiteI2d.data[j+ccTop][i+ccLeft] = simI2d.data[j+ccTop][i+ccLeft];
+						}
+					}
+				}
+			}
+			numCC = imageComponent2.getNumConnectedComponents();
+			ccArray = null;
+			ccArray = imageComponent2.getConnectedComponents();
+			for( int k=0; k<numCC; k++ ){
+				ConnectedComponent cc = ccArray[k];
+				int ccLeft = cc.getLeft();
+				int ccTop = cc.getTop();
+				BinaryImage shape = cc.getShape();
+				int ccWidth = shape.getWidth();
+				int ccHeight = shape.getHeight();
+				byte[][] ccData = shape.getData();
+				for( int j=0; j<ccHeight; j++ ){
+					for( int i=0; i<ccWidth; i++ ){
+						if( ccData[j][i] != 0 ){
+							whiteI2d.data[j+ccTop][i+ccLeft] = simI2d.data[j+ccTop][i+ccLeft];
+						}
+					}
+				}
+			}
+		}catch( Exception e ){
+			e.printStackTrace();
+		}
+		return( whiteI2d );
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/LowVisionProblem.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/LowVisionProblem.java
new file mode 100644
index 0000000..863a193
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/LowVisionProblem.java
@@ -0,0 +1,261 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.problem;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+import org.eclipse.actf.visualization.engines.lowvision.LowVisionType;
+import org.eclipse.actf.visualization.engines.lowvision.PageElement;
+import org.eclipse.actf.visualization.engines.lowvision.image.ConnectedComponent;
+import org.eclipse.actf.visualization.engines.lowvision.image.Int2D;
+import org.eclipse.actf.visualization.engines.lowvision.image.PageComponent;
+import org.eclipse.actf.visualization.engines.lowvision.image.PageImage;
+import org.eclipse.actf.visualization.eval.problem.ILowvisionProblemSubtype;
+
+
+public abstract class LowVisionProblem implements ILowvisionProblemSubtype{
+	public static final int UNSET_POSITION = -1;
+	public static final int DEFAULT_PRIORITY = 0;
+	
+    //061024
+    public static final short LOWVISION_PROBLEM = 0;
+    
+	PageImage pageImage = null; 
+	LowVisionType lowVisionType = null;
+	short problemType; 
+	short componentType = PageComponent.UNDEFINED_TYPE; 
+	PageComponent pageComponent = null; 
+	PageElement pageElement = null; 
+	String description; 
+	int left = UNSET_POSITION;
+	int top = UNSET_POSITION;
+	int width = 0;
+	int height = 0;
+	int priority; 
+
+	double probability = 0.0; // 
+	double characterScore = 0.0; //
+	int numRecommendations = 0; // recommendations.length;
+	LowVisionRecommendation[] recommendations = null;
+	boolean isGroupFlag = false; // is LowVisionProblemGroup?
+	
+	protected LowVisionProblem(){
+	}
+	
+	public LowVisionProblem( short _type, LowVisionType _lvType, String _description, PageComponent _com, double _proba ) throws LowVisionProblemException{
+		problemType = _type;
+		lowVisionType = _lvType;
+		description = _description;
+		pageComponent = _com;
+		componentType = pageComponent.getType();
+		pageImage = pageComponent.getPageImage();
+		ConnectedComponent cc = pageComponent.getConnectedComponent();
+		if( cc != null ){
+			left = cc.getLeft();
+			top = cc.getTop();
+			width = cc.getWidth();
+			height = cc.getHeight();
+		}
+		setPriority();
+		probability = _proba;
+		characterScore = probability * (double)width * (double)height; 
+	}
+
+	public LowVisionProblem( short _type, LowVisionType _lvType, String _description, PageElement _pe, double _proba ){
+		problemType = _type;
+		lowVisionType = _lvType;
+		description = _description;
+		pageElement = _pe;
+		if( pageElement != null ){
+			left = pageElement.getX();
+			top = pageElement.getY();
+			width = pageElement.getWidth();
+			height = pageElement.getHeight();
+		}
+		setPriority();
+		probability = _proba;
+	}
+	
+	private void setPriority(){
+		if( left == UNSET_POSITION || top == UNSET_POSITION ){
+			priority = DEFAULT_PRIORITY;
+		}else{
+			priority = 0x7fffffff - top * 0xffff - left;
+		}
+		/*
+		PageImage pi = component.getPageImage();
+		if( pi != null ){
+			int pageWidth = pi.getWidth();
+			int pageHeight = pi.getHeight();
+			priority = pageWidth*pageHeight - top*pageWidth - left;
+		}
+		else{
+			priority = DEFAULT_PRIORITY;
+		}
+		*/
+	}
+
+	protected abstract void setRecommendations() throws LowVisionProblemException;
+		
+	public short getType() {
+		return( LOWVISION_PROBLEM );
+	}
+
+	public LowVisionType getLowVisionType(){
+		return( lowVisionType );
+	}
+
+	// LowVision Error type (Color, Blur, etc.)
+	public short getLowVisionProblemType(){
+		return( problemType );
+	}
+	public String getDescription() throws LowVisionProblemException{
+		return( description );
+	}
+	public PageImage getPageImage(){
+		return( pageImage );
+	}
+	public int getX(){
+		return( left );
+	}
+	public int getY(){
+		return( top );
+	}
+	public int getWidth(){
+		return( width );
+	}
+	public int getHeight(){
+		return( height );
+	}
+	public int getPriority(){
+		return( priority );
+	}
+	public double getProbability(){
+		return( probability );
+	}
+	public int getIntProbability(){
+		return( (int)(Math.rint(probability*100.0)) );
+	}
+	public double getCharacterScore(){
+		return( characterScore );
+	}
+	public LowVisionRecommendation[] getRecommendations(){
+		return( recommendations );
+	}
+	public boolean isGroup(){
+		return( isGroupFlag );
+	}
+	public short getComponentType() throws LowVisionProblemException{
+		if( !isGroupFlag ){
+			return( componentType );
+		}
+		else{
+			throw new LowVisionProblemException( "componentType cannot be gotten from a ProblemGroup." );
+		}
+	}
+	public PageComponent getPageComponent() throws LowVisionProblemException{
+		if( !isGroupFlag ){
+			return( pageComponent );
+		}
+		else{
+			throw new LowVisionProblemException( "component cannot be gotten from a ProblemGroup." );
+		}
+	}
+
+	public PageElement getPageElement(){
+		return( pageElement );
+	}
+
+	public String toString(){
+		String compTypeString = null;
+		if( componentType == PageComponent.SS_CHARACTER_TYPE ){
+			compTypeString = "(SS)";
+		}
+		else if( componentType == PageComponent.MS_CHARACTER_TYPE ){
+			compTypeString = "(MS)";
+		}
+		else if( componentType == PageComponent.SM_CHARACTER_TYPE ){
+			compTypeString = "(SM)";
+		}
+		else{
+			compTypeString = ""+componentType;
+		}
+		StringBuffer sb = new StringBuffer();
+		sb.append( "Description=" + description );
+		sb.append( compTypeString );
+		sb.append( ", " );
+		sb.append( "(x,y)=(" + left + "," + top + ")" );
+		sb.append( ", " );
+		sb.append( "[WIDTH x HEIGHT]=[" + width + " x " + height + "]" );
+		sb.append( ", " );
+		sb.append( "Probability=" + (int)(Math.rint(probability*100.0)) );
+		sb.append( ", " );
+		sb.append( "#Recommendations=" + numRecommendations );
+		return( sb.toString() );
+	}
+	
+	public void dump( PrintStream _ps, boolean _doRecommendations ) throws LowVisionProblemException{
+		PrintWriter pw = new PrintWriter( _ps, true );
+		dump( pw, _doRecommendations );
+	}
+	public void dump( PrintWriter _pw, boolean _doRecommendations ) throws LowVisionProblemException{
+		_pw.println( "----------" );
+		_pw.println( "dumping a problem");
+		_pw.println( "problemType = " + problemType );
+		_pw.println( "componentType = " + componentType );
+		_pw.println( "description = " + getDescription() );
+		_pw.println( "(x,y) = ( " + getX() + ", " + getY() + ")" );
+		_pw.println( "width, height = " + getWidth() + ", " + getHeight() );
+		_pw.println( "priority = " + getPriority() );
+		LowVisionRecommendation[] recs = getRecommendations();
+		if( recs != null ){
+			_pw.println( "# of Recommendations = " + recs.length );
+		}
+		else{
+			_pw.println( "Recommendations are null." );
+		}
+		if( _doRecommendations && recs != null ){
+			for( int i=0; i<recs.length; i++ ){
+				_pw.println( "Recommendation #" + i );
+				recs[i].dump(_pw);
+			}
+		}
+		_pw.println( "----------" );
+	}
+
+	private static final int[] PROBLEM_COLORS = {
+		0x00ffffff, 0x00ff0000, 0x0000ff00
+	};
+	
+	public void drawSurroundingBox( Int2D _img ){
+		int x0 = getX();
+		int y0 = getY();
+		int x1 = x0+getWidth();
+		int y1 = y0+getHeight();
+		int color = PROBLEM_COLORS[problemType];
+		for( int i=x0; i<x1; i++ ){
+			_img.data[y0][i] = color;
+			_img.data[y1-1][i] = color;
+		}
+		for( int j=y0; j<y1; j++ ){
+			_img.data[j][x0] = color;
+			_img.data[j][x1-1] = color;
+		}
+	}
+	
+	public static void drawAllSurroundingBoxes( LowVisionProblem[] _problems, Int2D _img ){
+		for( int k=0; k<_problems.length; k++ ){
+			_problems[k].drawSurroundingBox( _img );
+		}
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/LowVisionProblemException.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/LowVisionProblemException.java
new file mode 100644
index 0000000..5c97947
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/LowVisionProblemException.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.problem;
+
+import org.eclipse.actf.visualization.eval.problem.ProblemException;
+
+public class LowVisionProblemException extends ProblemException{
+	public LowVisionProblemException(){
+		super();
+	}
+	public LowVisionProblemException( String _s ){
+		super( _s );
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/LowVisionProblemGroup.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/LowVisionProblemGroup.java
new file mode 100644
index 0000000..406da7b
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/LowVisionProblemGroup.java
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.problem;
+
+import java.util.Vector;
+
+import org.eclipse.actf.visualization.engines.lowvision.image.PageImage;
+
+/*
+ * Group of LV problems
+ * 
+ */
+public class LowVisionProblemGroup extends LowVisionProblem {
+	int numProblems; // problems.length;
+
+	LowVisionProblem[] problems;
+
+	LowVisionProblem representative = null;
+
+	double sumCharacterScores; // 
+
+	double groupScore; // (sumCharacterScore/area)
+
+	public LowVisionProblemGroup(Vector<LowVisionProblem> _vec)
+			throws LowVisionProblemException {
+		numProblems = _vec.size();
+		if (numProblems <= 0) {
+			throw new LowVisionProblemException(
+					"No instance belong to the group.");
+		}
+		problems = new LowVisionProblem[numProblems];
+
+		representative = _vec.elementAt(0);
+		problems[0] = representative;
+		this.pageImage = representative.pageImage;
+		this.lowVisionType = representative.lowVisionType;
+		this.problemType = representative.problemType;
+		this.componentType = representative.componentType;
+		this.description = representative.description;
+		sumCharacterScores = representative.characterScore;
+		setRecommendations();
+		this.isGroupFlag = true;
+
+		int tmpLeft = representative.getX();
+		int tmpRight = tmpLeft + representative.getWidth();
+		int tmpTop = representative.getY();
+		int tmpBottom = tmpTop + representative.getHeight();
+		for (int i = 1; i < numProblems; i++) {
+			LowVisionProblem curProb = _vec.elementAt(i);
+			if (curProb.problemType != this.problemType) {
+				throw new LowVisionProblemException(
+						"Problems of different types cannot be grouped.");
+			}
+			problems[i] = curProb;
+			int curLeft = curProb.getX();
+			int curRight = curLeft + curProb.getWidth();
+			int curTop = curProb.getY();
+			int curBottom = curTop + curProb.getHeight();
+			if (curLeft < tmpLeft) {
+				tmpLeft = curLeft;
+			}
+			if (tmpRight < curRight) {
+				tmpRight = curRight;
+			}
+			if (curTop < tmpTop) {
+				tmpTop = curTop;
+			}
+			if (tmpBottom < curBottom) {
+				tmpBottom = curBottom;
+			}
+			sumCharacterScores += curProb.characterScore;
+		}
+		this.left = tmpLeft;
+		this.top = tmpTop;
+		this.width = tmpRight - tmpLeft;
+		this.height = tmpBottom - tmpTop;
+		groupScore = sumCharacterScores / (double) width / (double) height;
+
+		calcProbability();
+		calcPriority();
+	}
+
+	protected void setRecommendations() {
+		this.numRecommendations = representative.numRecommendations;
+		this.recommendations = representative.recommendations;
+	}
+
+	private void calcProbability() throws LowVisionProblemException {
+		if (numProblems <= 0) {
+			throw new LowVisionProblemException(
+					"There are no Problems in this ProblemGroup.");
+		}
+		probability = 0.0;
+		// double problemArea = 0.0;
+		double maxProba = 0.0;
+		for (int i = 0; i < numProblems; i++) {
+			LowVisionProblem curProb = problems[i];
+			if (maxProba < curProb.probability) {
+				maxProba = curProb.probability;
+			}
+			// double curArea = curProb.width * curProb.height;
+			// probability += (curProb.probability * curArea);
+			// problemArea += curArea;
+		}
+
+		probability = maxProba;
+
+		// TODO consider problem area, etc
+		// if( problemType == LOWVISION_COLOR_PROBLEM ){
+		// probability /= problemArea;
+		// }
+		// else if( problemType == LOWVISION_IMAGE_COLOR_PROBLEM ){
+		// probability = maxProba;
+		// }
+		// else{
+		// probability /= (this.width * this.height);
+		// }
+	}
+
+	private void calcPriority() throws LowVisionProblemException {
+		if (problems[0].pageComponent == null) {
+			priority = 0;
+			return;
+		}
+
+		PageImage pi = problems[0].pageComponent.getPageImage();
+		if (problemType == LowVisionProblem.LOWVISION_IMAGE_COLOR_PROBLEM) {
+			priority = 0;
+		} else {
+			if (pi == null) {
+				throw new LowVisionProblemException(
+						"PageImage of the Problem is null.");
+			}
+			int pageWidth = pi.getWidth();
+			int pageHeight = pi.getHeight();
+			priority = pageWidth * pageHeight - top * pageWidth - left;
+		}
+	}
+
+	public LowVisionProblem getRepresentative() {
+		return (representative);
+	}
+
+	public int getNumProblems() {
+		return (numProblems);
+	}
+
+	public LowVisionProblem[] getProblems() {
+		return (problems);
+	}
+
+	public double getSumCharacterScores() {
+		return (sumCharacterScores);
+	}
+
+	public double getGroupScore() {
+		return (groupScore);
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/LowVisionRecommendation.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/LowVisionRecommendation.java
new file mode 100644
index 0000000..1b58758
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/LowVisionRecommendation.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.problem;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+public abstract class LowVisionRecommendation implements Recommendation{
+	public static final short ENOUGH_CONTRAST_RECOMMENDATION = 1;
+	public static final short ENLARGE_TEXT_RECOMMENDATION = 101;
+	public static final short ENLARGE_LINE_RECOMMENDATION = 102;
+	public static final short CHANGABLE_FONT_RECOMMENDATION = 103;
+	public static final short DONT_RELY_ON_COLOR_RECOMMENDATION = 201;
+	public static final short USE_ALLOWED_COLOR_RECOMMENDATION = 301;
+	
+	//
+	
+	short recommendationType;
+	LowVisionProblem problem;
+	String description;
+	int priority;
+	
+	public LowVisionRecommendation( short _type, LowVisionProblem _prob, String _desc ) throws LowVisionProblemException{
+		recommendationType = _type;
+		problem = _prob;
+		description = _desc;
+		setPriority();
+	}
+	
+	private void setPriority(){
+		// TODO
+		priority = 0;
+	}
+	
+	public short getType(){
+		return( recommendationType );
+	}
+	public String getDescription(){
+		return( description );
+	}
+	public int getPriority(){
+		return( priority );
+	}
+	
+	
+	public void dump( PrintStream _ps ){
+		PrintWriter pw = new PrintWriter( _ps, true );
+		dump( pw );
+	}
+	public void dump( PrintWriter _pw ){
+		_pw.println( "-----" );
+		_pw.println( "dumping a recommendation" );
+		_pw.println( "type = " + recommendationType );
+		_pw.println( "description = " + getDescription() );
+		_pw.println( "priority = " + getPriority() );
+		_pw.println( "-----" );
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/ProhibitedBackgroundColorProblem.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/ProhibitedBackgroundColorProblem.java
new file mode 100644
index 0000000..e4a000d
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/ProhibitedBackgroundColorProblem.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.problem;
+
+import org.eclipse.actf.visualization.engines.lowvision.LowVisionType;
+import org.eclipse.actf.visualization.engines.lowvision.PageElement;
+import org.eclipse.actf.visualization.engines.lowvision.image.PageComponent;
+import org.eclipse.actf.visualization.engines.lowvision.internal.Messages;
+
+public class ProhibitedBackgroundColorProblem extends LowVisionProblem{
+	private int foregroundColor = -1;
+	private int backgroundColor = -1;
+
+	public ProhibitedBackgroundColorProblem( PageComponent _pc, LowVisionType _lvType, double _proba ) throws LowVisionProblemException{
+		super( LOWVISION_PROHIBITED_BACKGROUND_COLOR_PROBLEM, _lvType, Messages.getString("ProhibitedBackgroundColorProblem.The_background_color_is_not_allowed_by_the_design_guideline._1"), _pc, _proba );
+		setRecommendations();
+	}
+
+	public ProhibitedBackgroundColorProblem( PageElement _pe, LowVisionType _lvType, double _proba ) throws LowVisionProblemException{
+		super( LOWVISION_PROHIBITED_BACKGROUND_COLOR_PROBLEM, _lvType, Messages.getString("ProhibitedBackgroundColorProblem.The_background_color_is_not_allowed_by_the_design_guideline._1"), _pe, _proba );
+		foregroundColor = _pe.getForegroundColor();
+		backgroundColor = _pe.getBackgroundColor();
+		setRecommendations();
+	}
+	
+	protected void setRecommendations() throws LowVisionProblemException{
+		numRecommendations = 1;
+		recommendations = new LowVisionRecommendation[numRecommendations];
+		recommendations[0] = new UseAllowedColorRecommendation( this );
+	}
+	
+	public int getForegroundColor(){
+		return( foregroundColor );
+	}
+
+	public int getBackgroundColor(){
+		return( backgroundColor );
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/ProhibitedBothColorsProblem.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/ProhibitedBothColorsProblem.java
new file mode 100644
index 0000000..898027b
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/ProhibitedBothColorsProblem.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.problem;
+
+import org.eclipse.actf.visualization.engines.lowvision.LowVisionType;
+import org.eclipse.actf.visualization.engines.lowvision.PageElement;
+import org.eclipse.actf.visualization.engines.lowvision.image.PageComponent;
+import org.eclipse.actf.visualization.engines.lowvision.internal.Messages;
+
+public class ProhibitedBothColorsProblem extends LowVisionProblem{
+	private int foregroundColor = -1;
+	private int backgroundColor = -1;
+	
+	public ProhibitedBothColorsProblem( PageComponent _pc, LowVisionType _lvType, double _proba ) throws LowVisionProblemException{
+		super( LOWVISION_PROHIBITED_BOTH_COLORS_PROBLEM, _lvType, Messages.getString("ProhibitedBothColorsProblem.Both_of_the_foreground_and_background_colors_are_not_allowed_by_the_design_guideline._1"), _pc, _proba );
+		setRecommendations();
+	}
+
+	public ProhibitedBothColorsProblem( PageElement _pe, LowVisionType _lvType, double _proba ) throws LowVisionProblemException{
+		super( LOWVISION_PROHIBITED_BOTH_COLORS_PROBLEM, _lvType, Messages.getString("ProhibitedBothColorsProblem.Both_of_the_foreground_and_background_colors_are_not_allowed_by_the_design_guideline._1"), _pe, _proba );
+		foregroundColor = _pe.getForegroundColor();
+		backgroundColor = _pe.getBackgroundColor();
+		setRecommendations();
+	}
+	
+	protected void setRecommendations() throws LowVisionProblemException{
+		numRecommendations = 1;
+		recommendations = new LowVisionRecommendation[numRecommendations];
+		recommendations[0] = new UseAllowedColorRecommendation( this );
+	}
+	
+	public int getForegroundColor(){
+		return( foregroundColor );
+	}
+
+	public int getBackgroundColor(){
+		return( backgroundColor );
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/ProhibitedForegroundColorProblem.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/ProhibitedForegroundColorProblem.java
new file mode 100644
index 0000000..9ab923d
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/ProhibitedForegroundColorProblem.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.problem;
+
+import org.eclipse.actf.visualization.engines.lowvision.LowVisionType;
+import org.eclipse.actf.visualization.engines.lowvision.PageElement;
+import org.eclipse.actf.visualization.engines.lowvision.image.PageComponent;
+import org.eclipse.actf.visualization.engines.lowvision.internal.Messages;
+
+
+public class ProhibitedForegroundColorProblem extends LowVisionProblem{
+	private int foregroundColor = -1;
+	private int backgroundColor = -1;
+
+	public ProhibitedForegroundColorProblem( PageComponent _pc, LowVisionType _lvType, double _proba ) throws LowVisionProblemException{
+		super( LOWVISION_PROHIBITED_FOREGROUND_COLOR_PROBLEM, _lvType, Messages.getString("ProhibitedForegroundColorProblem.The_foreground_color_is_not_allowed_by_the_design_guideline._1"), _pc, _proba );
+		setRecommendations();
+	}
+
+	public ProhibitedForegroundColorProblem( PageElement _pe, LowVisionType _lvType, double _proba ) throws LowVisionProblemException{
+		super( LOWVISION_PROHIBITED_FOREGROUND_COLOR_PROBLEM, _lvType, Messages.getString("ProhibitedForegroundColorProblem.The_foreground_color_is_not_allowed_by_the_design_guideline._1"), _pe, _proba );
+		foregroundColor = _pe.getForegroundColor();
+		backgroundColor = _pe.getBackgroundColor();
+		setRecommendations();
+	}
+
+	protected void setRecommendations() throws LowVisionProblemException{
+		numRecommendations = 1;
+		recommendations = new LowVisionRecommendation[numRecommendations];
+		recommendations[0] = new UseAllowedColorRecommendation( this );
+	}
+	
+	public int getForegroundColor(){
+		return( foregroundColor );
+	}
+
+	public int getBackgroundColor(){
+		return( backgroundColor );
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/Recommendation.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/Recommendation.java
new file mode 100644
index 0000000..e96e95b
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/Recommendation.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.problem;
+
+public interface Recommendation {
+    public short LOWVISION_RECOMMENDATION = 0;
+
+    public short BLIND_RECOMMENDATION = 1;
+
+    public short getType();
+
+    public String getDescription();
+
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/SmallFontProblem.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/SmallFontProblem.java
new file mode 100644
index 0000000..c87a4b4
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/SmallFontProblem.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.problem;
+
+import org.eclipse.actf.visualization.engines.lowvision.LowVisionType;
+import org.eclipse.actf.visualization.engines.lowvision.PageElement;
+import org.eclipse.actf.visualization.engines.lowvision.internal.Messages;
+
+/*
+ * detected by using HTML DOM
+ */
+public class SmallFontProblem extends LowVisionProblem{
+	public SmallFontProblem( PageElement _pe, LowVisionType _lvType, double _proba ) throws LowVisionProblemException{
+		super( LOWVISION_SMALL_FONT_PROBLEM, _lvType, Messages.getString("SmallFontProblem.This_text_is_too_small._1"), _pe, _proba );
+		// fontSize = _pe.getFontSize();
+		setRecommendations();
+	}
+
+	protected void setRecommendations() throws LowVisionProblemException{
+		numRecommendations = 1;
+		recommendations = new LowVisionRecommendation[numRecommendations];		
+		recommendations[0] = new EnlargeTextRecommendation( this );
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/UseAllowedColorRecommendation.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/UseAllowedColorRecommendation.java
new file mode 100644
index 0000000..cf70e2a
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/problem/UseAllowedColorRecommendation.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.problem;
+
+import org.eclipse.actf.visualization.engines.lowvision.internal.Messages;
+
+public class UseAllowedColorRecommendation extends LowVisionRecommendation{
+	public UseAllowedColorRecommendation( LowVisionProblem _prob ) throws LowVisionProblemException{
+		super( USE_ALLOWED_COLOR_RECOMMENDATION, _prob, Messages.getString("UseAllowedColorRecommendation.Use_a_color_allowed_by_the_design_guideline._1") );
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/util/DecisionMaker.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/util/DecisionMaker.java
new file mode 100644
index 0000000..dfb9482
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/util/DecisionMaker.java
@@ -0,0 +1,627 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.util;
+
+import org.eclipse.actf.visualization.engines.lowvision.LowVisionCommon;
+import org.eclipse.actf.visualization.engines.lowvision.LowVisionException;
+import org.eclipse.actf.visualization.engines.lowvision.character.CharacterMS;
+import org.eclipse.actf.visualization.engines.lowvision.character.CharacterSM;
+import org.eclipse.actf.visualization.engines.lowvision.character.CharacterSS;
+import org.eclipse.actf.visualization.engines.lowvision.color.ColorException;
+import org.eclipse.actf.visualization.engines.lowvision.color.ColorIRGB;
+import org.eclipse.actf.visualization.engines.lowvision.color.ColorLAB;
+import org.eclipse.actf.visualization.engines.lowvision.image.BinaryImage;
+import org.eclipse.actf.visualization.engines.lowvision.image.ConnectedComponent;
+import org.eclipse.actf.visualization.engines.lowvision.image.Container;
+import org.eclipse.actf.visualization.engines.lowvision.image.ImageException;
+import org.eclipse.actf.visualization.engines.lowvision.image.LineSegment;
+import org.eclipse.actf.visualization.engines.lowvision.image.PageComponent;
+import org.eclipse.actf.visualization.engines.lowvision.image.PageImage;
+import org.eclipse.actf.visualization.engines.lowvision.image.Topology;
+import org.eclipse.actf.visualization.engines.lowvision.image.Vector3D;
+import org.eclipse.actf.visualization.engines.lowvision.problem.ColorProblem;
+import org.eclipse.actf.visualization.engines.lowvision.problem.LowVisionProblem;
+import org.eclipse.actf.visualization.engines.lowvision.problem.LowVisionProblemException;
+
+/**
+ * Check color combination by using threshold (in LowvisionCommon)
+ * 
+ */
+public class DecisionMaker implements LowVisionCommon {
+	// // for PageImage
+	//
+	// check connected component or not
+	public static short judgeComponentType(ConnectedComponent _cc, PageImage _pi)
+			throws ImageException {
+		return (judgeComponentType(_cc, _pi, false));
+	}
+
+	public static short judgeComponentType(ConnectedComponent _cc,
+			PageImage _pi, boolean _test) throws ImageException {
+		// int pWidth = _pi.getWidth();
+		// int pHeight = _pi.getHeight();
+		BinaryImage shape = _cc.getShape();
+		int cWidth = shape.getWidth();
+		int cHeight = shape.getHeight();
+
+		// very small
+		if (cWidth < THRESHOLD_MIN_CHAR_WIDTH
+				|| cHeight < THRESHOLD_MIN_CHAR_HEIGHT) {
+			return (PageComponent.OTHER_TYPE );
+		}
+
+		double density = _cc.getDensity();
+
+		// underlined part (start)
+		LineSegment horSeg = shape.detectLongestHorizontalLine();
+		if (horSeg.isVertical() || horSeg.isDiagonal()) {
+			throw new ImageException(
+					"detectLongestHorizontalLine() does not work.");
+		}
+		double widthRatio = horSeg.getLength() / (double) cWidth;
+		double position = (double) (horSeg.getLeftPoint().getY())
+				/ (double) cHeight;
+		double ratio = (double) cWidth / (double) cHeight;
+		if (widthRatio >= THRESHOLD_MIN_UNDERLINE_WIDTH_RATIO
+				&& position >= THRESHOLD_MIN_UNDERLINE_POSITION
+				&& ratio >= THRESHOLD_MIN_UNDERLINE_RATIO
+				&& density < THRESHOLD_MIN_CONTAINER_DENSITY) {
+			return (PageComponent.CANDIDATE_UNDERLINED_CHARACTER_TYPE );
+		}
+
+		// container
+		if ((cWidth > THRESHOLD_MAX_CHAR_WIDTH || cHeight > THRESHOLD_MAX_CHAR_HEIGHT)) {
+			return (PageComponent.CONTAINER_TYPE );
+		}
+
+		// small (might be line)
+		if (ratio < THRESHOLD_MIN_CHAR_RATIO
+				|| THRESHOLD_MAX_CHAR_RATIO < ratio) {
+			return (PageComponent.OTHER_TYPE );
+		}
+
+		// test
+		/*
+		 * Topology topo = new Topology( _cc ); Topology thinTopo = new
+		 * Topology( _cc.thinning() ); int count1 = topo.getCount(); int count2 =
+		 * thinTopo.getCount(); int interior1 = topo.getNumInterior(); int
+		 * interior2 = thinTopo.getNumInterior(); int edge1 =
+		 * topo.getNumEdges(); int edge2 = thinTopo.getNumEdges(); int branch1 =
+		 * topo.getNumBranches(); int branch2 = thinTopo.getNumBranches(); int
+		 * cross1 = topo.getNumCrosses(); int cross2 = thinTopo.getNumCrosses();
+		 * 
+		 * double countDouble = (double)(topo.getCount()); double interiorRatio =
+		 * (double)(topo.getNumInterior())/countDouble; double edgeRatio =
+		 * (double)(topo.getNumEdges())/countDouble; double branchRatio =
+		 * (double)(topo.getNumBranches())/countDouble; double crossRatio =
+		 * (double)(topo.getNumCrosses())/countDouble;
+		 */
+
+		// test (density)
+		/*
+		 * if( density > THRESHOLD_MAX_CHARACTER_DENSITY ){ return(
+		 * PageComponent.OTHER_TYPE ); }
+		 */
+
+		// thinning
+		ConnectedComponent thinCc = _cc.thinning();
+		if ((double) (thinCc.getCount()) / (double) (_cc.getCount()) < THRESHOLD_MIN_THINNING_RATIO) {
+			return (PageComponent.OTHER_TYPE );
+		}
+
+		Topology thinTopo = new Topology(thinCc);
+		if (thinTopo.getNumBranches() > THRESHOLD_MAX_THINNED_BRANCHES) {
+			return (PageComponent.OTHER_TYPE );
+		}
+		if (thinTopo.getNumCrosses() > THRESHOLD_MAX_THINNED_CROSSES) {
+			return (PageComponent.OTHER_TYPE );
+		}
+
+		// debug(from here)
+		/*
+		 * if( _test ){ int ccX = _cc.getLeft(); int ccY = _cc.getTop(); int ccW =
+		 * _cc.getWidth(); int ccH = _cc.getHeight(); DebugUtil.debugMsg( null,
+		 * "Judging container at (" + ccX + "," + ccY + ") [" + ccW + " x " +
+		 * ccH + "] : count=(" + count1 + "," + count2 + ") interior=(" +
+		 * interior1 + "," + interior2 + ") edge=(" + edge1 + "," + edge2 + ")
+		 * branch=(" + branch1 + "," + branch2 + ") cross=(" + cross1 + "," +
+		 * cross2 + ")", "COMPONENT" ); // DebugUtil.debugMsg( null, "Judging
+		 * container at (" + ccX + "," + ccY + ") [" + ccW + " x " + ccH + "] :
+		 * count = " + topo.getCount() + ", interiorRatio = " + interiorRatio + ",
+		 * edgeRatio = " + edgeRatio + ", branchRatio = " + branchRatio + ",
+		 * crossRatio = " + crossRatio, "COMPONENT" ); // DebugUtil.debugMsg(
+		 * null, "Density = " + density, "COMPONENT" ); // debug(to here) }
+		 */
+
+		return (PageComponent.CANDIDATE_CHARACTER_TYPE );
+	} // judgeComponentType( ConnectedComponent )
+
+	// check connected component is MS character or not
+	public static boolean isMSCharacter(ConnectedComponent _cc)
+			throws ImageException {
+		BinaryImage shape = _cc.getShape();
+		int cWidth = shape.getWidth();
+		int cHeight = shape.getHeight();
+
+		// too small
+		if (cWidth < THRESHOLD_MIN_MSCHAR_WIDTH
+				|| cHeight < THRESHOLD_MIN_MSCHAR_HEIGHT) {
+			return (false);
+		}
+		if (cHeight > THRESHOLD_MAX_MSCHAR_HEIGHT) {
+			return (false);
+		}
+		/*
+		 * do not use thinning ConnectedComponent thinCc = _cc.thinning(); //
+		 * debug // DebugUtil.outMsg( null, "thinCc.count = " +
+		 * thinCc.getCount() + ", _cc.count = " + _cc.getCount() + ", Ratio = " +
+		 * (double)(thinCc.getCount())/(double)(_cc.getCount()) ); if(
+		 * (double)(thinCc.getCount())/(double)(_cc.getCount()) <
+		 * THRESHOLD_MIN_THINNING_RATIO ){ return( false ); }
+		 */
+		return (true);
+	}
+
+	public static boolean isTooSmallThinedMSCharacter(CharacterMS _msc)
+			throws ImageException {
+		ConnectedComponent curCc = _msc.getConnectedComponent();
+		ConnectedComponent thinCc = curCc.thinning();
+		double ratio = (double) (thinCc.getCount())
+				/ (double) (curCc.getCount());
+		if (ratio < THRESHOLD_MIN_THINNING_RATIO) {
+			return (true);
+		}
+		return (false);
+	}
+
+	public static boolean isSMCharacter(CharacterSM _smc) {
+		int foregroundColor = _smc.getForegroundColor();
+		int sumR = 0;
+		int sumG = 0;
+		int sumB = 0;
+		int w = _smc.getWidth();
+		int h = _smc.getHeight();
+		if (w < THRESHOLD_MIN_SMCHAR_WIDTH || h < THRESHOLD_MIN_SMCHAR_HEIGHT
+				|| h > THRESHOLD_MAX_SMCHAR_HEIGHT) {
+			return (false);
+		}
+		ConnectedComponent cc = _smc.getConnectedComponent();
+		byte[][] data = cc.getShape().getData();
+		int[][] img = _smc.getImage();
+		int count = 0;
+		for (int j = 0; j < h; j++) {
+			for (int i = 0; i < w; i++) {
+				if (data[j][i] == 0) {
+					int color = img[j][i];
+					sumR += (color >> 16) & 0xff;
+					sumG += (color >> 8) & 0xff;
+					sumB += color & 0xff;
+					count++;
+				}
+			}
+		}
+		sumR /= count;
+		sumG /= count;
+		sumB /= count;
+
+		int sumColor = ((sumR & 0xff) << 16) | ((sumG & 0xff) << 8)
+				| (sumB & 0xff);
+		try {
+			if (distinguishableTextColors(foregroundColor, sumColor)) {
+				return (true);
+			} else {
+				return (false);
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+			return (true);
+		}
+	}
+
+	// // for SimulatedPageImage
+
+	/*
+	 * Color combination check (for text)
+	 * 
+	 * criteria for text/image text (bg/fg connected) <- brightness image
+	 * (components are separated in some cases) <- chroma, hue
+	 * 
+	 */
+	public static boolean distinguishableTextColors(ColorLAB _c1, ColorLAB _c2) {
+		double deltaL = ColorLAB.deltaL(_c1, _c2);
+		double deltaE = ColorLAB.deltaE(_c1, _c2);
+		// double deltaH = ColorLAB.deltaH( _c1, _c2 );
+
+		// minimum delta of brightness
+		if (deltaL < MIN_ENOUGH_DELTA_L_FOR_TEXT) {
+			return (false);
+		}
+
+		// enough chroma/hue difference
+		// (required delta of brightness becomes small)
+		if (deltaE >= ENOUGH_DELTA_E_FOR_TEXT) {
+			return (true);
+		}
+		// if( deltaH >= ENOUGH_DELTA_H_FOR_TEXT ){
+		// return( true );
+		// }
+
+		double thresholdL = calcThresholdLforText(_c1, _c2);
+		if (deltaL < thresholdL) {
+			return (false);
+		} else {
+			return (true);
+		}
+	}
+
+	// Color combination check (for text)
+	public static boolean distinguishableTextColors(int _c1, int _c2)
+			throws LowVisionException {
+		// debug(from here)
+		/*
+		 * ColorIRGB i2_ = new ColorIRGB(_c2); ColorIRGB i1_ = new
+		 * ColorIRGB(_c1); int c1R = i1_.getR(); int c1G = i1_.getG(); int c1B =
+		 * i1_.getB(); try{ if( _c2 == ((90<<16)+(93<<8)+90) && (c1R>c1G) &&
+		 * (c1R>c1B) ){ DebugUtil.outMsg( null, "C1: R = " + i1_.getR() + ", G = " +
+		 * i1_.getG() + ", B = " + i1_.getB() ); ColorLAB l1_ = (new
+		 * ColorIRGB(_c1)).toXYZ().toLAB(); ColorLAB l2_ = (new
+		 * ColorIRGB(_c2)).toXYZ().toLAB(); DebugUtil.outMsg( null, "Delta L = " +
+		 * ColorLAB.deltaL(l1_,l2_) ); DebugUtil.outMsg( null, "Delta E = " +
+		 * ColorLAB.deltaE(l1_,l2_) ); } }catch( Exception e ){
+		 * e.printStackTrace(); }
+		 */
+		// debug(to here)
+		ColorLAB lab1 = null;
+		ColorLAB lab2 = null;
+		try {
+			lab1 = (new ColorIRGB(_c1)).toXYZ().toLAB();
+			lab2 = (new ColorIRGB(_c2)).toXYZ().toLAB();
+		} catch (ColorException ce) {
+			ce.printStackTrace();
+			throw new LowVisionException(
+					"ColorException occurred while converting int into ColorLAB");
+		}
+		return (distinguishableTextColors(lab1, lab2));
+	}
+
+	// obtain threshold of brightness from chroma/hue
+	public static double calcThresholdLforText(ColorLAB _c1, ColorLAB _c2) {
+		double deltaE = ColorLAB.deltaE(_c1, _c2);
+		double thresholdL = (MIN_ENOUGH_DELTA_L_FOR_TEXT - MAX_ENOUGH_DELTA_L_FOR_TEXT)
+				/ ENOUGH_DELTA_E_FOR_TEXT
+				* deltaE
+				+ MAX_ENOUGH_DELTA_L_FOR_TEXT;
+		if (thresholdL < 0.0) {
+			thresholdL = 0.0;
+		}
+		return (thresholdL);
+		/*
+		 * double deltaH = ColorLAB.deltaH( _c1, _c2 ); double thresholdL =
+		 * (MIN_ENOUGH_DELTA_L_FOR_TEXT-MAX_ENOUGH_DELTA_L_FOR_TEXT)/ENOUGH_DELTA_H_FOR_TEXT*deltaH +
+		 * MAX_ENOUGH_DELTA_L_FOR_TEXT; if( thresholdL < 0.0 ){ thresholdL =
+		 * 0.0; } return( thresholdL );
+		 */
+	}
+
+	public static double calcThresholdLforText(int _c1, int _c2)
+			throws LowVisionException {
+		ColorLAB lab1 = null;
+		ColorLAB lab2 = null;
+		try {
+			lab1 = (new ColorIRGB(_c1)).toXYZ().toLAB();
+			lab2 = (new ColorIRGB(_c2)).toXYZ().toLAB();
+		} catch (ColorException ce) {
+			ce.printStackTrace();
+			throw new LowVisionException(
+					"ColorException occurred while converting int into ColorLAB");
+		}
+		return (calcThresholdLforText(lab1, lab2));
+	}
+
+	// Color conbimation check (for image)
+	public static boolean distinguishableImageColors(ColorLAB _c1, ColorLAB _c2) {
+		if (calcColorDistanceForImage(_c1, _c2) >= 1.0) {
+			return (true);
+		} else {
+			return (false);
+		}
+
+	}
+
+	public static boolean distinguishableImageColors(int _c1, int _c2)
+			throws LowVisionException {
+		ColorLAB lab1 = null;
+		ColorLAB lab2 = null;
+		try {
+			lab1 = (new ColorIRGB(_c1)).toXYZ().toLAB();
+			lab2 = (new ColorIRGB(_c2)).toXYZ().toLAB();
+		} catch (ColorException ce) {
+			ce.printStackTrace();
+			throw new LowVisionException(
+					"ColorException occurred while converting int into ColorLAB");
+		}
+		return (distinguishableImageColors(lab1, lab2));
+	}
+
+	public static double calcColorDistanceForImage(ColorLAB _c1, ColorLAB _c2) {
+		return (ColorLAB.deltaE(_c1, _c2) / ENOUGH_DELTA_E_FOR_IMAGE);
+	}
+
+	public static double calcColorDistanceForImage(int _c1, int _c2)
+			throws LowVisionException {
+		ColorLAB lab1 = null;
+		ColorLAB lab2 = null;
+		try {
+			lab1 = (new ColorIRGB(_c1)).toXYZ().toLAB();
+			lab2 = (new ColorIRGB(_c2)).toXYZ().toLAB();
+		} catch (ColorException ce) {
+			ce.printStackTrace();
+			throw new LowVisionException(
+					"ColorException occurred while converting int into ColorLAB");
+		}
+		return (calcColorDistanceForImage(lab1, lab2));
+	}
+
+	/*
+	 * check the color can be considered as foreground color?
+	 */
+	public static boolean isForegroundColor(int _color, int _fore, int _back) {
+		Vector3D colV = colorToVector3D(_color);
+		Vector3D foreV = colorToVector3D(_fore);
+		Vector3D backV = colorToVector3D(_back);
+
+		Vector3D back2colV = Vector3D.subtract(colV, backV);
+		Vector3D back2foreV = Vector3D.subtract(foreV, backV);
+
+		if (back2foreV.isZeroVector() || back2colV.isZeroVector()) {
+
+			double distance = Vector3D
+					.magnitude(Vector3D.subtract(foreV, colV));
+			if (distance <= THRESHOLD_FOREGROUND_ERROR_MARGIN) {
+				return (true);
+			} else {
+				return (false);
+			}
+		}
+
+		double rCol = back2colV.magnitude();
+		double rFore = back2foreV.magnitude();
+		double sinTheta = 0.0;
+		double cosTheta = 0.0;
+		try {
+			sinTheta = Vector3D.sine(back2foreV, back2colV);
+			cosTheta = Vector3D.cosine(back2foreV, back2colV);
+		} catch (ImageException e) {
+			e.printStackTrace();
+		}
+
+		if (rCol * sinTheta > THRESHOLD_FOREGROUND_ERROR_MARGIN) {
+			return (false);
+		}
+
+		double ratio = rCol * cosTheta / rFore;
+		if (ratio < THRESHOLD_FOREGROUND_RATIO || 1.0 < ratio) {
+			return (false);
+		}
+
+		return (true);
+	}
+
+	private static Vector3D colorToVector3D(int _color) {
+		ColorIRGB ci = new ColorIRGB(_color);
+		return (new Vector3D((double) (ci.getR()), (double) (ci.getG()),
+				(double) (ci.getB())));
+	}
+
+	/*
+	 * calc search range for blurred text
+	 */
+	public static int calcSearchMinX(int _origLeft, int _origWidth,
+			int _pageWidth) {
+		int tmpX = _origLeft
+				- Math.round((THRESHOLD_LIMIT_BLURRED_WIDTH_RATIO - 1.0f)
+						/ 2.0f * _origWidth);
+		if (tmpX < 0) {
+			tmpX = 0;
+		}
+		return (tmpX);
+	}
+
+	public static int calcSearchMaxX(int _origLeft, int _origWidth,
+			int _pageWidth) {
+		int tmpX = _origLeft
+				+ _origWidth
+				+ Math.round((THRESHOLD_LIMIT_BLURRED_WIDTH_RATIO - 1.0f)
+						/ 2.0f * _origWidth);
+		if (tmpX > _pageWidth - 1) {
+			tmpX = _pageWidth - 1;
+		}
+		return (tmpX);
+	}
+
+	public static int calcSearchMinY(int _origTop, int _origHeight,
+			int _pageHeight) {
+		int tmpY = _origTop
+				- Math.round((THRESHOLD_LIMIT_BLURRED_HEIGHT_RATIO - 1.0f)
+						/ 2.0f * _origHeight);
+		if (tmpY < 0) {
+			tmpY = 0;
+		}
+		return (tmpY);
+	}
+
+	public static int calcSearchMaxY(int _origTop, int _origHeight,
+			int _pageHeight) {
+		int tmpY = _origTop
+				+ _origHeight
+				+ Math.round((THRESHOLD_LIMIT_BLURRED_HEIGHT_RATIO - 1.0f)
+						/ 2.0f * _origHeight);
+		if (tmpY > _pageHeight - 1) {
+			tmpY = _pageHeight - 1;
+		}
+		return (tmpY);
+	}
+
+	// // for Problems
+
+	/*
+	 * merge problems in the same container
+	 */
+	public static boolean areSameGroupProblems(LowVisionProblem _p1,
+			LowVisionProblem _p2) throws LowVisionProblemException {
+		if (_p1.isGroup() || _p2.isGroup()) {
+			throw new LowVisionProblemException(
+					"ProblemGroup cannot be grouped any more.");
+		}
+
+		// check component type
+		PageComponent component1 = _p1.getPageComponent();
+		PageComponent component2 = _p2.getPageComponent();
+		short componentType1 = component1.getType();
+		short componentType2 = component2.getType();
+		if (componentType1 != componentType2) {
+			return (false);
+		}
+
+		// check problem type
+		short type1 = _p1.getLowVisionProblemType();
+		if (type1 != _p2.getLowVisionProblemType()) {
+			return (false);
+		}
+
+		// color
+		// SS -> same fg/bg
+		// MS -> same bg
+		// SM -> same fg
+		if (type1 == LowVisionProblem.LOWVISION_COLOR_PROBLEM) {
+			ColorProblem cp1 = (ColorProblem) _p1;
+			ColorProblem cp2 = (ColorProblem) _p2;
+
+			if (componentType1 == PageComponent.SS_CHARACTER_TYPE) {
+				if (cp1.getBackgroundColor() != cp2.getBackgroundColor()) {
+					return (false);
+				}
+				if (cp1.getForegroundColor() != cp2.getForegroundColor()) {
+					return (false);
+				}
+			} else if (componentType1 == PageComponent.MS_CHARACTER_TYPE) {
+				if (cp1.getBackgroundColor() != cp2.getBackgroundColor()) {
+					return (false);
+				}
+			} else if (componentType1 == PageComponent.SM_CHARACTER_TYPE) {
+				if (cp1.getForegroundColor() != cp2.getForegroundColor()) {
+					return (false);
+				}
+			}
+		}
+
+		// blur
+		else if (type1 == LowVisionProblem.LOWVISION_BLUR_PROBLEM) {
+			if (componentType1 == PageComponent.SS_CHARACTER_TYPE) {
+				CharacterSS ssc1 = (CharacterSS) component1;
+				CharacterSS ssc2 = (CharacterSS) component2;
+				if (ssc1.getForegroundColor() != ssc2.getForegroundColor()) {
+					return (false);
+				}
+				if (ssc1.getBackgroundColor() != ssc2.getBackgroundColor()) {
+					return (false);
+				}
+			} else if (componentType1 == PageComponent.MS_CHARACTER_TYPE) {
+				if (((CharacterMS) component1).getBackgroundColor() != ((CharacterMS) component2)
+						.getBackgroundColor()) {
+					return (false);
+				}
+			} else if (componentType1 == PageComponent.SM_CHARACTER_TYPE) {
+				if (((CharacterSM) component1).getForegroundColor() != ((CharacterSM) component2)
+						.getForegroundColor()) {
+					return (false);
+				}
+			}
+		} else {
+			throw new LowVisionProblemException("Unknown problem type :"
+					+ type1);
+		}
+
+		// small container
+		Container cont = null;
+		cont = _p1.getPageComponent().getContainer();
+		if (cont != null) {
+			if (cont.getWidth() <= THRESHOLD_MAX_GROUPED_CONTAINER_WIDTH
+					&& cont.getHeight() <= THRESHOLD_MAX_GROUPED_CONTAINER_HEIGHT) {
+				return (true);
+			}
+		}
+
+		int left1 = _p1.getX();
+		int right1 = left1 + _p1.getWidth() - 1;
+		int top1 = _p1.getY();
+		int bottom1 = top1 + _p1.getHeight() - 1;
+		int left2 = _p2.getX();
+		int right2 = left2 + _p2.getWidth() - 1;
+		int top2 = _p2.getY();
+		int bottom2 = top2 + _p2.getHeight() - 1;
+
+		if (left1 - right2 > THRESHOLD_MAX_REGION_ELEMENT_SPACE
+				|| left2 - right1 > THRESHOLD_MAX_REGION_ELEMENT_SPACE) {
+			return (false);
+		}
+		if (top1 - bottom2 > THRESHOLD_MAX_REGION_ELEMENT_SPACE
+				|| top2 - bottom1 > THRESHOLD_MAX_REGION_ELEMENT_SPACE) {
+			return (false);
+		}
+
+		return (true);
+	}
+
+//	/*
+//	 * same Y region, near (X) -> word
+//	 */
+//	public static boolean areSameGroupProblems(LowVisionProblem _p1,
+//			LowVisionProblem _p2) throws ImageException { //
+//		if (_p1.isGroup() || _p2.isGroup()) {
+//			throw new ImageException("ProblemGroup cannot be grouped any more.");
+//		}
+//		if (_p1.getLowVisionProblemType() != _p2.getLowVisionProblemType()) {
+//			return (false);
+//		}
+//
+//		int left1 = _p1.getX();
+//		int right1 = left1 + _p1.getWidth() - 1;
+//		int top1 = _p1.getY();
+//		int bottom1 = top1 + _p1.getHeight() - 1;
+//		int left2 = _p2.getX();
+//		int right2 = left2 + _p2.getWidth() - 1;
+//		int top2 = _p2.getY();
+//		int bottom2 = top2 + _p2.getHeight() - 1;
+//		if (left1 - right2 > THRESHOLD_MAX_CHARACTER_SPACE
+//				|| left2 - right1 > THRESHOLD_MAX_CHARACTER_SPACE) {
+//			return (false);
+//		}
+//		if (bottom1 < top2 || bottom2 < top1) {
+//			return (false);
+//		}
+//		return (true);
+//	}
+
+	//return color for the score map
+	public static int getScoreMapColor(double _score) {
+		if (_score <= 0.0) {
+			return (0x00aaaaaa);
+		} else if (_score < SCORE_ORANGE) {
+			return (0x00ffff00);
+		} else if (_score < SCORE_RED) {
+			return (0x00ff7700);
+		} else {
+			return (0x00ff0000);
+		}
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/util/EdgeDetector.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/util/EdgeDetector.java
new file mode 100644
index 0000000..e19372f
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/util/EdgeDetector.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.visualization.engines.lowvision.util;
+
+import java.awt.image.BufferedImage;
+import java.awt.image.ConvolveOp;
+import java.awt.image.Kernel;
+
+import org.eclipse.actf.visualization.engines.lowvision.LowVisionException;
+
+public class EdgeDetector {
+	public static final short METHOD_LAPLACIAN4_MINUS = 0;
+
+	public static final short METHOD_LAPLACIAN4_PLUS = 1;
+
+	public static final short METHOD_LAPLACIAN8_MINUS = 2;
+
+	public static final short METHOD_LAPLACIAN8_PLUS = 3;
+
+	public static final short METHOD_DEFAULT = METHOD_LAPLACIAN4_MINUS;
+
+	private static final float[] LAPLACIAN4_3X3_MINUS = { 0.0f, 1.0f, 0.0f,
+			1.0f, -4.0f, 1.0f, 0.0f, 1.0f, 0.0f };
+
+	private static final float[] LAPLACIAN4_3X3_PLUS = { 0.0f, -1.0f, 0.0f,
+			-1.0f, 4.0f, -1.0f, 0.0f, -1.0f, 0.0f };
+
+	private static final float[] LAPLACIAN8_3X3_MINUS = { 1.0f, 1.0f, 1.0f,
+			1.0f, -8.0f, 1.0f, 1.0f, 1.0f, 1.0f };
+
+	private static final float[] LAPLACIAN8_3X3_PLUS = { -1.0f, -1.0f, -1.0f,
+			-1.0f, 8.0f, -1.0f, -1.0f, -1.0f, -1.0f };
+
+	private BufferedImage srcBufferedImage = null;
+
+	private BufferedImage destBufferedImage = null;
+
+//	private int width = 0;
+//
+//	private int height = 0;
+
+	public EdgeDetector(BufferedImage _src) throws LowVisionException {
+		this(_src, METHOD_DEFAULT);
+	}
+
+	public EdgeDetector(BufferedImage _src, short _method)
+			throws LowVisionException {
+		srcBufferedImage = _src;
+//		width = srcBufferedImage.getWidth();
+//		height = srcBufferedImage.getHeight();
+
+		if (_method == METHOD_LAPLACIAN4_MINUS) {
+			destBufferedImage = convolve(srcBufferedImage, 3, 3,
+					LAPLACIAN4_3X3_MINUS);
+		} else if (_method == METHOD_LAPLACIAN4_PLUS) {
+			destBufferedImage = convolve(srcBufferedImage, 3, 3,
+					LAPLACIAN4_3X3_PLUS);
+		} else if (_method == METHOD_LAPLACIAN8_MINUS) {
+			destBufferedImage = convolve(srcBufferedImage, 3, 3,
+					LAPLACIAN8_3X3_MINUS);
+		} else if (_method == METHOD_LAPLACIAN8_PLUS) {
+			destBufferedImage = convolve(srcBufferedImage, 3, 3,
+					LAPLACIAN8_3X3_PLUS);
+		} else {
+			throw new LowVisionException("Unknown method: " + _method);
+		}
+	}
+
+	private BufferedImage convolve(BufferedImage _srcImage, int _kernelWidth,
+			int _kernelHeight, float[] _kernelData) {
+		BufferedImage tmpImage = new BufferedImage(_srcImage.getWidth(),
+				_srcImage.getHeight(), BufferedImage.TYPE_INT_RGB);
+		Kernel ker = new Kernel(_kernelWidth, _kernelHeight, _kernelData);
+		ConvolveOp cop = new ConvolveOp(ker, ConvolveOp.EDGE_NO_OP, null);
+		return (cop.filter(_srcImage, tmpImage));
+	}
+
+	public BufferedImage writeToImage() {
+		// TBD
+		return (destBufferedImage);
+	}
+}
diff --git a/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/util/LengthUtil.java b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/util/LengthUtil.java
new file mode 100644
index 0000000..3e5993f
--- /dev/null
+++ b/plugins/org.eclipse.actf.visualization.engines.lowvision/src/org/eclipse/actf/visualization/engines/lowvision/util/LengthUtil.java
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Junji MAEDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.visualization.engines.lowvision.util;
+
+
+// convert length in stylesheet
+// in: 2.54cm
+// cm: 
+// mm: 
+// pt: (1/72in)
+// pc: (12pt = 1/6in)
+// px: (1px = 0.21mm) experimental value (device dependent...)
+public class LengthUtil {
+	public static float in2cm( float _in ){
+		return( _in*2.54f );
+	}
+	public static float in2mm( float _in ){
+		return( _in*25.4f );
+	}
+	public static float in2pt( float _in ){
+		return( _in*72.0f );
+	}
+	public static float in2pc( float _in ){
+		return( _in*6.0f );
+	}
+	public static float in2px( float _in ){
+		return( mm2px(in2mm(_in)) );
+	}
+
+	public static float cm2in( float _cm ){
+		return( _cm/2.54f );
+	}
+	public static float cm2mm( float _cm ){
+		return( _cm*10.0f );
+	}
+	public static float cm2pt( float _cm ){
+		return( in2pt(cm2in(_cm)) );
+	}
+	public static float cm2pc( float _cm ){
+		return( in2pc(cm2in(_cm)) );
+	}
+	public static float cm2px( float _cm ){
+		return( _cm/0.021f );
+	}
+
+	public static float mm2in( float _mm ){
+		return( _mm/25.4f );
+	}
+	public static float mm2cm( float _mm ){
+		return( _mm/10.0f );
+	}
+	public static float mm2pt( float _mm ){
+		return( in2pt(mm2in(_mm)) );
+	}
+	public static float mm2pc( float _mm ){
+		return( in2pc(mm2in(_mm)) );
+	}
+	public static float mm2px( float _mm ){
+		return( _mm/0.21f );
+	}
+
+	public static float pt2in( float _pt ){
+		return( _pt/72.0f );
+	}
+	public static float pt2cm( float _pt ){
+		return( in2cm(pt2in(_pt)) );
+	}
+	public static float pt2mm( float _pt ){
+		return( in2mm(pt2in(_pt)) );
+	}
+	public static float pt2pc( float _pt ){
+		return( _pt/12.0f );
+	}
+	public static float pt2px( float _pt ){
+		return( mm2px(pt2mm(_pt)) );
+	}
+
+	public static float pc2in( float _pc ){
+		return( _pc/6.0f );
+	}
+	public static float pc2cm( float _pc ){
+		return( in2cm(pc2in(_pc)) );
+	}
+	public static float pc2mm( float _pc ){
+		return( in2mm(pc2in(_pc)) );
+	}
+	public static float pc2pt( float _pc ){
+		return( _pc*12.0f );
+	}
+	public static float pc2px( float _pc ){
+		return( mm2px(pc2mm(_pc)) );
+	}
+
+	public static float px2in( float _px ){
+		return( mm2in(px2mm(_px)) );
+	}
+	public static float px2cm( float _px ){
+		return( _px*0.021f );
+	}
+	public static float px2mm( float _px ){
+		return( _px*0.21f );
+	}
+	public static float px2pt( float _px ){
+		return( mm2pt(px2mm(_px)) );
+	}
+	public static float px2pc( float _px ){
+		return( mm2pc(px2mm(_px)) );
+	}
+}