tesseract
3.03
|
00001 // Copyright 2007 Google Inc. All Rights Reserved. 00002 // 00003 // Licensed under the Apache License, Version 2.0 (the "License"); You may not 00004 // use this file except in compliance with the License. You may obtain a copy of 00005 // the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by 00006 // applicable law or agreed to in writing, software distributed under the 00007 // License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 00008 // OF ANY KIND, either express or implied. See the License for the specific 00009 // language governing permissions and limitations under the License. 00010 00011 package com.google.scrollview; 00012 00013 import com.google.scrollview.events.SVEvent; 00014 import com.google.scrollview.ui.SVImageHandler; 00015 import com.google.scrollview.ui.SVWindow; 00016 import org.piccolo2d.nodes.PImage; 00017 00018 import java.io.BufferedReader; 00019 import java.io.IOException; 00020 import java.io.InputStreamReader; 00021 import java.io.PrintStream; 00022 import java.net.ServerSocket; 00023 import java.net.Socket; 00024 import java.util.ArrayList; 00025 import java.util.regex.Pattern; 00026 00032 public class ScrollView { 00033 00035 public static int SERVER_PORT = 8461; 00036 00042 private static Socket socket; 00043 private static PrintStream out; 00044 public static BufferedReader in; 00045 public static float polylineXCoords[]; // The coords being received. 00046 public static float polylineYCoords[]; // The coords being received. 00047 public static int polylineSize; // The size of the coords arrays. 00048 public static int polylineScanned; // The size read so far. 00049 private static ArrayList<SVWindow> windows; // The id to SVWindow map. 00050 private static Pattern intPattern; // For checking integer arguments. 00051 private static Pattern floatPattern; // For checking float arguments. 00052 00054 static int nrInputLines = 0; 00055 00057 static boolean debugViewNetworkTraffic = false; 00058 00060 public static void addMessage(SVEvent e) { 00061 if (debugViewNetworkTraffic) { 00062 System.out.println("(S->c) " + e.toString()); 00063 } 00064 String str = e.toString(); 00065 // Send the whole thing as UTF8. 00066 try { 00067 byte [] utf8 = str.getBytes("UTF8"); 00068 out.write(utf8, 0, utf8.length); 00069 } catch (java.io.UnsupportedEncodingException ex) { 00070 System.out.println("Oops... can't encode to UTF8... Exiting"); 00071 System.exit(0); 00072 } 00073 out.println(); 00074 // Flush the output and check for errors. 00075 boolean error = out.checkError(); 00076 if (error) { 00077 System.out.println("Connection error. Quitting ScrollView Server..."); 00078 System.exit(0); 00079 } 00080 } 00081 00083 public static String receiveMessage() throws IOException { 00084 return in.readLine(); 00085 } 00086 00091 private static void IOLoop() { 00092 String inputLine; 00093 00094 try { 00095 while (!socket.isClosed() && !socket.isInputShutdown() && 00096 !socket.isOutputShutdown() && 00097 socket.isConnected() && socket.isBound()) { 00098 inputLine = receiveMessage(); 00099 nrInputLines++; 00100 if (debugViewNetworkTraffic) { 00101 System.out.println("(c->S," + nrInputLines + ")" + inputLine); 00102 } 00103 00104 if (polylineSize > polylineScanned) { 00105 // We are processing a polyline. 00106 // Read pairs of coordinates separated by commas. 00107 boolean first = true; 00108 for (String coordStr : inputLine.split(",")) { 00109 int coord = Integer.parseInt(coordStr); 00110 if (first) { 00111 polylineXCoords[polylineScanned] = coord; 00112 } else { 00113 polylineYCoords[polylineScanned++] = coord; 00114 } 00115 first = !first; 00116 } 00117 assert first; 00118 } else { 00119 // Process this normally. 00120 processInput(inputLine); 00121 } 00122 } 00123 } 00124 // Some connection error 00125 catch (IOException e) { 00126 System.out.println("Connection error. Quitting ScrollView Server..."); 00127 } 00128 System.exit(0); 00129 } 00130 00131 // Parse a comma-separated list of arguments into ArrayLists of the 00132 // possible types. Each type is stored in order, but the order 00133 // distinction between types is lost. 00134 // Note that the format is highly constrained to what the client used 00135 // to send to LUA: 00136 // Quoted string -> String. 00137 // true or false -> Boolean. 00138 // %f format number -> Float (no %e allowed) 00139 // Sequence of digits -> Integer 00140 // Nothing else allowed. 00141 private static void parseArguments(String argList, 00142 ArrayList<Integer> intList, 00143 ArrayList<Float> floatList, 00144 ArrayList<String> stringList, 00145 ArrayList<Boolean> boolList) { 00146 // str is only non-null if an argument starts with a single or double 00147 // quote. str is set back to null on completion of the string with a 00148 // matching quote. If the string contains a comma then str will stay 00149 // non-null across multiple argStr values until a matching closing quote. 00150 // Backslash escaped quotes do not count as terminating the string. 00151 String str = null; 00152 for (String argStr : argList.split(",")) { 00153 if (str != null) { 00154 // Last string was incomplete. Append argStr to it and restore comma. 00155 // Execute str += "," + argStr in Java. 00156 int length = str.length() + 1 + argStr.length(); 00157 StringBuilder appended = new StringBuilder(length); 00158 appended.append(str); 00159 appended.append(","); 00160 appended.append(argStr); 00161 str = appended.toString(); 00162 } else if (argStr.length() == 0) { 00163 continue; 00164 } else { 00165 char quote = argStr.charAt(0); 00166 // If it begins with a quote then it is a string, but may not 00167 // end this time if it contained a comma. 00168 if (quote == '\'' || quote == '"') { 00169 str = argStr; 00170 } 00171 } 00172 if (str != null) { 00173 // It began with a quote. Check that it still does. 00174 assert str.charAt(0) == '\'' || str.charAt(0) == '"'; 00175 int len = str.length(); 00176 if (len > 1 && str.charAt(len - 1) == str.charAt(0)) { 00177 // We have an ending quote of the right type. Now check that 00178 // it is not escaped. Must have an even number of slashes before. 00179 int slash = len - 1; 00180 while (slash > 0 && str.charAt(slash - 1) == '\\') 00181 --slash; 00182 if ((len - 1 - slash) % 2 == 0) { 00183 // It is now complete. Chop off the quotes and save. 00184 // TODO(rays) remove the first backslash of each pair. 00185 stringList.add(str.substring(1, len - 1)); 00186 str = null; 00187 } 00188 } 00189 // If str is not null here, then we have a string with a comma in it. 00190 // Append , and the next argument at the next iteration, but check 00191 // that str is null after the loop terminates in case it was an 00192 // unterminated string. 00193 } else if (floatPattern.matcher(argStr).matches()) { 00194 // It is a float. 00195 floatList.add(Float.parseFloat(argStr)); 00196 } else if (argStr.equals("true")) { 00197 boolList.add(true); 00198 } else if (argStr.equals("false")) { 00199 boolList.add(false); 00200 } else if (intPattern.matcher(argStr).matches()) { 00201 // Only contains digits so must be an int. 00202 intList.add(Integer.parseInt(argStr)); 00203 } 00204 // else ignore all incompatible arguments for forward compatibility. 00205 } 00206 // All strings must have been terminated. 00207 assert str == null; 00208 } 00209 00211 private static void processInput(String inputLine) { 00212 if (inputLine == null) { 00213 return; 00214 } 00215 // Execute a function encoded as a LUA statement! Yuk! 00216 if (inputLine.charAt(0) == 'w') { 00217 // This is a method call on a window. Parse it. 00218 String noWLine = inputLine.substring(1); 00219 String[] idStrs = noWLine.split("[ :]", 2); 00220 int windowID = Integer.parseInt(idStrs[0]); 00221 // Find the parentheses. 00222 int start = inputLine.indexOf('('); 00223 int end = inputLine.lastIndexOf(')'); 00224 // Parse the args. 00225 ArrayList<Integer> intList = new ArrayList<Integer>(4); 00226 ArrayList<Float> floatList = new ArrayList<Float>(2); 00227 ArrayList<String> stringList = new ArrayList<String>(4); 00228 ArrayList<Boolean> boolList = new ArrayList<Boolean>(3); 00229 parseArguments(inputLine.substring(start + 1, end), 00230 intList, floatList, stringList, boolList); 00231 int colon = inputLine.indexOf(':'); 00232 if (colon > 1 && colon < start) { 00233 // This is a regular function call. Look for the name and call it. 00234 String func = inputLine.substring(colon + 1, start); 00235 if (func.equals("drawLine")) { 00236 windows.get(windowID).drawLine(intList.get(0), intList.get(1), 00237 intList.get(2), intList.get(3)); 00238 } else if (func.equals("createPolyline")) { 00239 windows.get(windowID).createPolyline(intList.get(0)); 00240 } else if (func.equals("drawPolyline")) { 00241 windows.get(windowID).drawPolyline(); 00242 } else if (func.equals("drawRectangle")) { 00243 windows.get(windowID).drawRectangle(intList.get(0), intList.get(1), 00244 intList.get(2), intList.get(3)); 00245 } else if (func.equals("setVisible")) { 00246 windows.get(windowID).setVisible(boolList.get(0)); 00247 } else if (func.equals("setAlwaysOnTop")) { 00248 windows.get(windowID).setAlwaysOnTop(boolList.get(0)); 00249 } else if (func.equals("addMessage")) { 00250 windows.get(windowID).addMessage(stringList.get(0)); 00251 } else if (func.equals("addMessageBox")) { 00252 windows.get(windowID).addMessageBox(); 00253 } else if (func.equals("clear")) { 00254 windows.get(windowID).clear(); 00255 } else if (func.equals("setStrokeWidth")) { 00256 windows.get(windowID).setStrokeWidth(floatList.get(0)); 00257 } else if (func.equals("drawEllipse")) { 00258 windows.get(windowID).drawEllipse(intList.get(0), intList.get(1), 00259 intList.get(2), intList.get(3)); 00260 } else if (func.equals("pen")) { 00261 if (intList.size() == 4) { 00262 windows.get(windowID).pen(intList.get(0), intList.get(1), 00263 intList.get(2), intList.get(3)); 00264 } else { 00265 windows.get(windowID).pen(intList.get(0), intList.get(1), 00266 intList.get(2)); 00267 } 00268 } else if (func.equals("brush")) { 00269 if (intList.size() == 4) { 00270 windows.get(windowID).brush(intList.get(0), intList.get(1), 00271 intList.get(2), intList.get(3)); 00272 } else { 00273 windows.get(windowID).brush(intList.get(0), intList.get(1), 00274 intList.get(2)); 00275 } 00276 } else if (func.equals("textAttributes")) { 00277 windows.get(windowID).textAttributes(stringList.get(0), 00278 intList.get(0), 00279 boolList.get(0), 00280 boolList.get(1), 00281 boolList.get(2)); 00282 } else if (func.equals("drawText")) { 00283 windows.get(windowID).drawText(intList.get(0), intList.get(1), 00284 stringList.get(0)); 00285 } else if (func.equals("addMenuBarItem")) { 00286 if (boolList.size() > 0) { 00287 windows.get(windowID).addMenuBarItem(stringList.get(0), 00288 stringList.get(1), 00289 intList.get(0), 00290 boolList.get(0)); 00291 } else if (intList.size() > 0) { 00292 windows.get(windowID).addMenuBarItem(stringList.get(0), 00293 stringList.get(1), 00294 intList.get(0)); 00295 } else { 00296 windows.get(windowID).addMenuBarItem(stringList.get(0), 00297 stringList.get(1)); 00298 } 00299 } else if (func.equals("addPopupMenuItem")) { 00300 if (stringList.size() == 4) { 00301 windows.get(windowID).addPopupMenuItem(stringList.get(0), 00302 stringList.get(1), 00303 intList.get(0), 00304 stringList.get(2), 00305 stringList.get(3)); 00306 } else { 00307 windows.get(windowID).addPopupMenuItem(stringList.get(0), 00308 stringList.get(1)); 00309 } 00310 } else if (func.equals("update")) { 00311 windows.get(windowID).update(); 00312 } else if (func.equals("showInputDialog")) { 00313 windows.get(windowID).showInputDialog(stringList.get(0)); 00314 } else if (func.equals("showYesNoDialog")) { 00315 windows.get(windowID).showYesNoDialog(stringList.get(0)); 00316 } else if (func.equals("zoomRectangle")) { 00317 windows.get(windowID).zoomRectangle(intList.get(0), intList.get(1), 00318 intList.get(2), intList.get(3)); 00319 } else if (func.equals("readImage")) { 00320 PImage image = SVImageHandler.readImage(intList.get(2), in); 00321 windows.get(windowID).drawImage(image, intList.get(0), intList.get(1)); 00322 } else if (func.equals("drawImage")) { 00323 PImage image = new PImage(stringList.get(0)); 00324 windows.get(windowID).drawImage(image, intList.get(0), intList.get(1)); 00325 } else if (func.equals("destroy")) { 00326 windows.get(windowID).destroy(); 00327 } 00328 // else for forward compatibility purposes, silently ignore any 00329 // unrecognized function call. 00330 } else { 00331 // No colon. Check for create window. 00332 if (idStrs[1].startsWith("= luajava.newInstance")) { 00333 while (windows.size() <= windowID) { 00334 windows.add(null); 00335 } 00336 windows.set(windowID, new SVWindow(stringList.get(1), 00337 intList.get(0), intList.get(1), 00338 intList.get(2), intList.get(3), 00339 intList.get(4), intList.get(5), 00340 intList.get(6))); 00341 } 00342 // else for forward compatibility purposes, silently ignore any 00343 // unrecognized function call. 00344 } 00345 } else if (inputLine.startsWith("svmain")) { 00346 // Startup or end. Startup is a lua bind, which is now a no-op. 00347 if (inputLine.startsWith("svmain:exit")) { 00348 exit(); 00349 } 00350 // else for forward compatibility purposes, silently ignore any 00351 // unrecognized function call. 00352 } 00353 // else for forward compatibility purposes, silently ignore any 00354 // unrecognized function call. 00355 } 00356 00358 public static void exit() { 00359 System.exit(0); 00360 } 00361 00366 public static void main(String[] args) { 00367 if (args.length > 0) { 00368 SERVER_PORT = Integer.parseInt(args[0]); 00369 } 00370 windows = new ArrayList<SVWindow>(100); 00371 intPattern = Pattern.compile("[0-9-][0-9]*"); 00372 floatPattern = Pattern.compile("[0-9-][0-9]*\\.[0-9]*"); 00373 00374 try { 00375 // Open a socket to listen on. 00376 ServerSocket serverSocket = new ServerSocket(SERVER_PORT); 00377 System.out.println("Socket started on port " + SERVER_PORT); 00378 00379 // Wait (blocking) for an incoming connection 00380 socket = serverSocket.accept(); 00381 System.out.println("Client connected"); 00382 00383 // Setup the streams 00384 out = new PrintStream(socket.getOutputStream(), true); 00385 in = 00386 new BufferedReader(new InputStreamReader(socket.getInputStream(), 00387 "UTF8")); 00388 } catch (IOException e) { 00389 // Something went wrong and we were unable to set up a connection. This is 00390 // pretty 00391 // much a fatal error. 00392 // Note: The server does not get restarted automatically if this happens. 00393 e.printStackTrace(); 00394 System.exit(1); 00395 } 00396 00397 // Enter the main program loop. 00398 IOLoop(); 00399 } 00400 }