From d50acb4911d668c73fdc417ea58d563ec47f2b5a Mon Sep 17 00:00:00 2001 From: Bane Stojkovic Date: Fri, 18 Mar 2022 20:55:40 +0100 Subject: [PATCH] Improve speed of rendering of the grid --- .../org/diylc/presenter/DrawingManager.java | 366 +++++++++++------- .../src/org/diylc/presenter/update.xml | 16 + diylc/diylc-library/lib/diylc-core.jar | Bin 353214 -> 353214 bytes .../guitar/AbstractGuitarPickup.java | 26 +- .../passive/PotentiometerPanel.java | 27 +- .../semiconductors/TransistorTO3.java | 27 +- diylc/diylc-swing/RegressionTestRunner.launch | 2 +- diylc/diylc-swing/lib/diylc-core.jar | Bin 353214 -> 353214 bytes diylc/diylc-swing/library/main.jar | Bin 791303 -> 791754 bytes 9 files changed, 297 insertions(+), 167 deletions(-) diff --git a/diylc/diylc-core/src/org/diylc/presenter/DrawingManager.java b/diylc/diylc-core/src/org/diylc/presenter/DrawingManager.java index b4e3c55a..600d6eed 100644 --- a/diylc/diylc-core/src/org/diylc/presenter/DrawingManager.java +++ b/diylc/diylc-core/src/org/diylc/presenter/DrawingManager.java @@ -34,6 +34,7 @@ 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.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -108,7 +109,7 @@ public class DrawingManager { private boolean debugComponentAreas; private boolean debugContinuityAreas; - + // rendering stats private Map renderStatsByType = new HashMap(); private long lastStatsReportedTime = System.currentTimeMillis(); @@ -119,28 +120,30 @@ public class DrawingManager { private List proximityMarkers = null; - public DrawingManager(MessageDispatcher messageDispatcher, IConfigurationManager configManager) { + public DrawingManager(MessageDispatcher messageDispatcher, + IConfigurationManager configManager) { super(); this.messageDispatcher = messageDispatcher; this.configManager = configManager; - + try { - this.theme = (Theme) configManager.readObject(IPlugInPort.THEME_KEY, - Constants.DEFAULT_THEME); + this.theme = (Theme) configManager.readObject(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME); } catch (Exception e) { LOG.error("Error loading theme", e); this.theme = Constants.DEFAULT_THEME; // replace bad value with default configManager.writeValue(IPlugInPort.THEME_KEY, Constants.DEFAULT_THEME); } - + componentAreaMap = new HashMap, ComponentArea>(); lastDrawnStateMap = new HashMap, ComponentState>(); String debugComponentAreasStr = System.getProperty(DEBUG_COMPONENT_AREAS); - debugComponentAreas = debugComponentAreasStr != null && debugComponentAreasStr.equalsIgnoreCase("true"); + debugComponentAreas = + debugComponentAreasStr != null && debugComponentAreasStr.equalsIgnoreCase("true"); String debugContinuityAreasStr = System.getProperty(DEBUG_CONTINUITY_AREAS); - debugContinuityAreas = debugContinuityAreasStr != null && debugContinuityAreasStr.equalsIgnoreCase("true"); + debugContinuityAreas = + debugContinuityAreasStr != null && debugContinuityAreasStr.equalsIgnoreCase("true"); } /** @@ -161,10 +164,12 @@ public class DrawingManager { * @param visibleRect * @return */ - public List> drawProject(Graphics2D g2d, Project project, Set drawOptions, - IComponentFilter filter, Rectangle selectionRect, Collection> selectedComponents, - Set> lockedComponents, Set> groupedComponents, List controlPointSlot, - List> componentSlot, boolean dragInProgress, Double externalZoom, Rectangle2D visibleRect) { + public List> drawProject(Graphics2D g2d, Project project, + Set drawOptions, IComponentFilter filter, Rectangle selectionRect, + Collection> selectedComponents, Set> lockedComponents, + Set> groupedComponents, List controlPointSlot, + List> componentSlot, boolean dragInProgress, Double externalZoom, + Rectangle2D visibleRect) { long totalStartTime = System.nanoTime(); failedComponents.clear(); if (project == null) { @@ -185,104 +190,69 @@ public class DrawingManager { if (drawOptions.contains(DrawOption.ANTIALIASING)) { g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, + RenderingHints.VALUE_TEXT_ANTIALIAS_ON); } else { g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); - g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); + g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, + RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); } if (configManager.readBoolean(IPlugInPort.HI_QUALITY_RENDER_KEY, false)) { - g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); - g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); + g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, + RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); + g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, + RenderingHints.VALUE_COLOR_RENDER_QUALITY); g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE); - g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); + g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, + RenderingHints.VALUE_INTERPOLATION_BILINEAR); // g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, // RenderingHints.VALUE_STROKE_PURE); } else { - g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED); - g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_SPEED); + g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, + RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED); + g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, + RenderingHints.VALUE_COLOR_RENDER_SPEED); g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED); g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE); - g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR); + g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, + RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR); } // AffineTransform initialTx = g2d.getTransform(); - Dimension d = getCanvasDimensions(project, zoom, drawOptions.contains(DrawOption.EXTRA_SPACE)); + Dimension canvasDimension = + getCanvasDimensions(project, zoom, drawOptions.contains(DrawOption.EXTRA_SPACE)); g2dWrapper.setColor(theme.getBgColor()); - g2dWrapper.fillRect(0, 0, d.width, d.height); - g2d.clip(new Rectangle(new Point(0, 0), d)); - + g2dWrapper.fillRect(0, 0, canvasDimension.width, canvasDimension.height); + g2d.clip(new Rectangle(new Point(0, 0), canvasDimension)); + + Rectangle2D extraSpaceRect = new Rectangle2D.Double(); + AffineTransform extraSpaceTx = new AffineTransform(); + // calculate size to be rendered double extraSpace = getExtraSpace(project) * zoom; - Dimension dInner = getCanvasDimensions(project, zoom, false); - GridType gridType = GridType.LINES; - if (drawOptions.contains(DrawOption.GRID) && gridType != GridType.NONE) { - double zoomStep = project.getGridSpacing().convertToPixels() * zoom; - float gridThickness = (float) (1f * (zoom > 1 ? 1 : zoom)); - if (gridType == GridType.CROSSHAIR) { - g2d.setStroke(new BasicStroke(gridThickness, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10f, new float[] { - (float) zoomStep / 2, (float) zoomStep / 2}, (float) zoomStep / 4)); - } else if (gridType == GridType.DOT) { - g2d.setStroke(new BasicStroke(gridThickness, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10f, new float[] { - 1f, (float) zoomStep - 1}, 0f)); - } else { - g2d.setStroke(ObjectCache.getInstance().fetchZoomableStroke(gridThickness)); - } - - g2dWrapper.setColor(theme.getGridColor()); - for (double i = zoomStep; i < d.width; i += zoomStep) { - g2dWrapper.draw(new Line2D.Double(i, 0, i, d.height - 1)); - } - for (double j = zoomStep; j < d.height; j += zoomStep) { - g2dWrapper.draw(new Line2D.Double(0, j, d.width - 1, j)); - } - // draw dots if needed - if (project.getDotSpacing() > 1 && zoomStep > 8) { - g2d.setStroke(ObjectCache.getInstance().fetchZoomableStroke(gridThickness * 3)); - g2d.setColor(theme.getDotColor()); - for (double i = extraSpace + zoomStep * project.getDotSpacing(); i < extraSpace + dInner.width; i += zoomStep * project.getDotSpacing()) - for (double j = extraSpace + zoomStep * project.getDotSpacing(); j < extraSpace + dInner.height; j += zoomStep * project.getDotSpacing()) { - g2d.fillOval((int)Math.round(i - 1), (int)Math.round(j - 1), 3, 3); - } - } - } - - Rectangle2D extraSpaceRect = null; - AffineTransform extraSpaceTx = null; - // manage extra space - if (drawOptions.contains(DrawOption.EXTRA_SPACE)) { - float borderThickness = (float) (3f * (zoom > 1 ? 1 : zoom)); - g2d.setStroke(ObjectCache.getInstance().fetchStroke(borderThickness, new float[] {borderThickness * 4, borderThickness * 4, }, 0, BasicStroke.CAP_BUTT)); - g2dWrapper.setColor(theme.getOutlineColor()); - extraSpaceRect = new Rectangle2D.Double(extraSpace, extraSpace, dInner.getWidth(), dInner.getHeight()); - g2d.draw(extraSpaceRect); - extraSpaceTx = g2d.getTransform(); - - // translate to the new (0, 0) - g2d.transform(AffineTransform.getTranslateInstance(extraSpace, extraSpace)); - if (visibleRect != null) - visibleRect.setRect(visibleRect.getX() - extraSpace, visibleRect.getY() - extraSpace, - visibleRect.getWidth(), visibleRect.getHeight()); - } + drawGrid(project, g2d, zoom, extraSpace, canvasDimension, visibleRect, drawOptions, + extraSpaceRect, extraSpaceTx); // apply zoom if (Math.abs(1.0 - zoom) > 1e-4) { g2dWrapper.scale(zoom, zoom); if (visibleRect != null) - visibleRect.setRect(visibleRect.getX() / zoom, visibleRect.getY() / zoom, - visibleRect.getWidth() / zoom, visibleRect.getHeight() / zoom); + visibleRect.setRect(visibleRect.getX() / zoom, visibleRect.getY() / zoom, + visibleRect.getWidth() / zoom, visibleRect.getHeight() / zoom); } - + // Composite mainComposite = g2d.getComposite(); // Composite alphaComposite = // AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f); // g2dWrapper.resetTx(); - + // put components and their states in a map - Map, ComponentState> componentStateMap = new HashMap, ComponentState>(); + Map, ComponentState> componentStateMap = + new HashMap, ComponentState>(); for (IDIYComponent component : project.getComponents()) { ComponentState state = ComponentState.NORMAL; if (drawOptions.contains(DrawOption.SELECTION) && selectedComponents.contains(component)) { @@ -294,9 +264,9 @@ public class DrawingManager { } componentStateMap.put(component, state); } - + boolean outlineMode = drawOptions.contains(DrawOption.OUTLINE_MODE); - + // give the cache a chance to prepare all the components in multiple threads if (drawOptions.contains(DrawOption.ENABLE_CACHING)) { DrawingCache.Instance.bulkPrepare(componentStateMap, g2dWrapper, outlineMode, project, zoom); @@ -312,7 +282,7 @@ public class DrawingManager { // Do not track the area if component is not invalidated and was // drawn in the same state. boolean trackArea = lastDrawnStateMap.get(component) != state; - + synchronized (g2d) { g2dWrapper.startedDrawingComponent(); if (!trackArea) { @@ -326,14 +296,16 @@ public class DrawingManager { // Draw the component through the g2dWrapper. long componentStart = System.nanoTime(); try { - - if (drawOptions.contains(DrawOption.ENABLE_CACHING)) // go through the DrawingCache - DrawingCache.Instance.draw(component, g2dWrapper, state, drawOptions.contains(DrawOption.OUTLINE_MODE), project, zoom, visibleRect); + + if (drawOptions.contains(DrawOption.ENABLE_CACHING)) // go through the DrawingCache + DrawingCache.Instance.draw(component, g2dWrapper, state, + drawOptions.contains(DrawOption.OUTLINE_MODE), project, zoom, visibleRect); else // go straight to the wrapper component.draw(g2dWrapper, state, outlineMode, project, g2dWrapper); - + if (g2dWrapper.isTrackingContinuityArea()) { - LOG.info("Component " + component.getName() + " of type " + component.getClass().getName() + " did not stop tracking continuity area."); + LOG.info("Component " + component.getName() + " of type " + + component.getClass().getName() + " did not stop tracking continuity area."); } } catch (Exception e) { LOG.error("Error drawing " + component.getName(), e); @@ -349,7 +321,7 @@ public class DrawingManager { Counter stats = null; String key = component.getClass().getCanonicalName().replace("org.diylc.components.", ""); if (renderStatsByType.containsKey(key)) { - stats = renderStatsByType.get(key); + stats = renderStatsByType.get(key); } else { stats = new Counter(); renderStatsByType.put(key, stats); @@ -374,13 +346,17 @@ public class DrawingManager { continue; VisibilityPolicy visibilityPolicy = component.getControlPointVisibilityPolicy(i); if ((groupedComponents.contains(component) - && (visibilityPolicy == VisibilityPolicy.ALWAYS || (selectedComponents.contains(component) && visibilityPolicy == VisibilityPolicy.WHEN_SELECTED)) || (!groupedComponents - .contains(component) && !selectedComponents.contains(component) && component - .getControlPointVisibilityPolicy(i) == VisibilityPolicy.ALWAYS))) { + && (visibilityPolicy == VisibilityPolicy.ALWAYS + || (selectedComponents.contains(component) + && visibilityPolicy == VisibilityPolicy.WHEN_SELECTED)) + || (!groupedComponents.contains(component) + && !selectedComponents.contains(component) + && component.getControlPointVisibilityPolicy(i) == VisibilityPolicy.ALWAYS))) { g2dWrapper.setColor(CONTROL_POINT_COLOR); Point2D controlPoint = component.getControlPoint(i); int pointSize = CONTROL_POINT_SIZE - 2; - g2dWrapper.fillOval((int)(controlPoint.getX() - pointSize / 2), (int)(controlPoint.getY() - pointSize / 2), pointSize, pointSize); + g2dWrapper.fillOval((int) (controlPoint.getX() - pointSize / 2), + (int) (controlPoint.getY() - pointSize / 2), pointSize, pointSize); } } } @@ -389,17 +365,19 @@ public class DrawingManager { for (IDIYComponent component : selectedComponents) { for (int i = 0; i < component.getControlPointCount(); i++) { if (!groupedComponents.contains(component) - && (component.getControlPointVisibilityPolicy(i) == VisibilityPolicy.WHEN_SELECTED || component - .getControlPointVisibilityPolicy(i) == VisibilityPolicy.ALWAYS)) { + && (component.getControlPointVisibilityPolicy(i) == VisibilityPolicy.WHEN_SELECTED + || component.getControlPointVisibilityPolicy(i) == VisibilityPolicy.ALWAYS)) { Point2D controlPoint = component.getControlPoint(i); int pointSize = CONTROL_POINT_SIZE; g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR.darker()); - g2dWrapper.fillOval((int)(controlPoint.getX() - pointSize / 2), (int)(controlPoint.getY() - pointSize / 2), pointSize, pointSize); + g2dWrapper.fillOval((int) (controlPoint.getX() - pointSize / 2), + (int) (controlPoint.getY() - pointSize / 2), pointSize, pointSize); g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR); - g2dWrapper.fillOval((int)(controlPoint.getX() - CONTROL_POINT_SIZE / 2 + 1), (int)(controlPoint.getY() - CONTROL_POINT_SIZE / 2 - + 1), CONTROL_POINT_SIZE - 2, CONTROL_POINT_SIZE - 2); + g2dWrapper.fillOval((int) (controlPoint.getX() - CONTROL_POINT_SIZE / 2 + 1), + (int) (controlPoint.getY() - CONTROL_POINT_SIZE / 2 + 1), CONTROL_POINT_SIZE - 2, + CONTROL_POINT_SIZE - 2); } } } @@ -412,8 +390,8 @@ public class DrawingManager { for (IDIYComponent component : componentSlot) { try { - component.draw(g2dWrapper, ComponentState.NORMAL, drawOptions.contains(DrawOption.OUTLINE_MODE), project, - g2dWrapper); + component.draw(g2dWrapper, ComponentState.NORMAL, + drawOptions.contains(DrawOption.OUTLINE_MODE), project, g2dWrapper); } catch (Exception e) { LOG.error("Error drawing " + component.getName(), e); @@ -428,11 +406,13 @@ public class DrawingManager { for (Point2D point : controlPointSlot) { if (point != null) { g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR.darker()); - g2dWrapper.fillOval((int)(point.getX() - CONTROL_POINT_SIZE / 2), (int)(point.getY() - CONTROL_POINT_SIZE / 2), CONTROL_POINT_SIZE, + g2dWrapper.fillOval((int) (point.getX() - CONTROL_POINT_SIZE / 2), + (int) (point.getY() - CONTROL_POINT_SIZE / 2), CONTROL_POINT_SIZE, CONTROL_POINT_SIZE); g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR); - g2dWrapper.fillOval((int)(point.getX() - CONTROL_POINT_SIZE / 2 + 1), (int)(point.getY() - CONTROL_POINT_SIZE / 2 + 1), - CONTROL_POINT_SIZE - 2, CONTROL_POINT_SIZE - 2); + g2dWrapper.fillOval((int) (point.getX() - CONTROL_POINT_SIZE / 2 + 1), + (int) (point.getY() - CONTROL_POINT_SIZE / 2 + 1), CONTROL_POINT_SIZE - 2, + CONTROL_POINT_SIZE - 2); } } } @@ -477,9 +457,8 @@ public class DrawingManager { g2d.draw(a); } } - - if (this.proximityMarkers != null) - { + + if (this.proximityMarkers != null) { g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(2)); g2d.setColor(Color.red); for (Shape s : this.proximityMarkers) @@ -493,33 +472,125 @@ public class DrawingManager { g2d.fill(currentContinuityArea); g2d.setComposite(oldComposite); } - + // shade extra space if (SHADE_EXTRA_SPACE && extraSpaceRect != null) { - Area extraSpaceArea = new Area(new Rectangle2D.Double(0, 0, d.getWidth(), d.getHeight())); + Area extraSpaceArea = new Area( + new Rectangle2D.Double(0, 0, canvasDimension.getWidth(), canvasDimension.getHeight())); extraSpaceArea.subtract(new Area(extraSpaceRect)); g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.05f)); g2d.setTransform(extraSpaceTx); g2d.setColor(theme.getOutlineColor()); g2d.fill(extraSpaceArea); } - + long totalEndTime = System.nanoTime(); - + totalStats.add(totalEndTime - totalStartTime); - + logStats(); return failedComponents; } - + + private double zoomCached = 0; + private Dimension canvasDimensionCached; + private double extraSpaceCached; + private GridType gridTypeCached; + private BufferedImage cachedGridImage; + + private void drawGrid(Project project, Graphics2D g2dIn, double zoom, double extraSpace, + Dimension canvasDimension, Rectangle2D visibleRect, Set drawOptions, + Rectangle2D extraSpaceRect, AffineTransform extraSpaceTx) { + + GridType gridType = GridType.LINES; + + Dimension innerCanvasDimension = getCanvasDimensions(project, zoom, false); + + // draw from cache + if (zoom != zoomCached || !canvasDimension.equals(canvasDimensionCached) + || extraSpace != extraSpaceCached || gridType != gridTypeCached) { + try { + cachedGridImage = new BufferedImage((int) canvasDimension.getWidth(), + (int) canvasDimension.getHeight(), BufferedImage.TYPE_INT_ARGB); + // create graphics + Graphics2D g2d = cachedGridImage.createGraphics(); + + if (drawOptions.contains(DrawOption.GRID) && gridType != GridType.NONE) { + double zoomStep = project.getGridSpacing().convertToPixels() * zoom; + float gridThickness = (float) (1f * (zoom > 1 ? 1 : zoom)); + if (gridType == GridType.CROSSHAIR) { + g2d.setStroke(new BasicStroke(gridThickness, BasicStroke.CAP_BUTT, + BasicStroke.JOIN_MITER, 10f, + new float[] {(float) zoomStep / 2, (float) zoomStep / 2}, (float) zoomStep / 4)); + } else if (gridType == GridType.DOT) { + g2d.setStroke(new BasicStroke(gridThickness, BasicStroke.CAP_BUTT, + BasicStroke.JOIN_MITER, 10f, new float[] {1f, (float) zoomStep - 1}, 0f)); + } else { + g2d.setStroke(ObjectCache.getInstance().fetchZoomableStroke(gridThickness)); + } + + g2d.setColor(theme.getGridColor()); + for (double i = zoomStep; i < canvasDimension.width; i += zoomStep) { + g2d.draw(new Line2D.Double(i, 0, i, canvasDimension.height - 1)); + } + for (double j = zoomStep; j < canvasDimension.height; j += zoomStep) { + g2d.draw(new Line2D.Double(0, j, canvasDimension.width - 1, j)); + } + // draw dots if needed + if (project.getDotSpacing() > 1 && zoomStep > 8) { + g2d.setStroke(ObjectCache.getInstance().fetchZoomableStroke(gridThickness * 3)); + g2d.setColor(theme.getDotColor()); + for (double i = extraSpace + zoomStep * project.getDotSpacing(); i < extraSpace + + innerCanvasDimension.width; i += zoomStep * project.getDotSpacing()) + for (double j = extraSpace + zoomStep * project.getDotSpacing(); j < extraSpace + + innerCanvasDimension.height; j += zoomStep * project.getDotSpacing()) { + g2d.fillOval((int) Math.round(i - 1), (int) Math.round(j - 1), 3, 3); + } + } + } + } finally { + zoomCached = zoom; + canvasDimensionCached = (Dimension) canvasDimension.clone(); + extraSpaceCached = extraSpace; + gridTypeCached = gridType; + } + } + + if (cachedGridImage == null) { + LOG.warn("Cached grid image is null!"); + return; + } + + g2dIn.drawImage(cachedGridImage, 0, 0, null); + + // manage extra space + if (drawOptions.contains(DrawOption.EXTRA_SPACE)) { + float borderThickness = (float) (3f * (zoom > 1 ? 1 : zoom)); + g2dIn.setStroke(ObjectCache.getInstance().fetchStroke(borderThickness, + new float[] {borderThickness * 4, borderThickness * 4,}, 0, BasicStroke.CAP_BUTT)); + g2dIn.setColor(theme.getOutlineColor()); + extraSpaceRect.setRect(new Rectangle2D.Double(extraSpace, extraSpace, + innerCanvasDimension.getWidth(), innerCanvasDimension.getHeight())); + g2dIn.draw(extraSpaceRect); + extraSpaceTx.setTransform(g2dIn.getTransform()); + + // translate to the new (0, 0) + g2dIn.transform(AffineTransform.getTranslateInstance(extraSpace, extraSpace)); + if (visibleRect != null) + visibleRect.setRect(visibleRect.getX() - extraSpace, visibleRect.getY() - extraSpace, + visibleRect.getWidth(), visibleRect.getHeight()); + } + } + public void logStats() { // log render time stats periodically if (System.currentTimeMillis() - lastStatsReportedTime > statReportFrequencyMs) { lastStatsReportedTime = System.currentTimeMillis(); - String mapAsString = renderStatsByType.entrySet().stream().sorted((e1, e2) -> -Long.compare(e1.getValue().getNanoTime(), e2.getValue().getNanoTime())) - .map(e -> e.toString()) - .collect(Collectors.joining("; ", "{", "}")); + String mapAsString = renderStatsByType.entrySet().stream() + .sorted( + (e1, e2) -> -Long.compare(e1.getValue().getNanoTime(), e2.getValue().getNanoTime())) + .map(e -> e.toString()).collect(Collectors.joining("; ", "{", "}")); LOG.debug("Render stats: " + mapAsString); LOG.debug("Page stats: " + totalStats.toAvgString()); DrawingCache.Instance.logStats(); @@ -572,11 +643,13 @@ public class DrawingManager { public double getExtraSpace(Project project) { double width = project.getWidth().convertToPixels(); double height = project.getHeight().convertToPixels(); - double targetExtraSpace = EXTRA_SPACE * Math.max(width, height); - return CalcUtils.roundToGrid(targetExtraSpace, project.getGridSpacing().scale(project.getDotSpacing())); + double targetExtraSpace = EXTRA_SPACE * Math.max(width, height); + return CalcUtils.roundToGrid(targetExtraSpace, + project.getGridSpacing().scale(project.getDotSpacing())); } - public Dimension getCanvasDimensions(Project project, Double zoomLevel, boolean includeExtraSpace) { + public Dimension getCanvasDimensions(Project project, Double zoomLevel, + boolean includeExtraSpace) { double width = project.getWidth().convertToPixels(); double height = project.getHeight().convertToPixels(); @@ -588,7 +661,7 @@ public class DrawingManager { width *= zoomLevel; height *= zoomLevel; - + return new Dimension((int) width, (int) height); } @@ -606,7 +679,7 @@ public class DrawingManager { configManager.writeValue(IPlugInPort.THEME_KEY, theme); messageDispatcher.dispatchMessage(EventType.REPAINT); } - + public void findContinuityAreaAtPoint(Project project, Point2D p) { if (continuityAreaCache == null) continuityAreaCache = getContinuityAreas(project); @@ -620,7 +693,7 @@ public class DrawingManager { currentContinuityArea = null; } - + public List getContinuityAreas(Project project) { // Find all individual continuity areas for all components List preliminaryAreas = new ArrayList(); @@ -628,11 +701,11 @@ public class DrawingManager { Set connections = new HashSet(); for (IDIYComponent c : project.getComponents()) { ComponentArea a = getComponentArea(c); - + if (c instanceof IContinuity) { for (int i = 0; i < c.getControlPointCount() - 1; i++) for (int j = i + 1; j < c.getControlPointCount(); j++) - if (((IContinuity)c).arePointsConnected(i, j)) + if (((IContinuity) c).arePointsConnected(i, j)) connections.add(new Connection(c.getControlPoint(i), c.getControlPoint(j))); } @@ -654,30 +727,32 @@ public class DrawingManager { checkBreakout.set(i, true); } } - } + } } // Check if we need to break some areas out in case they are interrupted List areas = new ArrayList(); for (int i = 0; i < preliminaryAreas.size(); i++) { Area a = preliminaryAreas.get(i); - if (checkBreakout.get(i)) - areas.addAll(AreaUtils.tryAreaBreakout(a)); - else - areas.add(a); + if (checkBreakout.get(i)) + areas.addAll(AreaUtils.tryAreaBreakout(a)); + else + areas.add(a); } - + CalcUtils.expandConnections(connections); AreaUtils.crunchAreas(areas, connections); - + return areas; } - + public List getContinuityAreaProximity(Project project, float threshold) { - List continuityAreas = getContinuityAreas(project); - Stroke s = ObjectCache.getInstance().fetchBasicStroke(threshold - 1); // value eyeballed for approx good results - List expanded = continuityAreas.parallelStream().map((a) -> new Area(s.createStrokedShape(a))).collect(Collectors.toList()); + List continuityAreas = getContinuityAreas(project); + Stroke s = ObjectCache.getInstance().fetchBasicStroke(threshold - 1); // value eyeballed for + // approx good results + List expanded = continuityAreas.parallelStream() + .map((a) -> new Area(s.createStrokedShape(a))).collect(Collectors.toList()); List intersections = new ArrayList(); for (int i = 0; i < expanded.size() - 1; i++) { for (int j = i + 1; j < expanded.size(); j++) { @@ -688,25 +763,28 @@ public class DrawingManager { intersections.add(first); } } - + AreaUtils.crunchAreas(intersections, null); double minSize = new Size(1d, SizeUnit.cm).convertToPixels(); - + List shapes = new ArrayList(); for (Area a : intersections) { Rectangle2D bounds2d = a.getBounds2D(); if (bounds2d.getWidth() < minSize) - bounds2d = new Rectangle2D.Double(bounds2d.getCenterX() - minSize / 2, bounds2d.getY(), minSize, bounds2d.getHeight()); + bounds2d = new Rectangle2D.Double(bounds2d.getCenterX() - minSize / 2, bounds2d.getY(), + minSize, bounds2d.getHeight()); if (bounds2d.getHeight() < minSize) - bounds2d = new Rectangle2D.Double(bounds2d.getX(), bounds2d.getCenterY() - minSize / 2, bounds2d.getWidth(), minSize); - - shapes.add(new Area(new Ellipse2D.Double(bounds2d.getX(), bounds2d.getY(), bounds2d.getWidth(), bounds2d.getHeight()))); + bounds2d = new Rectangle2D.Double(bounds2d.getX(), bounds2d.getCenterY() - minSize / 2, + bounds2d.getWidth(), minSize); + + shapes.add(new Area(new Ellipse2D.Double(bounds2d.getX(), bounds2d.getY(), + bounds2d.getWidth(), bounds2d.getHeight()))); } - - //AreaUtils.crunchAreas(shapes, null); - - this.proximityMarkers = shapes; - + + // AreaUtils.crunchAreas(shapes, null); + + this.proximityMarkers = shapes; + return shapes; } } diff --git a/diylc/diylc-core/src/org/diylc/presenter/update.xml b/diylc/diylc-core/src/org/diylc/presenter/update.xml index 869037ce..9205a56c 100644 --- a/diylc/diylc-core/src/org/diylc/presenter/update.xml +++ b/diylc/diylc-core/src/org/diylc/presenter/update.xml @@ -3801,5 +3801,21 @@ https://github.com/bancika/diy-layout-creator/releases + + + 4 + 22 + 3 + + 2022-03-18 00:00:00.000 CET + + + + BUG_FIX + Improved rendering performance + + + https://github.com/bancika/diy-layout-creator/releases + diff --git a/diylc/diylc-library/lib/diylc-core.jar b/diylc/diylc-library/lib/diylc-core.jar index c2978555210b5af1ad79439d5905228a652e96ee..4b6444712c5b2e709125e19c9f29cde18661cfc4 100644 GIT binary patch delta 5478 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 E2Y@Zq7XSbN delta 5478 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 maxX) + maxX = bounds2d.getMaxX(); + if (bounds2d.getMaxY() > maxY) + maxY = bounds2d.getMaxY(); + } + } + return new Rectangle2D.Double(minX - margin, minY - margin, maxX - minX + 2 * margin, maxY - minY + 2 * margin); } public enum Polarity { diff --git a/diylc/diylc-library/src/org/diylc/components/passive/PotentiometerPanel.java b/diylc/diylc-library/src/org/diylc/components/passive/PotentiometerPanel.java index 17b832cf..57d5e1ce 100644 --- a/diylc/diylc-library/src/org/diylc/components/passive/PotentiometerPanel.java +++ b/diylc/diylc-library/src/org/diylc/components/passive/PotentiometerPanel.java @@ -27,6 +27,7 @@ import java.awt.Composite; import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.Polygon; +import java.awt.Shape; import java.awt.geom.Area; import java.awt.geom.Ellipse2D; import java.awt.geom.Point2D; @@ -477,14 +478,26 @@ public class PotentiometerPanel extends AbstractPotentiometer { @Override public Rectangle2D getCachingBounds() { - Area area = new Area(); - Area[] body = getBody(); + Shape[] body = getBody(); int margin = 20; - for (Area a : body) - if (a != null) - area.add(a); - Rectangle2D bounds = area.getBounds2D(); - return new Rectangle2D.Double(bounds.getX() - margin, bounds.getY() - margin, bounds.getWidth() + 2 * margin, bounds.getHeight() + 2 * margin); + double minX = 0; + double minY = 0; + double maxX = 0; + double maxY = 0; + for (Shape a : body) { + if (a != null) { + Rectangle2D bounds2d = a.getBounds2D(); + if (bounds2d.getMinX() < minX) + minX = bounds2d.getMinX(); + if (bounds2d.getMinY() < minY) + minY = bounds2d.getMinY(); + if (bounds2d.getMaxX() > maxX) + maxX = bounds2d.getMaxX(); + if (bounds2d.getMaxY() > maxY) + maxY = bounds2d.getMaxY(); + } + } + return new Rectangle2D.Double(minX - margin, minY - margin, maxX - minX + 2 * margin, maxY - minY + 2 * margin); } @Override diff --git a/diylc/diylc-library/src/org/diylc/components/semiconductors/TransistorTO3.java b/diylc/diylc-library/src/org/diylc/components/semiconductors/TransistorTO3.java index e8179f76..7b86d8e9 100644 --- a/diylc/diylc-library/src/org/diylc/components/semiconductors/TransistorTO3.java +++ b/diylc/diylc-library/src/org/diylc/components/semiconductors/TransistorTO3.java @@ -28,6 +28,7 @@ import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.RenderingHints; +import java.awt.Shape; import java.awt.geom.AffineTransform; import java.awt.geom.Area; import java.awt.geom.Ellipse2D; @@ -367,13 +368,25 @@ public class TransistorTO3 extends AbstractLabeledComponent { @Override public Rectangle2D getCachingBounds() { - Area area = new Area(); - Area[] body = getBody(); + Shape[] body = getBody(); int margin = 20; - for (Area a : body) - if (a != null) - area.add(a); - Rectangle2D bounds = area.getBounds2D(); - return new Rectangle2D.Double(bounds.getX() - margin, bounds.getY() - margin, bounds.getWidth() + 2 * margin, bounds.getHeight() + 2 * margin); + double minX = 0; + double minY = 0; + double maxX = 0; + double maxY = 0; + for (Shape a : body) { + if (a != null) { + Rectangle2D bounds2d = a.getBounds2D(); + if (bounds2d.getMinX() < minX) + minX = bounds2d.getMinX(); + if (bounds2d.getMinY() < minY) + minY = bounds2d.getMinY(); + if (bounds2d.getMaxX() > maxX) + maxX = bounds2d.getMaxX(); + if (bounds2d.getMaxY() > maxY) + maxY = bounds2d.getMaxY(); + } + } + return new Rectangle2D.Double(minX - margin, minY - margin, maxX - minX + 2 * margin, maxY - minY + 2 * margin); } } diff --git a/diylc/diylc-swing/RegressionTestRunner.launch b/diylc/diylc-swing/RegressionTestRunner.launch index 5bc0594e..027dba42 100644 --- a/diylc/diylc-swing/RegressionTestRunner.launch +++ b/diylc/diylc-swing/RegressionTestRunner.launch @@ -9,6 +9,6 @@ - + diff --git a/diylc/diylc-swing/lib/diylc-core.jar b/diylc/diylc-swing/lib/diylc-core.jar index c2978555210b5af1ad79439d5905228a652e96ee..4b6444712c5b2e709125e19c9f29cde18661cfc4 100644 GIT binary patch delta 5478 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 E2Y@Zq7XSbN delta 5478 zcmY*bc|cC-8t;A2dFyLWq}10Y5>b|vlvXO078R{jhG8(4nXylXFk`!h4`*y+mt`yo z2Sd1HkbS)_G8n@c`#Q#OZ})wk=lpa3`aR3<+1~A(+T(7u$K4#V(iGLs%F1MAm6ST) zp*8Q3S{=cd1WQ-u2T;rcc~Yw7v}(4jVjdvwXYBzVvvvSpyaPZ6j{=y@g8}yP2!I#7 zBY=$6VzRlDB~!5jy+}dQH%bT;*h>JUgHO5B|8->XQM*D!p&A3QRK?1t)iBUzbF;-q zID;4}+DfP?5%W3VbDKPCz+|T=1~|>RPyxK{S}!D8YCS%HdZ5`!bbsUZ17f&$q6+qj z{&P^b4fp}m=`HIJrv{Z{n)|`NsN00BMtyS!Z`A8LZ9^O%o`Uf|MZ_Q~kvjk_ySx4i z($9^upt*TBPsErQKg815WW-HztpF_-eK z4Enqa>Z`u!;{g5qHN_F*Y^IGs{{T1I`|*fMgLs&(@eZkChPmw>%;=VgE|YHlFe`|PJzI&&+lYD-yNQ!T_x*w<9- zipBhg_6$S}+*gHDo%?w@w$rEX2-=&Sw#K&n&$y%B^;`q$Q5R^sftQ-2KJ)Td=(oRm z6XPFVr%iRJ-voY(eiQcIGVhmn5^84M!Zo)%x$_@TAOGrsNvwa1z$CHva}XCk_}xKX zk(w{xY*7H)ymMEaddTUWd#^5dDF=GOwbd2eO*`B|n6%*m!nLO2!v_x3NeyivMBm7n z6AF6;b4B5_iTSADdhEdRfvYDuvx6=m2tT$$afAX*PyY2;U&YF*x8~x|+cL zZ^cv)s-oL4OcE2q>d<4`kr~Y;ynlZ!UpAM+wIdPCTTkoE24kJw5iE_;Un(7&rOEUQ zw78Ly(I$%Ffcn)Kwga=xOkj&p@JnJE2JcH@J;1UdouPwgvi0cLl+CiOq5BVg*+0-V zr-SwI~&A<^pcTm zH1aQe#>_bIv$1SGTBc59mr&?CnQceGRLTCvmed)n7bTyXwD+i4u7$f6-%1WTaV85z z#t*Yu2&Su_$C`t%XCXU-dvI?L}A8jHWr13w=5HdtoLju%{^;r=$9+yqAsOHZQH=Ak#UQ2KNOfX z{~Co^w!9JrXGdO(!Z{cI28ClycpM5Q555bVsBOmOb(P(;H1qN3TII`sM%Tywd>dNa zTk_o~$PHYI!Y6I{Y!u#xa@x(Ion#(7=zLjc4+q((4W2}8cC@h5)o|Vv`Q}Kz9EJVS zd;tm>aXcEXsy-*4r@_ZUzt)2vfg7(c@5x`lt<~qH^IwoNB7;|Re1NtM{-&2t?`VE8I?xSxj z=D8T8_T&F0p_KoKK}QDg4VY%gAbt~FDT8^C4W^m@x!2c&;L%XERR!Ef3r&!-ZWzHQ zP?giI!vZg=R#sVdmiTRM*rT34n%~DM!^ZOWkXP$4fvcSplcw+r zctZ7KbNLG_y>A}hjIMzTcs{xgeb4RS3#^}7%kKe4+qs_K1H+OH{5)0~x`oej1k2mK zd;+HVY(Ia3rOIo06jCmE@wId1Dktp5XEYk(TDCIesTKr?dP%82&uV z)8Y3+?|zLxz_vo_c{-+`QM#7j;VUpY>K^Zh!mB3?DO9F}s6h;S%LJ4l!ey zQrQ?R_S=;d{?ra&wjP;81P)pK%wTfIurB6{HeC1#@?v`FpjpML5-AyYG)eMIEjm# zMSFmF5f0uXsxU8FB!Z;8=#Yp56Jw$qU>pn90<<=f-rq!ewMpcG-DFEm3}b6 zMLuAf9gY2+f%ojFem8sZDfqYAi@|{I4x%^UPzR9%c-VpBJsqjuFh}wqb|k->lgLHB z6V=z9Xc26jMK;(AovF@FXORN>2WK%FaHI>x9dn_)9*wBqL5(PWPb0FMTuIM&C4I9i z&GFWi`bcX`c~&>3dan&VwF&7fno$35n}|}VTi_;!03LOt^={Er^ap)tkZ$vZd|Dd5edQ$yTPgo76mMG3Yu?mN7ly z`kxj?`&1uBb9d}ad8TzH{d#AL3k|2Z%5cheKAh(EilBZzjv(HF2+C{Mg?N3tkbi9# z>g%O}@sYGH3nIz?i-B#rQvFF?$$p|M#mV(HYn`I-Ro4bak+V7qor|NXc3w2qUK?%H zil#G=&`su)XLn&YI_uB6(Va+&A$@fW-KEztWKWBg`6Pc;EZwblv2^D$OubSB+4@@iS#Q;a>->}^JMB{Y%=jLCeu@5PN6G3E`|C#pCXq_@_l+z z+|Zsh&w-wDb*0^uO8xgsrTC4h7`Hf$+RaI$@YQMfqAX6QE=$tsfjN*))jWF92WwI< zQ3hFW8G2#{J-FL4#2~OY&7=>_SDD1Sn@Qb-Wf4x#qG@g$7?n->Vgp|onBJT0RlRZZ z7U$4nibSWU+Qc}_l(%mIFG>9P0(A_CHbSd54DJdN)&4qdI|Hc>A zK5PG0?tRXjXRmb#FX9|3Q6S*VLTWvTIp8$>ubcQnZNXhbqdY&seUGMs@%T!-QWM0yd$^!Nr- zmF4vZcAXSp2D`osMnim=2YnfXxv~&V{U1LT4MstU^f1Z^$%2`jNYx~K!83l>g$MS#>~A&^1N^3ZVW%7<-WHi*W0h+d?ZcZ6WqB>U1ZYWzD1Mz4<=>7M7I z-*Mo#P+ta#|)ehUu=M-7BI3jMAQj}L?N zX~HMK26{U1kuQd!drt83Fb=mXyf6t&nhkteaD)a2$4{8x%t4kQwvP;HDn-MA)<(hq zMSGDcOM$P1nbygN7Y4m>Qp({wVOn&m;89E@N9S%+dqH>2s{-0e#B>)QaOa-tGGdF1naL0PFE9(HLhGp@_3ouU(lLmOd zzB+wgE<#9GD+)P;69mMCqCo(dFo(%f0e3hrg2d$j*xrDCssxb1*3R!I;QfDljJg0F19*w4;E4$uGMf zno9{3{ZDBy5rQBKF&y0LTgU_h0viOQ84U}{Obz5Ae!&^@1JPkh9fg3iFs0I>z@z^p z<)jeE-aoIyJ_5v8;`yF^i3kD~1!6&cC4m2VF!vr;*1(ww&LFu7C=AJNN5hA%r2(;F z?ww@cjL8J^+5o}-?=ki9- z{x3^?54nY=&wd#)XLuBx2H_6= z2okS`XI?k4iOWTthfitDRo2T}LykIKSe>Qw7snq}`g{brS!wBqmba_seNIlA58Flk z{ckWoA)$3j%P@*?UZ!ryLbZ%HI^zD`ivi7-cztNMzosxOLro`Qm3U%a2449&aS%H!*_aGzhUmgtE$L{1L(Ru z^Y0<}=v4pp(7KavmXZIC=W<7f;}QkZo8^kx^(tQCq0_!0O5qvS?1YN#i(lrra~TxD z#$^smee^0kE4;ePc^oDmO%8!SG^;v_DQv)Hg^Lsoo6R#Hm_#)v->**cl*`dq^Dr_l z=+19+$oH14*IK6=hEfX$4NG^(O|DhRT}JSXe5>^8kWcO5KZzY`;Q{#z|=l{#q{i>G6Djms@&f#ZnjD|9LxnO9-9O_-z%I-atZwEwzAsNKTOWNL{mWTl&9MsfTJU4i$g65=5l*r?e! z{J~x4xoFp3-dbZSO@Zlw*+p{kmW(uD1*}(ugnLRj!jJMzvR4rTCrBx*bSt!8O54Ib zJ<7){A(|5C*%AWctej@lob&+6F9>~RS7bVyBKD5*`=)u5kymdP`QQZ~r>hmDx^`>C z=z4g~9T_P0zm6xiNS9MRFoketzWcOxY5QU9#T)b8f6>;H*@U1h#V z824H$K0(YnH!;3Z2sQK~tg4=l?eHDvdodj*vg+hY)77Ph!#-1II@un-PPzp4dlJil^UT4aCPZSA^vRdip!Q~p#tA;;yXGHa))3_|Lt zk3z{Ge&#=%%d+;m=_Z@dkZ0Sd4v$j2Vg(PqR(Pv%Y>-&*B#{48@lq=NTmLJ~T5A*f z__uh9_W6VAJ?MoVCDvfNday-{#~9$#_SdxhO)DQEQspkn#mgDg4xe{2CUG-_^jZcF zoK=gIRKb0bt+X{xrz0~~d~eLYNhe|cqSnT>Gk4&yDIElzO!^MtZf#uDgm`fZ;46U@ zq)aU8^$HNmE8TT)Jn2Rb24xvhLiu()Zl%C9{^op%OLSUJirg`8G#0XIT_Z=s)(lH1%W(~NNN^V;28c&^_*#V)PC5PPSZ6xIZ8I^LF+HXBcxUg5DCS0!`ErE!hD_m=i zO-N6HIKbDhIkpa0H4DKFAlILz;m)u|gPgRH^Y=!q&Mhm9;-lJTj$`;>?kvGK^TGyM z{1SlMmyl1;rIt_aYW7OZUz%j?z^v&17(F=gYl8lKjnv3+i{~iU3*jq~Fk8xFMoWG3 zCzrwhRhuvlrVMpiSi**=h!kG^_PJ!1U0F+)b+p<~9q?Poa&pTPGFP)APRMZdZf(nL z=)!R$d@&<`c2nD!91CkX`R!>09roZ*rDpa|g4Qs^@0LaV0jQYsZxcTt7lTK!$yYr@ zxVXOzz9SQ``JEv>_9`OjH)|BmgrSFo#JfH7@BBGu3aKccu%n_BYRSwf=A7OOTuwNY zlZhLYs7dU7bvyBRZ@q3s?==#Rc?UFGA&*@0ni3>VjYwrur&c(=sT8s_G*39wM$+Kr zcpt_F$O}GCeb3k?OvBV5knIT0V7o)VeP!_DJ(8k|!X9O?kM&XxpCT9AI2myR#W_h* zvG5!mdDD0f9kl}ULcAkJ)>RmP zjEVpcv9|H_jat(%#{C;`up>U6KV_7d*TP23G)}N+cQ*GvaI2h`#FuN`$BUtKCwD%Df-ResYgXQ)RV3 z-OpVHLydKCw@H57q3fvPB+l9!$>uWb{e{f(i$n%k&SFwV6-XqMgxgX}RO05&wdfzW z4HFzmMHltsnX0mZx7yve+<=oUw@5)gXC<~k-D)8(k140g)iT1P@ALsrONgy4AFB;9 zHb<@W@Hs^a^~a~z7QcGZO{b#84A#MiR~m|iGdM8gru8>^P(u;bRg)}A6Uj>Vmy;p~ zY)jr75+3KEG4z;9Zc1)=Z@kAUSQ(j`Jb!e!^e@0y%ZAW`_pYu!1OA+Le>MS6tJ9IB z;W*>S)SM6eRFEJk?2k&tQ*D+{B~TxK!0s{q)%M{RKJn^@NP#W>dMi1; zULe$BsblwY9;FFUqnmwVrrc0P+GXv$Jk!17(rvMQ3rvTFMZP}gC$~KCs_IgNl1a5= zn1h^9o6X>;kecDnH3}^~Z0pSeBM<&*47sYP@iiAIQEal_-;$OY%IF1JjnpMt9pJWJ zPIf}%-fv!mhuB$OcEgFdLnK1@Z6mKd{C2b?7Hn;s?OBF z4+k!POu@fZQ74JtguY?PaaNT=>l;4!u#~M66HnjE+Lty{v+o$&BQvT}SVoCh`dj5& z8KpV)ZQ(|s3-NI{=N*mGdvk?+3}qbNL;`YJtskt`{R69KtX|T9z+zcZ=}?SYtwF)9 zAy$lUR{W-(V+#osRJ2r|Z(`ymV~g_olUAstThqX(lMcb}_kLYrG~Lh(WWJl`w9g$b z$yE5AV=Fi0{+h%k_L51@)?X;>zn#wv&+$#)F44 zazH3JpF5#$U+e1$BANKyp|-CpCGQhCw2qK`bNjEw*W#Lr7F}1KVr%P$A~~Y69P{%J z|2AVA^iA33wTH8Qt+YVhGnTI=lX zTQ8ytrsU(=3QIjrY2JzcpKpm*K^$x!^M7194{Ua)|HeBri%veLzoj$jQY^kiYC)mJ zT8%okRNZNvDV$~-k+RpXO={@UWOp#NUqfg70G%pk#oF@R5Z?-QoLQ0I6H$CVG_pL1 z0&{2H2xZRxE}gR|J;Awf{w3 z*j>}ir5hHN_4RRACdgWSnC9m-w7y{~8m-#3+}AJC!~)Ghe@DBFdCg`ql=f1D)^G|M zS&*3}7e#MP*3Ec_M3S;txu!LeBa$_EfH!e2jO|(GNDVgH*c6YW_XPog6w<sBSK-&Y^M6b=5u4KHcnWk9pb`!_GU?hYIzvH(H}EP z1WT?{41S-1#oSqX$Rw$Oj-IMmC;i6MgFP)Eu|sR$MeyL0rqv!931G0I3QV8wb5Y@Q zQ7x|&)aBA+n)*sRvh@S=%z?bqtjvK>%BBmk2|nt`Z;KwnM~gxRf3obj!vYuuGmyLmWP)|2gGmcDguAZr8CluW?Jhxth{-&H zB*Ks%vg4dnTv1u@R(erk;$YftEt;rgUSMiVVohBbX2~f>ml;QQ3J1#=OQkT$*z17s zM1kh_nJNM2+0;zhmh}r-hQwCYy8}A0o0@PpZ2XdXyQ@~zp@k}B(E_TR|_dbGz6 zF^`v>d%{1C+$^KHED(T8@=(Iv_~*!F2tkUKl2L4!Z}jS=E1Oj`ba{puu)=4)7pW#V zr+JgE{+00@HTzrFs+yibd$xd(r4LX}?$XhCKq$L&WX{V5xcEz3PLBt|cZyYBv6!tJ zNw#+eqWFim-3UxvVdRXYi+zQDn)$^!*Lr2@9b@3cz`-@|68ILp>OD-{c(Br@I;;43 z)0N<%5Vez(U7a8iZSTQwM@6w&8K^;CY_2M9FJ+GZ(H@V;-aJuhsZB}fx_Upo5hw(w z#oGNSQ~2$Gy|n4ocdqY~6bmKD@4U(M9%di+bkVisRm@ci&pD$t?pVI2=>ca0A=Wtp zXXtdx3~c{)|!(7qu0nH zulIfaiOL7l{u#znR&OqxJY-nOyJL1tS|$~il3eWiEd__;lf#gSnoC6GlgmVv^gVlM zF^5P0{oboG-R2a5rVtMorsJ)*Es4X{K`e}YNp1ujxrbstU|KB}H2n{THofIr)q(GN zOX$J^_|_#BBqUum#YGZ5N%L=gQyw*Sdc$?MPxqH&%Rz(Jg2c_avv(hr{m9@ozv=F^ z5_{Rpd#y>{98Vwk2s{8=&y>A4x}9xi4yfF3i>IcbC0B|yy2{zuasH~>E{0I_?JNUjm|A<>IbX?)OgDR={xl_rk@EliPBI_({Lj3okDRD z<=ZF3|NmSjZADP18TX@iH*{fxrjjr1T<~;Jt9}7Z8|X9L8mYdl-lQ6yXqnS^j(!L`&5w zE(C;w8~ooV>6}Aoj8Kyc1Zm)lWZ55tkEAdaScn`j6>PYOkFY5=LPR}+m#Ih=#5b_1 zb~Z$9+!qd!7~=DZ`}06U0?`u&9+N^WfN|Vp5$|9MolOyOuwfo#4%r_rJRioZ;J#EL zlEH|G(C@B@e_-(z`yz6}< z3j6u#1OjEvNY^rArw6KNLZWk5uX z1ctelLV?5%3w3}INfc%mg$2o*@&ywrhr|oB+o6M$1_SFFAsxfS<*bpkP+-B&vAoxz zd=6d!`@fnG5Cqv?K*NS^x*##a5`gA|gp7*uvNZyWRXvfOzfZ5CYxJ?QFtVA3L>5@k!gM2T3 zu3CVXo(~&+3z0xzdg$uU%IJnPU0V(ho-YswwYEG^p<+%7cj(ORL^$Un`ryo{!h#*m zBZZN#ruh2;(JrdjSvn!u2vQ5KHx}cmj$=FhACn|=B>DyNNQ*Au1})>fTd3Gr>_a$o=3)MwdxB-@I7(;i7ZKlN*Z zh{yVo=$qU7C{?WYbUn0H@4vhEF=T+shOn+=%M2yo`>i%?=r-+ayoB??E*aA>E<`u-=y!p%LacT&#MN1`kdaeC|+bB(!Q^uP;7VmuJ}t6-F!vd zmp%J=OhS?=HexNk2u3yQ@3zw*+}EwY)5L!;q^xOrGiji-p~d7fWLp2xNc8RfLKk6e zsA@H&>rB?*>toM>+o*d%>fh^adKq@-XrbgnkKyN=bjLIDD-@l1xIwbS7~}=Up#5B$ zi`-tnIN1_&=C>DkM=FqOyB{_d+pCj7^cWA1+zE;N!Z~gXB4ey7-B?Ah_f<$>{ zOIdKrtuC8HQ5&}u5x>+EU}_5P6!>a+lnr5xbAo4pLCzl?Wu*^}7-^8~^)S^Rgd?sH z*9e*IH!HcG8T|_!LsUJhjG{8&&utR3g-1j`$EYbn$wzN~xXrQGI>orEWgsaye)||8 ztII?yDB>3O*<%ZD`OBWGtBw5iy6)FaH?nWkWo zkk25F&n>Th6^b=|uRd*d%%s%=i!rD5#RarjEKA!jP93`EvvWc`ZOrZG@6D3xzMUkqL=Lq))JFENSA4w&Y$f$~g7+`N z8iS)&?C(U5WX}&R8Z)-^)7;H;deyNg7K+Pm5QKPp;`yZr#wktD^@_{rG;=*qGM=CV z`(lWyWR>dy%Fl#S4=C5nL?4gvCjfxg9_ z{v_a}xQOZn5M&A$jNK%&My&Igs1{LuX3zyz$m+t57XNlblPDSmjgNQ1(7_-_ta24+3nQu#zPJ$r~8{xi$B9UlTF660f>h;8At2jcdp3vC$WzAlhnm6e;@YaHa z7yUhZAIGrI^)(__rO#KYx|A;-iX-qF3)S2R#$G8^VJaHeh!D`aVL#Coz1dtWj_@M6 z(mh8PZVv4Hzb~OLyVzQD^Ghxn92|wfe|K~kD}6~UK~UgFfUH=k@mo4zLMk7Z@ubZx%>o9rQBxP9O7L$=8!6Goc2&2sp`p@a zvT?4`$M#9HviAbK*TI{RI*3pvHYV&Tc)H>`?wzmv^edHn)KY28FvHe4y!z{6T-P10Qr0!Dke(>LC6KlTuP zyMGvMlOgyH{@}e3!2+jt=3OeX-$K$Icl8RuV$PcxEl3^_I|+5N?rh!F3EV!(lpLBBZ=?>}_O0}SVG<|!XB zp5{iY&rY`+jojJq2g(2RH=otexy(mjSZ2F!f;r*`Vn)i{FKzEzzOJ9;_^AnWdY)6c zJ?4*rr*6g-q<#3vBi@Dk)@Z*fx-?2TvJDD67I-39D9Z%G7v*WcBE1ToL&&T7MAz2R z9{L6Hc86D{r>2R6+~^k?1`>HP^Bej!0lgO9`g&e=TZ7q_cxw|Gx+T4NycLp*`5W3v zF|Yx+i-;@=$;92D`zrt~<*JGxdh~dhC^-Gw?AK|J7R`E&^@-VzDuVrs*>cvI>4t(D zwpkS_+moaHpSOA6*gEVx1lIq4HgKiG{}SY})*NkL$&!E;RWz2w_QL>*t*B%ld39um za(fFr7sD6oMe=?8)I@|Y5#0XcmxE4GgellUjcy6JnJTRHnbRRR>$qdI)Y(U0&e=Z< z{}!2MQ;d(YoGf4?cp2c%LgRcDjPoazpu_1Ew^Tt4UX!U`+_8aQ$EfpwA4LQd0Vxl@ zlY?^KnAwOw!r&p0r(4@ejd6k)Q)Wvf7NtL>FLerZ)6?$$!$)kg1B3V8m=AX}_5n-- zq(8kicK(M%^WYvm8GtoC#udEz>E4cB?@v9C_A2>7_YIn0&}P>~_oHIqJ~NfJIrBlp zb*`oeBhl?#j_?{0!fBldqvQ2SN_QY-2DS}JjI;y`jrdW(z*26Ufpa$a@a=lQADnhx zY)4f~#>%XBLri=i3*WBPzHhZAX!YPC4qQ}p+wdPmr29WG!=m>mkX4-AgPVl$<~`|1 zrssmW{48q^NkL)b7=M4>aqjnT0wx=nDg;Ya=YoW0b#Os{|B5r|3(x)QtvK+C5Fm^w zmJck=6F3Cf_<9Tnc{Ee^2Q-(tB}!@Ip#MYg;3NoevE&97CC0x|tQu=8d6We=vDT6HG92RWqfQ)Rh_ioYj~Y_( z(73k9spdFVCzkby{x_9AbK92&Jlg#kR8+5^lO*yfE2h-0J|Va~You;#Nr@RVgK3Ru zA1i`vP`C9%UueSUM2&giXZ&J0FEW0UOz`kOes-4f}wy9#D7b4x4$5J z{7h&$PF7MqME*IEz(qM*S47-0C>STV?}nfHZ45kpb814ur_pLOt0&xExWpgvY^hV^tkpe-lOb8U7sLlXPKtrKr!wPyhGs{ z?pvKAo}e~P_HQHTQPIK;#H8S)ol=lCz(e|{iO&K9s`-z%6)}a? zRBD;+`c{Ox{@x4SEnzC>F5uJzMD4XW$_j&hjZ}XvA+5d)<4GlHYc5LSny5)Y1LG(K z-)NQ`hpBXxNpxg6)h@HTnZ^NRB}{HlawUw0HhvhHcdzI*HRf#hXI58V^tlH42plK@ zx}!mrgOxtd(es<|eh^!@&+GbfK2DY|BVoe`ffm`FSeJ@%-A-6S-QbX`)^X!KCs6Ij zdz!nq@r~@~dD<#%{@W?-qQr)_?^dU-Jt}z89WoEy{pI(-V#oI#-y?O0X_f)@lVYzz z1RJ!V$_Z_9Qq3M*vCU&w;T5dC(*z_@w?KRGLG%wYsDHSPL#=ne*zxZa>H*$>x%sfQ zZnLt*(IqZ1`tA~E(!qHhPMm}n_T|4LWg6|G?a*$!6Sghe;~2H)v{F1-aR7s1z6h8N z98(D_5@xJjmeK6nQxuhCX@X1Xbzw;i?I;F@$CoV-XjY(0? z&#(^VI}2V3>Fm|ioS@t27j;%wYgY3Y>Q`?fSk%OR36 zxjWWjxjSf#6X+=}ksFb+R+f%*tn19&`>(whbF}t7TQtFDR=v7ka-%2vey7b(^jR0S zXwnDoVE>C4`R<1}Q%ONj5q-GyS+YC_iczVW9`K%3OVwl|;VQBFSJTV{y-R2}SHL;b zRAzw&$yLR>#R;WJ`X6Iz8Sg&yWex3wB&cE7N50dT7csG-nk~byPqW~yC-v5zx52O% zco?0q0P$gfmkMSFk&6Hmhq0aSrY9_{>oDxUy_=udwZ3#ec9Rqgjyce6&*iZ~LqAqn zbWaYbYX}W%jMyX5&7Ui<9SxhyYarDn!+)>G`Uxdb+IBvfbctU#A=lk%7~Q^k&f1Cv z;Vva03C;~+KF=NgOd%^tNH=ZWffPM*hjfYAo=5)#j4nP$ywrTn+-YuQyQ8-Xm_yMX zKebqW@3EU}yGOEgvxL~v*gf&iMx=RLaR7=ws_fb2nYpy$($|)XEfs_0<df%!4j z%e|GLTZWKg@sLOshpbD3=f*@_^hmT;qipVXV}0TXc@lC0IYC^TW)4Wsp1ej;JBxQD z2<-UjlPmt0-oLVLwgzC%U8*Q#$$0EgUSuESd<%;$v^#GN&Dib-pDpM zQ9fPs{j2S3AR`sjWVKE-YZ5m2n>uL`r~`H?m}ILQlhQO3IiMpDEVGROHlh`-Mml@J zp@ty`pJzt@#u+wjS8DIG#|-=A|I74zpvy|0A>#}KU~*t{Y-Mja%WN@KTkCvo^2bBZ z>RY2HyRt~>hnqR;4oz)Ua>!kDPes=DB3v`L#ms!5?BnQS{O<}m^PM>h6s1gTDQ+;M zGVR*$E5Rh1e)WPaoM1lb3GcozcJqmFc51htI0n)6ck!(?6w!*66uY^+=wInM>=!EN zmZ#R`hib?9?@i*1%ak-|8&dM#4A<7o@_((ZX&y+Kg5tuJbJ~*5;!gQ>1>tEqI>air z3w=nk7RelNGF8Z8kuv+JnDF>rx)=x z4*622TwHB!EiWgy{*IPeORj9sT&8O)QNeR(VOYgoq)bM&`}7K1nzOWGOl3p&OT5s^ z_NUwThX&`e7i}&E!|J6r#;b%ysG4YpO1ne5zuGjE_m|(3W~NJd>P?ASvUhowft3;= zmD0jrhm?ATnHYQp;zM6~c>ftt&hX71SfPl&3-8(J$q)685FAS4ggUlCm-$6SC`VQ@{zLjc%0uP2tN8# z-E&>Q(JmRfrZibZ)JvL4nu@;1 zClz^bYLkIAz2LB{a^XRQPhR9~u=-wPG$^Lx>UAgG`u%(jpy!vmAlis)Aa0>*Ggg>lng!{94z4uRX z^9^q5*iGM-{dlv+6>cST7Kxyd=N7?Z74Q#B)^mt*e{M6Z5y z&T#$(C5^7h^z)p`B!nLvkTn9PiA_T+j6+bZi;Smn+5usDEBA;y(j&9wyH5DvVtNz6 zr|ZWn8cZ#!gFeGITLVW!V>PGf^@FmJn8fC%E%rZgxN*pe7P4I_FMT-uDC)yBa>>|Z z`BA}OhVSxi#aEY01*`jC*pGPoNwL3(M|Ykk@@7Owa&+HStAfc``mp)IsA^g|z!4-? zaScm&ip#`@$~2nsAKWBEeD8|~((2HDA0z%5t8ugG&8qxU6)F5DixqK#Qm*y!%e5EM zDreu}iYgC&00rf}P|n3vDTRx8Cum!ABL9EyI+X&m!~yht~K)Z)ag6rQRsl#Z@6@acRKxRO-Wr*lzH zEK(|@XedLpTf%CA!Ue&n5*9<|3NbNoX~CD#_p*`vUG#)3{>^)54ovZcb>RytVp7kb zk2{FfD7^8SRX-{Hc|lUUvhCTZiymM6I+c+(l{o98+j@v;Rj_Gi@EY#nl;UBUBb}fN zH^~5Wl;eyrU}TC87a_b58`efs`lPY6*W5g|Voc$%aX%@t$4e9$e`mG08! zpt~S=m;Sw+gn}C_uD3O^##AqN5_=(u8_8(Fur;P%JmD(>ZQ0h+n5v#3=tAV2L?`}Y=eachE z_bdWkr&F0rVB!{;@&ca*9k=X8+-qHdlFDLg`vA%b_Cm=e_rwXx0_29%Daobh$DyDS z))M(u#HduvqEbGCo#nJzWABylaavY0j2j)HuOS4yk;5#Jm*)^H!MUH~`Fndq+)h5Bt7HTw51P$8k%sAi*lFnBR1&^e|59Cm#@97U z%P#(;l-a%T^G-vx*P?cfs{t&taHDK)J4Zc`^GA`^wZ<){)H!=2e#ts&kN1Bs3YU!4 zQ8Zn51(sxPG?HesF~GTAk7?}|$k>vuNOWJuaRDog2d}-p;=e`tE|F#oCh7j?Z1qFo zjw5d60h`+X+k=!hd`bf0LUuk;V6#>31IaBvXAHu$8KVbZ<;SCjPMJ=)qS72+{%BE5 zbLWFAd5gwPtjRY^1E-U?$HbX2jc+OyzhwtDZh<@1gV|11`rk}l6E_Da`6`>VAu00j z@y&jGm{EZCmd(r=wv;x-Dd97N{YLnX)V8!vzcS~pq}OwMSdl6 zbkqsH-ag;_8HTEs&6K!a9>6$#coinMLMg$n3y^TNjhO(@id)j}SJ1k74CYbWD14mu zENSlkqTI;6-+04bU9Jx{6Kz+i@-e6*TiH2bI4Cxp7nblT+Cn11@$Va6-L$k}^Jt_m zIfjeIbE}cKL@)rIOHMcWLoqUh%K3GIACJ}`}ac|Ei@1aOa+^!g~U-#55x%dRl(U*{+%?ZnyH*9#cQ)eP%LVe_e#`^WElnueL zw*`lA8oMd(n3G{hTK3Ju_}zU-&;hNy%<676_Dn_Mzr5Qh%EC@JQ%D=vtE( zKR1Z>EVo#rKFHn35qTQ-XLBCnlF94Rd>5TI`neJKkn~8O3_LnzOtDAxK{KjjIePlo zC|0D){~*sFHyB}|`tFcCkV8EYd}ES0ecIK~* zfjG0QF2AW@W-_mCI_uO*+BM3FYRr=fi{1T$vr7>ZkK|d&1nQ0#H?J80?AV>@ZEmEZ zVb!r}-uUf<<-i)(Iuqt#RhUP*Ln-0wj)kcCK=k^lP4}xm3Ql3T^#piXad?;w^C2jx zDEu-={B(temN83t*wyU};t#uLecNY!^~SEO{BYjh?A|G3a-95G;*;bGwAKYUccm#5Q+Kp@LaQb+HO3qk&uzJTGa z;(-KTPYI5syR_Ww>VQgr+@GF>=OTSHk0H8W>ntfvSf}(avAL|i4ZHGR}kF2Wsv{0Cl}K9p%LOICQbuO; z$p34dO_qf-VU0o&Y6gaoRN=+dN0)pvw>ouc&rNF5*iyT@n|DWhg0f#I6-_&sNButx zHj?u6I#b6agSp`{ZR;x%CW$6zF0S-#-o&c0Wp$lrh3E?LMCuOUwUIkZD^-8A@<#lV z_s#HcX;ycsKV0?M5%L*oac=3bA8+WQ=cOs<(>qJX>s?c!WAExrhGz}FmvW2P& z*^gJB%%x%;G}GJ?O;*F142{=Qa=PQ~QI-r#ClHSL2Eaf1Ns*&z{Nc0xaJ;5Ctk9ou zjV}u8P3$!zLv@7oW($Hw!rlQok=Jc~H+b@Qz&9*x)TJ@&xzU9?e60owBc;e3- zBK|qi9qgb=bzF#b-}8xnm{H5x8_iz*_|fo;u9B7G^GBDOu%3$^1Ox74c_V6QPcmv- z(?}qEj0E_QV#>Eop>xy1b^F(!7H&vla{?`7rqy#NKj)@a=(l3|%Cz1tc8>C))Z6-g zqg{5_lm+85isXJ5ubEw~S263 z76KvE`Xe&?yY1tiRB!K7(UzxpunGyc4k|ZQWl5?k=*jBFpG4_ zY$dWZuJ_q~0s61A1tol_a)PK^Zs9Ky_4B>M76{6J%?$iNt*A;N%;VDuajC@l;)j>1 zJjyM`Rv)cO$IS@kvaT!U}hUlSedms zy7_b&q2cJ>trweTwPf#=SNwX;fm=JMa6rmPto^E2YR3(@#F6`FN}IB)U2#Xbq%lmi zbm^dEdg4*^|1JGN2L_PxkY759>?V+&Ki+*F^i3gUzy@ZsNZ(;CMTE;pPq02AqHQF0 zShtbP719H&SxNd1Nfq-&Dh&lW4JP#t9a#bEg%d)CoC9k_qJNG29yVpifczH*HhYKc z4Qrd);78U(e*yDJBY%WpB4v?5uqLiV9b|r3)6=*avI`6>X@yLQ0BbNJFLa*nC53}S zcn51Rg7qLhnjzyus(zs%K`ZQ#$6@_ue&NXdFs0Iw$j|>x;Mt6PEV2nKr0OK(T9{JP zROANOfHV^s2NoM!CGt0zRC_gY8!T*}CS*n!rmz*c3^t|Gfh_)?D};Z$_9cpdgr32N<*g1LuT- zlwjbqa8L)V@$h>T$P<=XreY8)@=H&mRu$;E5%75s`5mMRQ@BG$ zMEn<{yc3{LFwS$S%bEz~rSSaYiKGSu5t#r9Lj11K(4Z>6LAWr8`4Om)1O|Dn=P`v0 zQEYyOC?TN;0tK&u&?qF76?j;x_;~zQ>PX<=qIv%7HS3xJkwGdzC}`lB-alZ+_|^53 zU1+l`9ekcRFa!Y|K?;R%5D{hjEsCsIueoOetDVQMlQ2nJ;j$^+-lggM;>M{ZNsQWw zDH@IP*|o+7XuGnW&%bK>xTk-kr_e!*y1?*p zdEc(%$A)0&82p}Yt-qNYIAr{-Oe_mE#>dy5IAL06-(}eDa zDc`OQECCKb`$zDdUUIV6wdB2VxBt)PIs4oU+vkt|cF8nHz}-Knc96{ykVAj>3*9^W z|F5>L10JjI|Jyvzee6Q^mShz|T1FBgTUJs+W*SI6sWcP~aw8)d*%BpXOJ;V+&fY7s z`Ja1lU*GT3@9*{Mb-JJT`+Pp1v(LGQ&#maaEp_GdGV7Ywjzi8fZ&cPCHy+7FKc{|N z(Wy!8qZ97I_b;Kg6QTz*yq1)1SPxw{KIp3(o}vAV-myU3bY9Z2V6u;0Wx3PH|{{=JAr~zHmP1Qr6)^PrVO4-!7fIe16T-@rFRDjdJU!)D-vh zG#&DD3htwIhDCh4pAv^=GnQK4HMqqsr^yut4=vJc7OUm_x=yos^5gX%--vyOuGQ!D z^%Wl5G%a5H)?2v0RUx(h5bp-uicR$CT7jb=Ul4nlu`oO^bTjTE73QMN`Svs8o4ZE1r z!aubS-wacE{77Bsa#wJVY}feXqb!*YAH_HWgxx96b%@3*ZhI8eJW6C-kbDvTS%|Z( z+$dZrR+er4XO_jm3&pn|@HCi_Ejk6N*!BdSZsXc(HEoGyD_!B?T7rf?DGFifD!wW3yK?_vztB|1r|Ywis`}_OD2nrmGB&#^160~#`rg~Ui7|Pbph&>gs%dx!X6g>LGmhw$MmjmF0J7FAqqlKwsU6s%7u(K8L}#2`?Jl5A#X#KC^@4XjQo+ zOw+n#YE|g2PZ3Irm-G=)JDL;CEE1g3t+uwstpUgWaX_&d3ahxy!#Djd223cY1DfEpeQ;!G5@7$ z$mFcYT2fN`)R*;@wNm}>qN`QAlJ~B!G;3cqzbcVXQ6TPZ+Vj@U$SBRB<5Gkt70gm% zH57D5&?43KuyRkgq{+V1?pZNy`n!ZUh*zfTue`Bq4te5CB-4hMO0SgkPC@h{bdq?>S6gQ4 zvHwxlQ)vOBqedo+SEa2oIRxhdMee>oCI8cIC-3jc^a*YCt5X3}49gzJ4n?%+%Y7i~ z?Wq>mBDCQ(QWfi|T_zt;)2gw&kh=YzcET#HS-_?BK+G5S_zxk+skYgCY^<7&Xub0A zh9EJg$$4%HKh;4QuUpn1-V}MoZpBhE@55Aej+^U5o3N6rj9|>kdC3<-*}5zE1Lf+X zJh9RoyULAnFLlOAH+m!GxVj(Wu^dOiH0U87;6uSxiu zcyFC>>8A69LAmEg>cZzA$rZ*9>kJyW1{bL7aaP$StDFn3N}1DDK7LQf_!VB)SXehx zF3ada((zHvJ!RyF(0;?u;a^p4C)uhLG;UqfjHxOv_aF6@mHn4jSW53I*BKc*`6aO>Yq&2ZB%3_c zHI8-CT~XoL)68NhX*}G2@Xhj@-%&Gd`qzkYVw~C>$+bq+9E)!)zn89Mm1(P`F&VJG z7*l=UXvCiMP}hg5HN`~spj_hjgim+Ib$pE6-AbNp=w!Tb3jEY;bm95_%d!_6zs`)j zbrW>Je?Mv{pJZ?NzM{`Wp3kG&X#9old+Tt8ld+q0D{)Ef-)Rh8jCc~pjI8dCDHt=Z zR}l5#uw>JPuw*{ZWkL56dP0;!<@Fn^f$fBEhHz7sPBM#Wfd)N?Q%cf@B#B-~_j3Hs zcH>58Q&X<0^K*hel><(4PWKX{Y^Vv;uC&G#M*F`@8Tx;xQ%On^e6;uIxzR+q)?=)O z{_a$Jm6vd8yK0O~gA3GpG(r@NE$=+-RURP94NF?I81=L}CCk3=FuFFfcL#g8xfqvI zM$+%33-p&Gle$yW+39_trn!BV$uTWHYPCEIyojRAYMPGQdw+TnDtbPte@=Meh_TzO!ubTw6K%VT%8uAS*l^Hu zaFgL~ElWP@eaz{D8IQpu4dd(gFK^fy*&DYN9Cx!h7n$M|z~8J8l0s7gZ{uZotf_gM zIZjDC>-kWV{)hcGk+O%L=SSEVNHD+GH&JclCI)@IJ*$3|pWpc6!;l^cdzMmy!#Jm> zuj-jAL#M1%D;9t3{pdwU9&ozhn4U+P<%zfHOKl7;_A>s2zS}!HZnZz6iOpm_tE_l3 zV}Q2!_pxM?G?uwAbNjEy#V@i1pRJ9&67XoWBs3>R_URLT?BF}C<{ z3*~DDVxEkoNl*~O*C!?d89$8ou>`D^v&6g|xcs!ZzTQk{{KOmSJ}#E=ZooK0}bZf{u^<7KZIFF ziJnglRX#{(cww$g?S?Z?SA29sOMH+2*Q&viTCq1ootLK_!&F8c#6~y?{-s@?%XSBj z{l1bi7p$4&nsQ4|H#oc@+31i?2OmDrkr8eYqmin7?KBzN+j(?c3SE`2ia6?xc8JwUXpX(B8cm-{H%UtVyxNg^%iC%t<;!cw z^WmdmuZ6j~8wnlN?Zz%mk4&EOc9=#N%wN9kJeI4*OAMH7Wyq0QO1qvg@?#)a(}yFv z=#&Ik|Hdm3lM&Zl3^lbS>GAVfO(W_9qJnBJE!Agdzqa^IUSH4e;<6A}ks{-{`-$9^ zOk>BT&vtkHjhA*GfAuiCc_m6WKh1FSi_A}9e2kCbPMPnf(VIPE|!-ZCUkivHpou1ZMa8Xq+B;X|L(^4 z@x@nW+S;FT%~;=loV&Cd+%3es_0+CIXBHo~uiIUDe1>SS__$-;_Oo95I`ij4PK(i5 zt99enT3Q*`jDCI6lnmOiPfA@_63>79%*S%krsaD2w!V?!o5LCPo(|FFBerv7g6#&L zcRnVV@gziqdsH3J3F0hguT*;C`RI|~+M3WzI%RI~jO|6c@L`$3n7xd_>{c7LyAGRr zy$Cp*`Y}Pqo%q83K!VcJuJ&KzjFToa4Yvs$uH;H}B6rt?MRbWXz za(soe@|XWmV8Mx=dTG(bvBSDc>7~aCl$?0qL}-dBcsRvLyJVJHueq#_L*Yz#DGRa- zZw)GQ!cRq9e`fXgD^2DNeZ&3L;pYrlkEI`ZvBaDI!e3ky+^+7gt7u*vrByKOQZS@0 z2~pDyW;Co6zFNj4bdu`MYyC$Tc1E9Zv}Dt9H-Gh9{o{(jdWC2~%}^sws;m4^Wbx3H zoI)h)txehWFV^|(_TQd-_Z;7==WWHw^_7Z?W8e|zIwL*$e`)`g_l+KHBU{mRFxX@R@#Llp9@U+ zuCHI&S+<|QalhQ)@eALm231$+*G;A^6Bn6e*QL&#&!gGn-q#`2FSlRo9Ie#T{EK73 zM%_`jhEhvphXTfg9lMtqEi&$uo?45`_{_37Hk+a06>6Nj@SS)r*K=_-*vR9FRF16Y zBIENxC!GuJ5dwkcva;oFbz#IuwY-W)hY8#DPRc*CfWBa_TQ|w}iQ4eiw!9CSW(*C12b{5f&NX`p<3O=Ya9rw6o$HBxhz zSf$L=;$1b((z*H##EJ~q!-cZ*1l$rTH+Bc>KD9gHZ5=%|Uj0q@yG5_;DY{(}23*g5 zQYTXjnzQ%{HAij91}?_uDbZxK<$|c zUtFO0fQVzobMXOUxZFUPE4B7TF{ORZQI~C;CdxC)ve@clSw&|LrtM%Xe#clM;d{$o zh&@qF-9=4Q24BW^`_r^Wb0InNroH;=`u+JFp-(-56&t+jzdR-*9;>~HK1`=Xp7C2` zWXVtkjv7+%xqEHIy!&X~Y~;N0javo9g>T$utLG`A>wNr%sr3quvh7gCs&Zh71AWfVbj31u zgQz1JXKLo`>Mtx2%btOs07E0)qP*nkwL|kZ)gO3rZbcjDG;*!<9bPNn%BuRs;uIp zR_^8ntR^O0iBNvlY;F-n8~w`V^vKO3Pv?)#=3_brrY>dq#1K%wUGz;;-;&(iwW2M0dcQKSaH{k=wJ0teI-GSO@{CiKYsZ71E>B~#m9*e$`zeq1 zi~5?)D*3R47UlavUf;6vW$mwymNT|3nFECk#hXzY|9;E4;^ZR7tWM?mjaXP79j z?ow6z#T?h4n;FF8jaO!T7WNvMK-Sk22+y+nKSXM&>i>vxSuFZ8Wgpr_`R>}YTlDs6 zAD`Bq`QBUR#pL)?ZGc?vtS-li7&V#bO0E5TuLnPbRatU4%}QmO?Dh(^EE{{3AR7@U z^H!#tCSz#7mJt2&;PRj~L6Dw$kXkE%*UWt9`iS3ijf)c(IEew(4}-T!NZ*L)i`O9c zI6-St%VMeOZWr&*X&MzB*EN?E_o355IVD?I>ze58UZ~z()u>KwW{<7L;M@4J`Zefu z&Vje@Z!BBJZTsn*2RaUH+HB`={eZ($a>v^DMi*ER6Bwsa|_nXt-mk z@c4Nd?>w?M>wHdkRcsguLnbGKdFmK@kzah`maL4I>lR_>#K@BET?Hm^Of zPkQNoRhn`aGqEfysZoWf5eo15*x9S}@n$Yfotmlb%nwEGrH^gBp2{=J+fF#uDzXM2 z8`XQ>*J1fXltnnFq<48`v6DXBzE(h7yMN=M#8qs}WKT;>1pp+NDc9HV?FDHlbmkw0VOVsk% zo)$bkQNn=F-J#q`Vd3WQlF`p;U3cLL&;9S#wpQ9zQsh6bRKis@d&;E9jVY^&4?;{? zHn*&#?rbKK4-`dNr+>flgRCb@{XCgag>B3&gGXl->p-t5E+&QHKf(lhV2W^B6t6AnWi@C zgVN`n66dMIBCIak*Xno7B~L_bKYQ^5WyJFN-id03^YnS`L#a@{vkDZk{lLQ~PKVl0 z%Y}80J%jI6^x9Sp&zCs7x;%-+Mkjr`f{k;9 zvPtjBUwzy#N%?R%=D7PYyWPAOYq*ZO3`%*L)ie8)$L;*gzo$>J_9Z|2cNfdJ1e*C~wDM%zu^vCJx31Uy zua8fKx3gZ-d^Q!4=QVDdAfO9(vSsnl=uSo0D;`_eV{@6ab|zq`Fa5zjc4DM|@9@L^ zOTA3q**OK{OkriyD#x$#y=JhYCu`VyVp>^!xqPIHQe-|VcD}&FXOsEUFw=Ll#A{9Z z+Pj+<924W&#x~@dm)XW{J0>ba3qR$WouP#Wxn{v5+v5bnd7G#kO)ra2h8)lC;Ra@IDA2Gf`B)Q1U6u?=bH%CmuI1}``$w3h}jRvPSKZJXXUTuvX#kHdM zfTg-P5%jidOdod@3zG0&Hu+aGEg6{(BWx=M;zJ_=)8WJ=aGUq)6s{Z1e)9}YmI4iv zU^-}#(6${!R0wvL=EkVj%OHyO+*w>7dYjhbgFA_OBYquMhu)p7_~HE6kz26qVK@;~ z5*LYs(Ent{;O?O0eQ`JiRN|J1vq2^G$v9bB)TH#Cut6j;gLbGD9e3yp2oI;OL)+lh z&p3RJ!8;rS7M+1*^pfiu4Tu%ZfLup%{lnwTNz2C3poMt<8E1)cpPJ~_wgB!f1~jfT z%Duh;apl+);Cj(&I#Px+McoK5$3>vI73*-k==iB8-pRKu|WoEWOyV+?13LbVgP7!>lD$JwEhmftuWD*3sN zQ$fw~QR1=7L?3GW5N6lAnkr)h1lCrfL@!BE_cy5s46rsEp6N{{0gsikZ3zFG2DEDs zL-3P#ScL%AwwxsfJQHdI&xSWft=e+nJy1zA-yeyDARhBWK^%|y8Z3d|j&hRs;BC=d z^zwM@0zFd&zkvFhsEU7wme5iQZ-R2NweeTcT#|OaTkB|c67(Mz3=pF>S9f5lg$D!x|Yl~5Jr z-|&N|WTXzS%Z=XRPT(ofd*=O{cte!)gaUHn01&*!3C$psDK01-)fXiKaiE@ml!ksF z9~8(5wu0`kkn<>#o_+xxK+@$>-=0w7v<4Ece2KXQ?2!jle zlqDR}MN->vOr9PNj3xVrzJ$yXvBgX1G?M1Ogxru+Dgv@b(x3>)7D;FSJfDn&&LYn_ zk(gR23Nl8X&qP7?NLm#IT|m-((U1$0CPYKdNV@G6yzLg$h6W-O+EG8W@$#zAKgc}g7S7jr!1fIMG|$MSc@ zW93s!!0d!2K&A*jmw@R#@dneA_$Q@E#Pm2MLM8~WC=v6EFA4M8Hwn|%nuO_*Nyg-X z$(X*;WUL-ereJzgQZT!ORLBw0cQqBO*Va_bKczHG&$Bd)_v=q;l#c1mOviA12BzOW z1Jl!xf$5Qbi|Gk|i#`8(i}Ca_u{0$U^Mm>wR!@%au<}&AgDeq$M6)p7tt`xbe->7M zy4hGc-e+U=&ifuZhw%O1WBBxY3^)A%*&*`04_Lhk=0L8<^Rpbx-tQcYfBGYafBlHb zcjaRJDliw5|H{SsiR~vWt^0)W_I}3N`_*Tx+)y5tUdhAy*I*vz--&$41F>72kLeRD zz@Ebk(C5%X=n4XR6=Lr6{YiC-F#5Y9%p6-WR;(Mv*mGYoR=w&akROu2yaY3=P>QAT zrI>pxUof|>e}T@T9|u5U?ZcyApmXRa2mTFo4qKK%CVWWnbJ8GNWLrORel2iA8DzkZ zkjO)LVMh=qi3|j7Igp2`~rKfKXa{ zN%(Kz%&(9tsuY@D8cYI&0igI0327h-QOXO~e}$Of{wOL|*y0^T;72rH-PV1;3oNOc z;CFyXGmX9ePp0&8h!2^L>dGN*io*CUgc0=-L8K}G5?P8Nk4mZ7;F}c?@(WjR5Q4Op zZ6OS>PYr~Grh+FBWd9Eg+4X~p37)L{DYCG)q<&TX}u2yDR@Vi~g3S?xGBsNADwlYC* zS{3GPaTVe%6MV7;;)6Gk2Vj`H8l=uFTS6RsrW)FTAlFfZZ404;OR6Cjw9;2Q1^R|S zbFP4jmnJb>DS`0CVV)Xj8`|=eHSz_FpqG>j{_W!$tX~7EAeMq^fDa~zk(|8nng%s9 z+))D|>n1#dAR($4viloY_JGj(8xYbT-J*-Yh2OAR{DvS|$F>kActJ$rBc12DsyFEQs<5THNsAAlOJM?UbQSC5&ust0Hb_-4gF zt^<@Bj;P1-zC}=z*Z-o28X#(Tx*pnwdYCrO@zj`}jO+y;8JP%)hdyy6d64}!Y}Npj zvAp{i0CC(H;8zWpBk2gr^_c{vgJ&8bG%v0Zpu>-Lwz9w=#2g*m`GcBmtFGG+tv@?SC}7LqjQKCs4AA1~f6?@5YDV}ts2=`AFcpbR zEl)oOAF}E?2EJuNVsvB;%>&o3f$FRP+E9LYxc|qSpyylz|48`-v@mnapN`7(9omjo zk1$Kr9Y65ZrRU%L;DHzOHYn!w*9=8G2QYEdgh1)H}*VyNmNTAY*?XvBS>;G_<$ zn{V-jP^#6AkUP`iK8-Xu!W`vY!_*K8O^^jk==l^~LoQQ0)bpN|r?R@oO0M&<_atjaJz92WTZj ze@qC%2Z|%YN<^4>Z%eox=4$^_fB(h{1a(59`C>fAFG!$He=-Ei36O{i%TVT1}`ib*9)q+uly0H8zT_8W96BBxOLA%lXN5qaBc7aYA0!ATeC!-(4 zs7D8AIN-G|Y-HiPfsz9Y7^2w?i6Cv}iU?KKFkwnJ*1F#i;S)UU_Y?F!d=In}HOD|_ zo&TQkn==6=m6|&CYycA|rby`1k0$sfDnl_DI<|+j@Hb-G6rAd6mXNyJi2+ zG!$?O$+sJ>H>ah8&8q&4!i<2{SRUYsF_<)!NGh-F9Ksg}Jx9w4clTjUHPHtOujKd- zzzQGihma_+uvI?*%w7HgSdd?b$M!bO^vpIyP~3-9WMsQZ40zs0=zQ>IKehyM4*(r1 z54VK0@acg+N+McRsBoZ1a)C&!q#J`HPvNJ-V1KM12})HofO*q{Xo?TrLUzC#&jEa# zo`7v~7jEOXtAj$rUQN)NBCm!!y(`ysJA2}&3cOor-ra@iXR3-k6c8k09z0L*&JQcuxr!- zN;iR0RT3v&<{?yl)YTom6b0R&Xa-=q)FfeP7Q*Bs;1mz6nvDPh0i{STc{pVR+xZkC z!p$L=c?@(C+$e;+$b|Vuflz-G6FQDU$U7VO5hARfz=SQM5Ep9MB)s$8DSk3CdUf!w zhs5&QEJ8(JUz{8RS>ssXhA~J24j+Tq(X8akea&;g;bE}BC!Npwc@Qc#>;3zu34hnB z_)bjW>2Ykr^BD(L+@uhpD4Zcl#|+nvV;#5)L2k-oNRbR33w$aOLyk-UgeZq0g?s53 zw)U$r2$H6WA(Kbxm{0_DyfOX2;|6fNat2?wB0VuIoPY%;A>{j(u=OO!&uoS~i^K7g zn2UvoaNG(Jioq^Z5F^Ywh3(OIP66cP=`93Z!d@W4aXU=dHHFPwn}|@x8*|Lv3ls*~ zVxx}De-C^d00zuKFcpxlQ`t9RziIFu3piFi4f2QHg@4WhADCvaV~WHK5DwkPgzhsC zKdR5{Moy9hI2w6^MUu2}69TvLQ^TDzSYMh!l<*~D$mut99Pl)OfPAkIwwMKoZU%zL z!D+K#TaBE5%gv?kZ-Bln0cIi6z1Yo6go?fj6Q2WFo3pXvzM{k7Vcu*y0$iDjHQ-YO zR{69A6X2h75b{PGUP2H!??1?~UszpR{Q`(&!+(&pUw`_f%-WLIHt^}gDyhFG#>Y+n z;deCB;b6Xb%mvALpl)UCKQQ>q60D1NN~wqGgFhB22U9-jJZmxeAO6t%pWP|?rzfCB z4ui2w%BP@(8x|oB_=zG8oF(XR^spWcjt<7f{%QJu|19P2EzM~hX--!7^8)60zzRs(+xV2XG6`?>flWjm(-8#W zh4(LFE3V}t5XKzCgfABVY(+Fm&WC&l)i4kGGU;OJqlZwj#gako;OHJOf1CirP@H7y zi7`M}A~4@c91U!}gq7BL37F!v#7u#E7Hs}9Dv$F=4&h6{oHU7&eP=Oh`WYPSzl+G$ zMGPR5j(sP4j1TT*(8clkGO!ouiwHU34IdmYobl%<+=C#!H?|OVc=yVml7oOj@q0o4 zGX#eT((^>-?JYhV>=W^4i5$7qmw-(CJzz~E-37_L#Q0q+==2@B3T#?LW3rk^+%}j9 zw(v+Zn<0opEIhjj3BV3?dh}Pgxiry>?2bAfQW=%R11s+>T7@Ls7C%?Ylvkh_cL89)@<{f}q|dH_VMaFGLGa}bUpCkVn81pc!w?13I$BQWm==8pfWR;~wp7(5(&x#5N zcQ7DA0T{hv`={lK5X6aT3qg;60@OfQ%#I09QxmZ5+r>2D2mD}Itb*eb>2{2RbBoHf zWpfl!@=yRnECun5TMeyC1CTx;40%LDKzBnKh;VWjCY+)nU|mSofYq=VOo_XJP0}uO zTyl%bx@Ge^El^@Bham^$@f=$=#}MR;!WM!JGPE=Ga!tRE2c3xp_+f+*6lJ|aR3YedKa zgUFavaJ?m{i+|o6azFqkx^2NCaN28ZTJb}WBNw+2Mz|WB9T1i62-0#5LzoBzIkXsM z0&d%Kz+5H@cAQ{=-};I3i@C8yWr2eTe};v4m&IM=Sd|WDWYWn#?*5ihD!7wCKwpcm z6M)h7;Qt`th7?;n5TDHG0W26w3KQTcdIH*uix5~O>~ENcfxwA6|L=|J-&6fq#D6k@ zJ62}cg#nw9uQ33fc?B5ERF9{IKQIt@P<1nO2Q+Sj(V6%^C$zWVr3TUxfX@I+mxF$Q z>@tuNNHYR;*Q@^nuT|n9_y!|p?GXZhto;vM&qzSuMT{XxbOVO)GZC=u<@cS!DS6<% zkt2p@4S6{gi}l0?3WUIfnE*0vu#y1Tfu` zHjO3~%9TQ2(xFAY7Vr7`EzsWq{t1)V$>N6HnF)JPjXk!(n=YVp6akM!NLcYas76+} zg_*#Ias^cFY#RYL1e~`?JvSEn!xd*C2qXUMv4Enx$-*uy1Vz*vxlylghrxto=J|Kt V<2DG33+`nh2+%Z!fKxBo{{c6k^S%H8 delta 32091 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 Aod5s;