- Timestamp:
- 2014-08-16T23:50:43+02:00 (10 years ago)
- Location:
- trunk/src/org/openstreetmap/josm
- Files:
-
- 1 added
- 1 deleted
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/data/imagery/GeorefImage.java
r7132 r7425 73 73 image.flush(); 74 74 } 75 changeImage(null, null );76 } 77 78 public void changeImage(State state, BufferedImage image ) {75 changeImage(null, null, null); 76 } 77 78 public void changeImage(State state, BufferedImage image, String errorMsg) { 79 79 flushResizedCachedInstance(); 80 80 this.image = image; … … 85 85 case FAILED: 86 86 BufferedImage imgFailed = createImage(); 87 layer.drawErrorTile(imgFailed );87 layer.drawErrorTile(imgFailed, errorMsg); 88 88 this.image = imgFailed; 89 89 break; -
trunk/src/org/openstreetmap/josm/gui/layer/ImageryLayer.java
r7291 r7425 9 9 import java.awt.Component; 10 10 import java.awt.Font; 11 import java.awt.Graphics ;11 import java.awt.Graphics2D; 12 12 import java.awt.GridBagLayout; 13 13 import java.awt.event.ActionEvent; 14 import java.awt.font.FontRenderContext; 15 import java.awt.font.LineBreakMeasurer; 16 import java.awt.font.TextAttribute; 17 import java.awt.font.TextLayout; 14 18 import java.awt.image.BufferedImage; 15 19 import java.awt.image.BufferedImageOp; 16 20 import java.awt.image.ConvolveOp; 17 21 import java.awt.image.Kernel; 22 import java.text.AttributedCharacterIterator; 23 import java.text.AttributedString; 24 import java.util.Hashtable; 18 25 import java.util.List; 26 import java.util.Map; 19 27 20 28 import javax.swing.AbstractAction; … … 68 76 private final ImageryAdjustAction adjustAction = new ImageryAdjustAction(this); 69 77 78 /** 79 * Constructs a new {@code ImageryLayer}. 80 */ 70 81 public ImageryLayer(ImageryInfo info) { 71 82 super(info.getName()); … … 81 92 } 82 93 83 public double getPPD() {94 public double getPPD() { 84 95 if (!Main.isDisplayingMapView()) return Main.getProjection().getDefaultZoomInPPD(); 85 96 ProjectionBounds bounds = Main.map.mapView.getProjectionBounds(); … … 231 242 } 232 243 233 public void drawErrorTile(BufferedImage img) { 234 Graphics g = img.getGraphics(); 244 /** 245 * Draws a red error tile when imagery tile cannot be fetched. 246 * @param img The buffered image 247 * @param message Additional error message to display 248 */ 249 public void drawErrorTile(BufferedImage img, String message) { 250 Graphics2D g = (Graphics2D) img.getGraphics(); 235 251 g.setColor(Color.RED); 236 252 g.fillRect(0, 0, img.getWidth(), img.getHeight()); 237 g.setFont(g.getFont().deriveFont(Font.PLAIN).deriveFont( 36.0f));253 g.setFont(g.getFont().deriveFont(Font.PLAIN).deriveFont(24.0f)); 238 254 g.setColor(Color.BLACK); 239 255 240 256 String text = tr("ERROR"); 241 g.drawString(text, (img.getWidth() + g.getFontMetrics().stringWidth(text)) / 2, img.getHeight()/2); 242 } 243 244 /* (non-Javadoc) 245 * @see org.openstreetmap.josm.gui.layer.Layer#destroy() 246 */ 257 g.drawString(text, (img.getWidth() - g.getFontMetrics().stringWidth(text)) / 2, g.getFontMetrics().getHeight()+5); 258 if (message != null) { 259 float drawPosY = 2.5f*g.getFontMetrics().getHeight()+10; 260 if (!message.contains(" ")) { 261 g.setFont(g.getFont().deriveFont(Font.PLAIN).deriveFont(18.0f)); 262 g.drawString(message, 5, (int)drawPosY); 263 } else { 264 // Draw message on several lines 265 Map<TextAttribute, Object> map = new Hashtable<TextAttribute, Object>(); 266 map.put(TextAttribute.FAMILY, "Serif"); 267 map.put(TextAttribute.SIZE, new Float(18.0)); 268 AttributedString vanGogh = new AttributedString(message, map); 269 // Create a new LineBreakMeasurer from the text 270 AttributedCharacterIterator paragraph = vanGogh.getIterator(); 271 int paragraphStart = paragraph.getBeginIndex(); 272 int paragraphEnd = paragraph.getEndIndex(); 273 FontRenderContext frc = g.getFontRenderContext(); 274 LineBreakMeasurer lineMeasurer = new LineBreakMeasurer(paragraph, frc); 275 // Set break width to width of image with some margin 276 float breakWidth = img.getWidth()-10; 277 // Set position to the index of the first character in the text 278 lineMeasurer.setPosition(paragraphStart); 279 // Get lines until the entire paragraph has been displayed 280 while (lineMeasurer.getPosition() < paragraphEnd) { 281 // Retrieve next layout 282 TextLayout layout = lineMeasurer.nextLayout(breakWidth); 283 284 // Compute pen x position 285 float drawPosX = layout.isLeftToRight() ? 0 : breakWidth - layout.getAdvance(); 286 287 // Move y-coordinate by the ascent of the layout 288 drawPosY += layout.getAscent(); 289 290 // Draw the TextLayout at (drawPosX, drawPosY) 291 layout.draw(g, drawPosX, drawPosY); 292 293 // Move y-coordinate in preparation for next layout 294 drawPosY += layout.getDescent() + layout.getLeading(); 295 } 296 } 297 } 298 } 299 247 300 @Override 248 301 public void destroy() { -
trunk/src/org/openstreetmap/josm/gui/layer/WMSLayer.java
r7140 r7425 62 62 import org.openstreetmap.josm.gui.progress.ProgressMonitor; 63 63 import org.openstreetmap.josm.io.WMSLayerImporter; 64 import org.openstreetmap.josm.io.imagery.Grabber;65 64 import org.openstreetmap.josm.io.imagery.HTMLGrabber; 65 import org.openstreetmap.josm.io.imagery.WMSException; 66 66 import org.openstreetmap.josm.io.imagery.WMSGrabber; 67 67 import org.openstreetmap.josm.io.imagery.WMSRequest; … … 147 147 private final Lock requestQueueLock = new ReentrantLock(); 148 148 private final Condition queueEmpty = requestQueueLock.newCondition(); 149 private final List< Grabber> grabbers = new ArrayList<>();149 private final List<WMSGrabber> grabbers = new ArrayList<>(); 150 150 private final List<Thread> grabberThreads = new ArrayList<>(); 151 151 private boolean canceled; … … 163 163 } 164 164 165 /** 166 * Constructs a new {@code WMSLayer}. 167 */ 165 168 public WMSLayer(ImageryInfo info) { 166 169 super(info); … … 648 651 GeorefImage img = images[modulo(request.getXIndex(),dax)][modulo(request.getYIndex(),day)]; 649 652 if (img.equalPosition(request.getXIndex(), request.getYIndex())) { 650 img.changeImage(request.getState(), request.getImage()); 653 WMSException we = request.getException(); 654 img.changeImage(request.getState(), request.getImage(), we != null ? we.getMessage() : null); 651 655 } 652 656 } … … 931 935 Main.map.mapView.zoomTo(Main.map.mapView.getCenter(), 1 / info.getPixelPerDegree()); 932 936 } 933 934 937 } 935 938 … … 938 941 try { 939 942 canceled = true; 940 for ( Grabber grabber: grabbers) {943 for (WMSGrabber grabber: grabbers) { 941 944 grabber.cancel(); 942 945 } … … 964 967 grabberThreads.clear(); 965 968 for (int i=0; i<threadCount; i++) { 966 Grabber grabber = getGrabber(i == 0 && threadCount > 1);969 WMSGrabber grabber = getGrabber(i == 0 && threadCount > 1); 967 970 grabbers.add(grabber); 968 971 Thread t = new Thread(grabber, "WMS " + getName() + " " + i); … … 1005 1008 } 1006 1009 1007 protected Grabber getGrabber(boolean localOnly) {1010 protected WMSGrabber getGrabber(boolean localOnly) { 1008 1011 if (getInfo().getImageryType() == ImageryType.HTML) 1009 1012 return new HTMLGrabber(Main.map.mapView, this, localOnly); -
trunk/src/org/openstreetmap/josm/io/imagery/WMSGrabber.java
r7132 r7425 9 9 import java.io.InputStream; 10 10 import java.io.InputStreamReader; 11 import java.io.StringReader; 11 12 import java.net.HttpURLConnection; 12 13 import java.net.MalformedURLException; … … 17 18 import java.text.DecimalFormatSymbols; 18 19 import java.text.NumberFormat; 20 import java.util.ArrayList; 19 21 import java.util.HashMap; 22 import java.util.List; 20 23 import java.util.Locale; 21 24 import java.util.Map; … … 24 27 import java.util.regex.Pattern; 25 28 29 import javax.xml.parsers.DocumentBuilder; 30 import javax.xml.parsers.DocumentBuilderFactory; 31 import javax.xml.parsers.ParserConfigurationException; 32 26 33 import org.openstreetmap.josm.Main; 34 import org.openstreetmap.josm.data.ProjectionBounds; 27 35 import org.openstreetmap.josm.data.coor.EastNorth; 28 36 import org.openstreetmap.josm.data.coor.LatLon; … … 35 43 import org.openstreetmap.josm.tools.ImageProvider; 36 44 import org.openstreetmap.josm.tools.Utils; 37 38 public class WMSGrabber extends Grabber { 45 import org.w3c.dom.Document; 46 import org.w3c.dom.NodeList; 47 import org.xml.sax.InputSource; 48 import org.xml.sax.SAXException; 49 50 /** 51 * WMS grabber, fetching tiles from WMS server. 52 * @since 3715 53 */ 54 public class WMSGrabber implements Runnable { 55 56 protected final MapView mv; 57 protected final WMSLayer layer; 58 private final boolean localOnly; 59 60 protected ProjectionBounds b; 61 protected volatile boolean canceled; 39 62 40 63 protected String baseURL; … … 42 65 private Map<String, String> props = new HashMap<>(); 43 66 67 /** 68 * Constructs a new {@code WMSGrabber}. 69 * @param mv Map view 70 * @param layer WMS layer 71 */ 44 72 public WMSGrabber(MapView mv, WMSLayer layer, boolean localOnly) { 45 super(mv, layer, localOnly); 73 this.mv = mv; 74 this.layer = layer; 75 this.localOnly = localOnly; 46 76 this.info = layer.getInfo(); 47 77 this.baseURL = info.getUrl(); 48 if (layer.getInfo().getCookies() != null && !layer.getInfo().getCookies().isEmpty()) {78 if (layer.getInfo().getCookies() != null && !layer.getInfo().getCookies().isEmpty()) { 49 79 props.put("Cookie", layer.getInfo().getCookies()); 50 80 } … … 60 90 } 61 91 92 int width() { 93 return layer.getBaseImageWidth(); 94 } 95 96 int height() { 97 return layer.getBaseImageHeight(); 98 } 99 62 100 @Override 63 void fetch(WMSRequest request, int attempt) throws Exception{ 101 public void run() { 102 while (true) { 103 if (canceled) 104 return; 105 WMSRequest request = layer.getRequest(localOnly); 106 if (request == null) 107 return; 108 this.b = layer.getBounds(request); 109 if (request.isPrecacheOnly()) { 110 if (!layer.cache.hasExactMatch(Main.getProjection(), request.getPixelPerDegree(), b.minEast, b.minNorth)) { 111 attempt(request); 112 } else if (Main.isDebugEnabled()) { 113 Main.debug("Ignoring "+request+" (precache only + exact match)"); 114 } 115 } else if (!loadFromCache(request)){ 116 attempt(request); 117 } else if (Main.isDebugEnabled()) { 118 Main.debug("Ignoring "+request+" (loaded from cache)"); 119 } 120 layer.finishRequest(request); 121 } 122 } 123 124 protected void attempt(WMSRequest request){ // try to fetch the image 125 int maxTries = 5; // n tries for every image 126 for (int i = 1; i <= maxTries; i++) { 127 if (canceled) 128 return; 129 try { 130 if (!request.isPrecacheOnly() && !layer.requestIsVisible(request)) 131 return; 132 fetch(request, i); 133 break; // break out of the retry loop 134 } catch (IOException e) { 135 try { // sleep some time and then ask the server again 136 Thread.sleep(random(1000, 2000)); 137 } catch (InterruptedException e1) { 138 Main.debug("InterruptedException in "+getClass().getSimpleName()+" during WMS request"); 139 } 140 if (i == maxTries) { 141 Main.error(e); 142 request.finish(State.FAILED, null, null); 143 } 144 } catch (WMSException e) { 145 // Fail fast in case of WMS Service exception: useless to retry: 146 // either the URL is wrong or the server suffers huge problems 147 Main.error("WMS service exception while requesting "+e.getUrl()+":\n"+e.getMessage().trim()); 148 request.finish(State.FAILED, null, e); 149 break; // break out of the retry loop 150 } 151 } 152 } 153 154 public static int random(int min, int max) { 155 return (int)(Math.random() * ((max+1)-min) ) + min; 156 } 157 158 public final void cancel() { 159 canceled = true; 160 } 161 162 private void fetch(WMSRequest request, int attempt) throws IOException, WMSException { 64 163 URL url = null; 65 164 try { … … 68 167 b.maxEast, b.maxNorth, 69 168 width(), height()); 70 request.finish(State.IMAGE, grab(request, url, attempt) );71 72 } catch (Exception e) {169 request.finish(State.IMAGE, grab(request, url, attempt), null); 170 171 } catch (IOException | OsmTransferException e) { 73 172 Main.error(e); 74 throw new Exception(e.getMessage() + "\nImage couldn't be fetched: " + (url != null ? url.toString() : ""), e); 75 } 76 } 77 78 public static final NumberFormat latLonFormat = new DecimalFormat("###0.0000000", 79 new DecimalFormatSymbols(Locale.US)); 173 throw new IOException(e.getMessage() + "\nImage couldn't be fetched: " + (url != null ? url.toString() : ""), e); 174 } 175 } 176 177 public static final NumberFormat latLonFormat = new DecimalFormat("###0.0000000", new DecimalFormatSymbols(Locale.US)); 80 178 81 179 protected URL getURL(double w, double s,double e,double n, … … 133 231 } 134 232 135 @Override136 233 public boolean loadFromCache(WMSRequest request) { 137 234 BufferedImage cached = layer.cache.getExactMatch( … … 139 236 140 237 if (cached != null) { 141 request.finish(State.IMAGE, cached );238 request.finish(State.IMAGE, cached, null); 142 239 return true; 143 240 } else if (request.isAllowPartialCacheMatch()) { … … 145 242 Main.getProjection(), request.getPixelPerDegree(), b.minEast, b.minNorth); 146 243 if (partialMatch != null) { 147 request.finish(State.PARTLY_IN_CACHE, partialMatch );244 request.finish(State.PARTLY_IN_CACHE, partialMatch, null); 148 245 return true; 149 246 } 150 247 } 151 248 152 if ((!request.isReal() && !layer.hasAutoDownload())){153 request.finish(State.NOT_IN_CACHE, null );249 if ((!request.isReal() && !layer.hasAutoDownload())){ 250 request.finish(State.NOT_IN_CACHE, null, null); 154 251 return true; 155 252 } … … 158 255 } 159 256 160 protected BufferedImage grab(WMSRequest request, URL url, int attempt) throws IOException, OsmTransferException {257 protected BufferedImage grab(WMSRequest request, URL url, int attempt) throws WMSException, IOException, OsmTransferException { 161 258 Main.info("Grabbing WMS " + (attempt > 1? "(attempt " + attempt + ") ":"") + url); 162 259 163 260 HttpURLConnection conn = Utils.openHttpConnection(url); 164 for (Entry<String, String> e : props.entrySet()) {261 for (Entry<String, String> e : props.entrySet()) { 165 262 conn.setRequestProperty(e.getKey(), e.getValue()); 166 263 } … … 169 266 170 267 String contentType = conn.getHeaderField("Content-Type"); 171 if( conn.getResponseCode() != 200 172 || contentType != null && !contentType.startsWith("image") ) 173 throw new IOException(readException(conn)); 268 if (conn.getResponseCode() != 200 269 || contentType != null && !contentType.startsWith("image") ) { 270 String xml = readException(conn); 271 try { 272 DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder(); 273 InputSource is = new InputSource(new StringReader(xml)); 274 Document doc = db.parse(is); 275 NodeList nodes = doc.getElementsByTagName("ServiceException"); 276 List<String> exceptions = new ArrayList<>(nodes.getLength()); 277 for (int i = 0; i < nodes.getLength(); i++) { 278 exceptions.add(nodes.item(i).getTextContent()); 279 } 280 throw new WMSException(request, url, exceptions); 281 } catch (SAXException | ParserConfigurationException ex) { 282 throw new IOException(xml, ex); 283 } 284 } 174 285 175 286 ByteArrayOutputStream baos = new ByteArrayOutputStream(); -
trunk/src/org/openstreetmap/josm/io/imagery/WMSRequest.java
r4745 r7425 19 19 private State state; 20 20 private BufferedImage image; 21 private WMSException exception; 21 22 22 23 public WMSRequest(int xIndex, int yIndex, double pixelPerDegree, boolean real, boolean allowPartialCacheMatch) { … … 33 34 } 34 35 35 36 public void finish(State state, BufferedImage image) { 36 public void finish(State state, BufferedImage image, WMSException exception) { 37 37 this.state = state; 38 38 this.image = image; 39 this.exception = exception; 39 40 } 40 41 … … 97 98 } 98 99 100 /** 101 * Replies the resulting state. 102 * @return the resulting state 103 */ 99 104 public State getState() { 100 105 return state; 101 106 } 102 107 108 /** 109 * Replies the resulting image, if any. 110 * @return the resulting image, or {@code null} 111 */ 103 112 public BufferedImage getImage() { 104 113 return image; 114 } 115 116 /** 117 * Replies the resulting exception, if any. 118 * @return the resulting exception, or {@code null} 119 * @since 7425 120 */ 121 public WMSException getException() { 122 return exception; 105 123 } 106 124
Note:
See TracChangeset
for help on using the changeset viewer.