This commit is contained in:
Branislav Stojkovic
2025-03-14 14:06:14 +01:00
parent ccf5d20713
commit 5c745d2d45
5 changed files with 219 additions and 329 deletions
@@ -74,7 +74,7 @@ public class DrawingCache {
.extractComponentTypeFrom((Class<? extends IDIYComponent<?>>) x.getComponent().getClass());
if (type != null && type.getEnableCache()) {
renderAndCache(x.getComponent(), g2d, x.getState(), outlineMode, project, zoom, scaleFactor, x.getZOrder(), false);
renderAndCache(x.getComponent(), g2d, x.getState(), outlineMode, project, zoom, scaleFactor, x.getZOrder());
}
});
}
@@ -89,14 +89,10 @@ public class DrawingCache {
* @param outlineMode
* @param project
* @param zoom
* @param scaleFactor
* @param zOrder
* @param mirrored
*/
@SuppressWarnings("unchecked")
public void draw(IDIYComponent<?> component, G2DWrapper g2d, ComponentState componentState,
boolean outlineMode, Project project, double zoom, double scaleFactor, int zOrder, Rectangle2D visibleRect,
boolean mirrored) {
boolean outlineMode, Project project, double zoom, double scaleFactor, int zOrder, Rectangle2D visibleRect) {
ComponentType type = ComponentProcessor.getInstance()
.extractComponentTypeFrom((Class<? extends IDIYComponent<?>>) component.getClass());
@@ -104,7 +100,7 @@ public class DrawingCache {
// if we need to apply caching
Point2D firstPoint = component.getControlPoint(0);
CacheValue value = renderAndCache(component, g2d, componentState, outlineMode, project, zoom, scaleFactor, zOrder, mirrored);
CacheValue value = renderAndCache(component, g2d, componentState, outlineMode, project, zoom, scaleFactor, zOrder);
if (value == null) {
return;
@@ -184,7 +180,7 @@ public class DrawingCache {
}
private CacheValue renderAndCache(IDIYComponent<?> component, G2DWrapper g2d, ComponentState componentState,
boolean outlineMode, Project project, double zoom, double scaleFactor, int zOrder, boolean mirrored) {
boolean outlineMode, Project project, double zoom, double scaleFactor, int zOrder) {
// if we need to apply caching
Point2D firstPoint = component.getControlPoint(0);
@@ -200,7 +196,7 @@ public class DrawingCache {
// only honor the cache if the component hasn't changed in the meantime
if (value == null || !value.getComponent().equalsTo(component)
|| value.getState() != componentState || value.getZoom() != zoom || value.getOutlineMode() != outlineMode
|| value.getScaleFactor() != scaleFactor || value.isMirrored() != mirrored) {
|| value.getScaleFactor() != scaleFactor) {
// figure out size and placement of buffer image
Rectangle2D rect = component.getCachingBounds();
int width = (int)Math.round(rect.getWidth() * zoom);
@@ -274,7 +270,7 @@ public class DrawingCache {
// add to the cache
value = new CacheValue(component, image, wrapper.getCurrentArea(), wrapper.getContinuityPositiveAreas(),
wrapper.getContinuityNegativeAreas(), componentState, outlineMode, zoom, scaleFactor, dx, dy, rect, mirrored);
wrapper.getContinuityNegativeAreas(), componentState, outlineMode, zoom, scaleFactor, dx, dy, rect);
imageCache.put(component, new SoftReference<DrawingCache.CacheValue>(value));
}
@@ -291,7 +287,6 @@ public class DrawingCache {
boolean outlineMode;
double zoom;
double scaleFactor;
boolean mirrored;
int dx;
int dy;
Rectangle2D cacheBounds;
@@ -299,7 +294,7 @@ public class DrawingCache {
public CacheValue(IDIYComponent<?> component, BufferedImage image, Area currentArea,
Map<String, Area> continuityPositiveAreas, Map<String, Area> continuityNegativeAreas,
ComponentState state, boolean outlineMode, double zoom, double scaleFactor, int dx, int dy,
Rectangle2D cacheBounds, boolean mirrored) {
Rectangle2D cacheBounds) {
super();
this.cacheBounds = cacheBounds;
// take a copy of the component, so we can check if it changed in the meantime
@@ -314,7 +309,6 @@ public class DrawingCache {
this.state = state;
this.outlineMode = outlineMode;
this.zoom = zoom;
this.scaleFactor = scaleFactor;
this.dx = dx;
this.dy = dy;
}
@@ -355,10 +349,6 @@ public class DrawingCache {
return scaleFactor;
}
public boolean isMirrored() {
return mirrored;
}
public int getDx() {
return dx;
}
@@ -1,17 +1,17 @@
/*
*
*
* DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
*
*
* This file is part of DIYLC.
*
*
* DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU
* General Public License as published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
*
* DIYLC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
*
* You should have received a copy of the GNU General Public License along with DIYLC. If not, see
* <http://www.gnu.org/licenses/>.
*/
@@ -46,26 +46,12 @@ import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.log4j.Logger;
import org.checkerframework.checker.units.qual.A;
import org.diylc.appframework.miscutils.IConfigurationManager;
import org.diylc.appframework.simplemq.MessageDispatcher;
import org.diylc.common.DrawOption;
import org.diylc.common.EventType;
import org.diylc.common.GridType;
import org.diylc.common.IComponentFilter;
import org.diylc.common.IPlugInPort;
import org.diylc.common.ObjectCache;
import org.diylc.common.*;
import org.diylc.components.AbstractTransparentComponent;
import org.diylc.core.BoardUndersideDisplay;
import org.diylc.core.ComponentForRender;
import org.diylc.core.ComponentState;
import org.diylc.core.IBoard;
import org.diylc.core.IContinuity;
import org.diylc.core.IDIYComponent;
import org.diylc.core.ILayeredComponent;
import org.diylc.core.Project;
import org.diylc.core.Theme;
import org.diylc.core.VisibilityPolicy;
import org.diylc.core.*;
import org.diylc.core.measures.Size;
import org.diylc.core.measures.SizeUnit;
import org.diylc.netlist.ContinuityGraph;
@@ -75,12 +61,13 @@ import org.diylc.utils.Constants;
/**
* Utility that deals with painting {@link Project} on the {@link Graphics2D} and keeps areas taken
* by each drawn component.
*
*
* @author Branislav Stojkovic
*/
public class DrawingManager {
private static final Logger LOG = Logger.getLogger(DrawingManager.class);
public static final byte MIRROR_ALPHA = 64;
public static int CONTROL_POINT_SIZE = 7;
public static double EXTRA_SPACE = 0.25;
@@ -95,8 +82,6 @@ public class DrawingManager {
public static Color CONTROL_POINT_COLOR = Color.blue;
public static Color SELECTED_CONTROL_POINT_COLOR = Color.green;
private static final Byte MIRRORED_ALPHA = 64;
private Theme theme;
// Maps keyed by object reference.
@@ -132,7 +117,7 @@ public class DrawingManager {
private List<Area> proximityMarkers = null;
public DrawingManager(MessageDispatcher<EventType> messageDispatcher,
IConfigurationManager<?> configManager) {
IConfigurationManager<?> configManager) {
super();
this.messageDispatcher = messageDispatcher;
this.configManager = configManager;
@@ -150,16 +135,16 @@ public class DrawingManager {
lastDrawnStateMap = new HashMap<IDIYComponent<?>, ComponentState>();
String debugComponentAreasStr = System.getProperty(DEBUG_COMPONENT_AREAS);
debugComponentAreas =
debugComponentAreasStr != null && debugComponentAreasStr.equalsIgnoreCase("true");
debugComponentAreasStr != null && debugComponentAreasStr.equalsIgnoreCase("true");
String debugContinuityAreasStr = System.getProperty(DEBUG_CONTINUITY_AREAS);
debugContinuityAreas =
debugContinuityAreasStr != null && debugContinuityAreasStr.equalsIgnoreCase("true");
debugContinuityAreasStr != null && debugContinuityAreasStr.equalsIgnoreCase("true");
}
/**
* Paints the project onto the canvas and returns the list of components that failed to draw.
*
*
* @param g2d
* @param project
* @param drawOptions
@@ -172,18 +157,16 @@ public class DrawingManager {
* @param componentSlot
* @param dragInProgress
* @param externalZoom
* @param scaleFactor
* @param scaleFactor
* @param visibleRect
* @return
*/
@SuppressWarnings("unlikely-arg-type")
public List<IDIYComponent<?>> drawProject(Graphics2D g2d, Project project,
Set<DrawOption> drawOptions, IComponentFilter filter, Rectangle selectionRect,
Collection<IDIYComponent<?>> selectedComponents, Set<IDIYComponent<?>> lockedComponents,
Set<IDIYComponent<?>> groupedComponents, List<Point2D> controlPointSlot,
List<IDIYComponent<?>> componentSlot, boolean dragInProgress, Double externalZoom,
Double scaleFactor, Rectangle2D visibleRect) {
Set<DrawOption> drawOptions, IComponentFilter filter, Rectangle selectionRect,
Collection<IDIYComponent<?>> selectedComponents, Set<IDIYComponent<?>> lockedComponents,
Set<IDIYComponent<?>> groupedComponents, List<Point2D> controlPointSlot,
List<IDIYComponent<?>> componentSlot, boolean dragInProgress, Double externalZoom,
Double scaleFactor, Rectangle2D visibleRect) {
long totalStartTime = System.nanoTime();
failedComponents.clear();
if (project == null) {
@@ -202,7 +185,7 @@ public class DrawingManager {
G2DWrapper g2dWrapper = new G2DWrapper(g2d, zoom);
configureG2D(g2d, drawOptions);
configureRenderingHints(g2d, drawOptions);
// group components with boards that contain them
Map<IBoard, List<IDIYComponent<?>>> boardMap = project.getComponents().stream()
@@ -210,7 +193,7 @@ public class DrawingManager {
.map(IBoard.class::cast)
.filter(b -> b.getBoardUndersideDisplay() != BoardUndersideDisplay.NONE)
.collect(Collectors.toMap(x -> x, x -> new ArrayList<IDIYComponent<?>>()));
Map<IDIYComponent<?>, List<IBoard>> componentBoardMap = new HashMap<IDIYComponent<?>, List<IBoard>>();
Map<IDIYComponent<?>, Set<IBoard>> componentBoardMap = new HashMap<IDIYComponent<?>, Set<IBoard>>();
for (IBoard board : boardMap.keySet()) {
Rectangle2D boardRect = board.getBoardRectangle();
@@ -227,14 +210,14 @@ public class DrawingManager {
}
if (include) {
boardMap.get(board).add(c);
componentBoardMap.computeIfAbsent(c, key -> new ArrayList<IBoard>()).add(board);
componentBoardMap.computeIfAbsent(c, key -> new HashSet<IBoard>()).add(board);
}
}
}
// AffineTransform initialTx = g2d.getTransform();
Dimension canvasDimension =
getCanvasDimensions(project, zoom, drawOptions.contains(DrawOption.EXTRA_SPACE));
getCanvasDimensions(project, zoom, drawOptions.contains(DrawOption.EXTRA_SPACE));
g2dWrapper.setColor(theme.getBgColor());
g2dWrapper.fillRect(0, 0, canvasDimension.width, canvasDimension.height);
@@ -247,14 +230,14 @@ public class DrawingManager {
double extraSpace = getExtraSpace(project) * zoom;
drawGrid(project, g2d, zoom, extraSpace, canvasDimension, visibleRect, drawOptions,
extraSpaceRect, extraSpaceTx);
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.getWidth() / zoom, visibleRect.getHeight() / zoom);
}
// Composite mainComposite = g2d.getComposite();
@@ -267,7 +250,7 @@ public class DrawingManager {
Map<IDIYComponent<?>, ComponentState> componentStateMap = new HashMap<IDIYComponent<?>, ComponentState>();
List<ComponentForRender> componentForRenderList = new ArrayList<ComponentForRender>();
for (int i = 0; i < project.getComponents().size(); i++) {
IDIYComponent<?> component = project.getComponents().get(i);
IDIYComponent<?> component = project.getComponents().get(i);
ComponentState state = ComponentState.NORMAL;
if (drawOptions.contains(DrawOption.SELECTION) && selectedComponents.contains(component)) {
if (dragInProgress) {
@@ -291,12 +274,11 @@ public class DrawingManager {
for (int i = 0; i < project.getComponents().size(); i++) {
IDIYComponent<?> component = project.getComponents().get(i);
// Do not draw the component if it's filtered out.
if (filter != null && !filter.testComponent(component)) {
continue;
}
ComponentState state = componentStateMap.get(component);
// Do not track the area if component is not invalidated and was
// drawn in the same state.
@@ -317,26 +299,11 @@ public class DrawingManager {
long componentStart = System.nanoTime();
try {
AffineTransform txBefore = new AffineTransform(g2d.getTransform());
drawComponent(project, drawOptions, scaleFactor, visibleRect, zoom, g2dWrapper,
outlineMode, i, component, state, false);
g2dWrapper.setTransform(txBefore);
drawComponent(project, drawOptions, scaleFactor, visibleRect, component, g2dWrapper, state, zoom, i, outlineMode);
// find one or more boards that contain the component and mirror the component to all
List<IBoard> boards = componentBoardMap.get(component);
if (boards != null) {
for (IBoard board : boards) {
double boardMirrorSpacing = board.getUndersideOffset().convertToPixels();
drawMirroredComponent(project, drawOptions, scaleFactor, visibleRect, zoom,
g2dWrapper, outlineMode, i, state, boardMirrorSpacing, component, board);
}
}
// if the component is the board itself, mirror it
if (boardMap.keySet().contains(component)) {
IBoard board = (IBoard) component;
double boardMirrorSpacing = board.getUndersideOffset().convertToPixels();
drawMirroredComponent(project, drawOptions, scaleFactor, visibleRect, zoom,
g2dWrapper, outlineMode, i, state, boardMirrorSpacing, component, (IBoard)component);
if (g2dWrapper.isTrackingContinuityArea()) {
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);
@@ -365,6 +332,29 @@ public class DrawingManager {
componentAreaMap.put(component, area);
lastDrawnStateMap.put(component, state);
}
// Mirror components that belong to boards that need to be mirrored
if (componentBoardMap.containsKey(component)) {
@SuppressWarnings("unchecked")
ComponentType componentType = ComponentProcessor.getInstance()
.extractComponentTypeFrom((Class<? extends IDIYComponent<?>>) component.getClass());
if (componentType.getTransformer() != null) {
Set<IBoard> boards = componentBoardMap.get(component);
for (IBoard board : boards) {
drawMirroredComponent(project, board, component, componentType, g2dWrapper, state, outlineMode);
}
}
}
// if a component itself is a board that needs to be mirrored, do it
if (IBoard.class.isInstance(component) && componentBoardMap.values().stream()
.anyMatch(boards -> boards.contains(component))) {
ComponentType componentType = ComponentProcessor.getInstance()
.extractComponentTypeFrom((Class<? extends IDIYComponent<?>>) component.getClass());
if (componentType.getTransformer() != null) {
drawMirroredComponent(project, (IBoard) component, component, componentType, g2dWrapper, state, outlineMode);
}
}
}
}
@@ -378,17 +368,17 @@ public class DrawingManager {
continue;
VisibilityPolicy visibilityPolicy = component.getControlPointVisibilityPolicy(i);
if ((groupedComponents.contains(component)
&& (visibilityPolicy == VisibilityPolicy.ALWAYS
&& (visibilityPolicy == VisibilityPolicy.ALWAYS
|| (selectedComponents.contains(component)
&& visibilityPolicy == VisibilityPolicy.WHEN_SELECTED))
|| (!groupedComponents.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);
(int) (controlPoint.getY() - pointSize / 2), pointSize, pointSize);
}
}
}
@@ -397,7 +387,7 @@ 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.WHEN_SELECTED
|| component.getControlPointVisibilityPolicy(i) == VisibilityPolicy.ALWAYS)) {
Point2D controlPoint = component.getControlPoint(i);
@@ -405,11 +395,11 @@ public class DrawingManager {
g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR.darker());
g2dWrapper.fillOval((int) (controlPoint.getX() - pointSize / 2),
(int) (controlPoint.getY() - pointSize / 2), pointSize, pointSize);
(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);
(int) (controlPoint.getY() - CONTROL_POINT_SIZE / 2 + 1), CONTROL_POINT_SIZE - 2,
CONTROL_POINT_SIZE - 2);
}
}
}
@@ -423,7 +413,7 @@ public class DrawingManager {
try {
component.draw(g2dWrapper, ComponentState.NORMAL,
drawOptions.contains(DrawOption.OUTLINE_MODE), project, g2dWrapper);
drawOptions.contains(DrawOption.OUTLINE_MODE), project, g2dWrapper);
} catch (Exception e) {
LOG.error("Error drawing " + component.getName(), e);
@@ -439,12 +429,12 @@ public class DrawingManager {
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,
CONTROL_POINT_SIZE);
(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);
(int) (point.getY() - CONTROL_POINT_SIZE / 2 + 1), CONTROL_POINT_SIZE - 2,
CONTROL_POINT_SIZE - 2);
}
}
}
@@ -509,7 +499,7 @@ public class DrawingManager {
// shade extra space
if (drawOptions.contains(DrawOption.EXTRA_SPACE) && SHADE_EXTRA_SPACE && extraSpaceRect != null) {
Area extraSpaceArea = new Area(
new Rectangle2D.Double(0, 0, canvasDimension.getWidth(), canvasDimension.getHeight()));
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);
@@ -526,121 +516,84 @@ public class DrawingManager {
return failedComponents;
}
private void drawMirroredComponent(Project project, Set<DrawOption> drawOptions,
Double scaleFactor, Rectangle2D visibleRect, double zoom, G2DWrapper g2dWrapper,
boolean outlineMode, int i, ComponentState state, double boardMirrorSpacing,
IDIYComponent<?> componentToDraw, IBoard board) {
private static void drawMirroredComponent(Project project, IBoard board, IDIYComponent<?> component,
ComponentType componentType, G2DWrapper g2dWrapper, ComponentState state, boolean outlineMode) {
double offset = board.getUndersideOffset().convertToPixels();
Rectangle2D boardRectangle = board.getBoardRectangle();
AffineTransform mirrorTx = null;
switch (board.getBoardUndersideDisplay()) {
case ABOVE:
mirrorTx = new AffineTransform();
mirrorTx.translate(boardRectangle.getMinX(), boardRectangle.getMinY());
mirrorTx.scale(1, -1);
mirrorTx.translate(-boardRectangle.getMinX(), -boardRectangle.getMinY());
mirrorTx.translate(0, boardMirrorSpacing);
break;
case BELOW:
mirrorTx = new AffineTransform();
mirrorTx.translate(boardRectangle.getMinX(), boardRectangle.getMaxY());
mirrorTx.scale(1, -1);
mirrorTx.translate(-boardRectangle.getMinX(), -boardRectangle.getMaxY());
mirrorTx.translate(0, -boardMirrorSpacing);
break;
case LEFT:
mirrorTx = new AffineTransform();
mirrorTx.translate(boardRectangle.getMinX(), boardRectangle.getMinY());
mirrorTx.scale(-1, 1);
mirrorTx.translate(-boardRectangle.getMinX(), -boardRectangle.getMinY());
mirrorTx.translate(boardMirrorSpacing, 0);
break;
case RIGHT:
mirrorTx = new AffineTransform();
mirrorTx.translate(boardRectangle.getMaxX(), boardRectangle.getMinY());
mirrorTx.scale(-1, 1);
mirrorTx.translate(-boardRectangle.getMaxX(), -boardRectangle.getMinY());
mirrorTx.translate(-boardMirrorSpacing, 0);
break;
default:
LOG.warn("Unexpected board underside display: " + board.getBoardUndersideDisplay());
break;
}
AffineTransform txBefore = new AffineTransform(g2dWrapper.getTransform());
byte alphaBefore = 0;
if (AbstractTransparentComponent.class.isInstance(componentToDraw)) {
alphaBefore = ((AbstractTransparentComponent<?>)componentToDraw).getAlpha();
((AbstractTransparentComponent<?>)componentToDraw).setAlpha(MIRRORED_ALPHA);
}
try {
g2dWrapper.setMirrorTransform(mirrorTx);
g2dWrapper.transform(mirrorTx);
drawComponent(project, drawOptions, scaleFactor, visibleRect, zoom, g2dWrapper, outlineMode, i, componentToDraw, state, true);
// componentToDraw.draw(g2dWrapper, state, outlineMode, project, g2dWrapper);
} finally {
g2dWrapper.setTransform(txBefore);
g2dWrapper.setMirrorTransform(null);
if (AbstractTransparentComponent.class.isInstance(componentToDraw)) {
((AbstractTransparentComponent<?>)componentToDraw).setAlpha(alphaBefore);
IDIYComponent<?> clonedComponent = component.clone();
int direction = 0;
Point2D pivotPoint = new Point2D.Double();
switch (board.getBoardUndersideDisplay()) {
case ABOVE:
direction = IComponentTransformer.VERTICAL;
pivotPoint.setLocation(boardRectangle.getMinX(), boardRectangle.getMinY() - offset / 2);
break;
case BELOW:
direction = IComponentTransformer.VERTICAL;
pivotPoint.setLocation(boardRectangle.getMinX(), boardRectangle.getMaxY() + offset / 2);
break;
case LEFT:
direction = IComponentTransformer.HORIZONTAL;
pivotPoint.setLocation(boardRectangle.getMinX() - offset / 2, boardRectangle.getMinY());
break;
case RIGHT:
direction = IComponentTransformer.HORIZONTAL;
pivotPoint.setLocation(boardRectangle.getMaxX() + offset / 2, boardRectangle.getMinY());
break;
}
componentType.getTransformer().mirror(clonedComponent, pivotPoint, direction);
if (AbstractTransparentComponent.class.isInstance(clonedComponent)) {
AbstractTransparentComponent<?> transparentComponent = (AbstractTransparentComponent<?>) clonedComponent;
transparentComponent.setAlpha(MIRROR_ALPHA);
}
clonedComponent.draw(g2dWrapper, state, outlineMode, project, g2dWrapper);
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
private void drawComponent(Project project, Set<DrawOption> drawOptions, Double scaleFactor,
Rectangle2D visibleRect, double zoom, G2DWrapper g2dWrapper, boolean outlineMode, int i,
IDIYComponent<?> component, ComponentState state, boolean mirrored) {
AffineTransform txBefore = new AffineTransform(g2dWrapper.getTransform());
try {
if (drawOptions.contains(DrawOption.ENABLE_CACHING)) // go through the DrawingCache
DrawingCache.Instance.draw(component, g2dWrapper, state,
drawOptions.contains(DrawOption.OUTLINE_MODE), project, zoom, scaleFactor, i, visibleRect, mirrored);
else // go straight to the wrapper
component.draw(g2dWrapper, state, outlineMode, project, g2dWrapper);
if (g2dWrapper.isTrackingContinuityArea()) {
LOG.debug("Component " + component.getName() + " of type "
+ component.getClass().getName() + " did not stop tracking continuity area.");
}
} finally {
g2dWrapper.setTransform(txBefore);
}
private static void drawComponent(Project project, Set<DrawOption> drawOptions, Double scaleFactor, Rectangle2D visibleRect, IDIYComponent<?> component, G2DWrapper g2dWrapper, ComponentState state, double zoom, int i, boolean outlineMode) {
if (drawOptions.contains(DrawOption.ENABLE_CACHING)) // go through the DrawingCache
DrawingCache.Instance.draw(component, g2dWrapper, state,
drawOptions.contains(DrawOption.OUTLINE_MODE), project, zoom, scaleFactor, i, visibleRect);
else // go straight to the wrapper
component.draw(g2dWrapper, state, outlineMode, project, g2dWrapper);
}
private void configureG2D(Graphics2D g2d, Set<DrawOption> drawOptions) {
private void configureRenderingHints(Graphics2D g2d, Set<DrawOption> drawOptions) {
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);
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);
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);
RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,
RenderingHints.VALUE_COLOR_RENDER_QUALITY);
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);
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);
RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,
RenderingHints.VALUE_COLOR_RENDER_SPEED);
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);
RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
}
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
}
private double zoomCached = 0;
@@ -650,8 +603,8 @@ public class DrawingManager {
private BufferedImage cachedGridImage;
private void drawGrid(Project project, Graphics2D g2dIn, double zoom, double extraSpace,
Dimension canvasDimension, Rectangle2D visibleRect, Set<DrawOption> drawOptions,
Rectangle2D extraSpaceRect, AffineTransform extraSpaceTx) {
Dimension canvasDimension, Rectangle2D visibleRect, Set<DrawOption> drawOptions,
Rectangle2D extraSpaceRect, AffineTransform extraSpaceTx) {
GridType gridType = GridType.LINES;
@@ -659,10 +612,10 @@ public class DrawingManager {
// draw from cache
if (zoom != zoomCached || !canvasDimension.equals(canvasDimensionCached)
|| extraSpace != extraSpaceCached || gridType != gridTypeCached) {
|| extraSpace != extraSpaceCached || gridType != gridTypeCached) {
try {
cachedGridImage = new BufferedImage((int) canvasDimension.getWidth(),
(int) canvasDimension.getHeight(), BufferedImage.TYPE_INT_ARGB);
(int) canvasDimension.getHeight(), BufferedImage.TYPE_INT_ARGB);
// create graphics
Graphics2D g2d = cachedGridImage.createGraphics();
@@ -671,11 +624,11 @@ public class DrawingManager {
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));
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));
BasicStroke.JOIN_MITER, 10f, new float[] {1f, (float) zoomStep - 1}, 0f));
} else {
g2d.setStroke(ObjectCache.getInstance().fetchZoomableStroke(gridThickness));
}
@@ -692,9 +645,9 @@ public class DrawingManager {
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())
+ innerCanvasDimension.width; i += zoomStep * project.getDotSpacing())
for (double j = extraSpace + zoomStep * project.getDotSpacing(); j < extraSpace
+ innerCanvasDimension.height; j += zoomStep * project.getDotSpacing()) {
+ innerCanvasDimension.height; j += zoomStep * project.getDotSpacing()) {
g2d.fillOval((int) Math.round(i - 1), (int) Math.round(j - 1), 3, 3);
}
}
@@ -706,12 +659,12 @@ public class DrawingManager {
gridTypeCached = gridType;
}
}
if (cachedGridImage == null) {
LOG.warn("Cached grid image is null!");
return;
}
if (drawOptions.contains(DrawOption.GRID) && gridType != GridType.NONE) {
g2dIn.drawImage(cachedGridImage, 0, 0, null);
}
@@ -720,10 +673,10 @@ public class DrawingManager {
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));
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()));
innerCanvasDimension.getWidth(), innerCanvasDimension.getHeight()));
g2dIn.draw(extraSpaceRect);
extraSpaceTx.setTransform(g2dIn.getTransform());
@@ -731,7 +684,7 @@ public class DrawingManager {
g2dIn.transform(AffineTransform.getTranslateInstance(extraSpace, extraSpace));
if (visibleRect != null)
visibleRect.setRect(visibleRect.getX() - extraSpace, visibleRect.getY() - extraSpace,
visibleRect.getWidth(), visibleRect.getHeight());
visibleRect.getWidth(), visibleRect.getHeight());
}
}
@@ -740,9 +693,9 @@ public class DrawingManager {
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("; ", "{", "}"));
.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();
@@ -797,11 +750,11 @@ public class DrawingManager {
double height = project.getHeight().convertToPixels();
double targetExtraSpace = EXTRA_SPACE * Math.max(width, height);
return CalcUtils.roundToGrid(targetExtraSpace,
project.getGridSpacing().scale(project.getDotSpacing()));
project.getGridSpacing().scale(project.getDotSpacing()));
}
public Dimension getCanvasDimensions(Project project, Double zoomLevel,
boolean includeExtraSpace) {
boolean includeExtraSpace) {
double width = project.getWidth().convertToPixels();
double height = project.getHeight().convertToPixels();
@@ -838,7 +791,7 @@ public class DrawingManager {
currentContinuityAreas = continuityGraphCache.findAreasFor(p);
}
public List<ContinuityArea> getContinuityAreas() {
// Find all individual continuity areas for all components
List<ContinuityArea> preliminaryAreas = new ArrayList<ContinuityArea>();
@@ -849,17 +802,17 @@ public class DrawingManager {
if (a == null || a.getOutlineArea() == null)
continue;
IDIYComponent<?> component = entry.getKey();
int layerId;
if (component instanceof ILayeredComponent) {
layerId = ((ILayeredComponent)component).getLayerId();
} else {
layerId = 0;
}
Collection<Area> positiveAreas = a.getContinuityPositiveAreas();
if (positiveAreas != null) {
for (Area a1 : positiveAreas) {
@@ -867,7 +820,7 @@ public class DrawingManager {
checkBreakout.add(false);
}
}
Collection<Area> negativeAreas = a.getContinuityNegativeAreas();
if (negativeAreas != null) {
for (Area na : negativeAreas) {
@@ -892,9 +845,9 @@ public class DrawingManager {
areas.add(a);
} else {
areas.addAll(breakoutAreas.stream()
.map(area -> new ContinuityArea(a.getLayerId(), area))
.collect(Collectors.toList()));
}
.map(area -> new ContinuityArea(a.getLayerId(), area))
.collect(Collectors.toList()));
}
} else
areas.add(a);
}
@@ -914,7 +867,7 @@ public class DrawingManager {
}
z++;
}
List<ContinuityArea> areas = getContinuityAreas();
return NetlistBuilder.buildContinuityGraph(areas, connections);
@@ -923,9 +876,9 @@ public class DrawingManager {
public List<Area> getContinuityAreaProximity(float threshold) {
List<ContinuityArea> continuityAreas = getContinuityAreas();
Stroke s = ObjectCache.getInstance().fetchBasicStroke(threshold - 1); // value eyeballed for
// approx good results
// approx good results
List<Area> expanded = continuityAreas.parallelStream()
.map((a) -> new Area(s.createStrokedShape(a.getArea()))).collect(Collectors.toList());
.map((a) -> new Area(s.createStrokedShape(a.getArea()))).collect(Collectors.toList());
List<Area> intersections = new ArrayList<Area>();
for (int i = 0; i < expanded.size() - 1; i++) {
for (int j = i + 1; j < expanded.size(); j++) {
@@ -945,13 +898,13 @@ public class DrawingManager {
Rectangle2D bounds2d = a.getBounds2D();
if (bounds2d.getWidth() < minSize)
bounds2d = new Rectangle2D.Double(bounds2d.getCenterX() - minSize / 2, bounds2d.getY(),
minSize, bounds2d.getHeight());
minSize, bounds2d.getHeight());
if (bounds2d.getHeight() < minSize)
bounds2d = new Rectangle2D.Double(bounds2d.getX(), bounds2d.getCenterY() - minSize / 2,
bounds2d.getWidth(), minSize);
bounds2d.getWidth(), minSize);
shapes.add(new Area(new Ellipse2D.Double(bounds2d.getX(), bounds2d.getY(),
bounds2d.getWidth(), bounds2d.getHeight())));
bounds2d.getWidth(), bounds2d.getHeight())));
}
// AreaUtils.crunchAreas(shapes, null);
@@ -960,4 +913,4 @@ public class DrawingManager {
return shapes;
}
}
}
@@ -1,17 +1,17 @@
/*
*
*
* DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
*
*
* This file is part of DIYLC.
*
*
* DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU
* General Public License as published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
*
* DIYLC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
*
* You should have received a copy of the GNU General Public License along with DIYLC. If not, see
* <http://www.gnu.org/licenses/>.
*/
@@ -62,6 +62,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.diylc.common.ObjectCache;
import org.diylc.common.ZoomableStroke;
import org.diylc.core.IDrawingObserver;
@@ -69,24 +70,24 @@ import org.diylc.core.IDrawingObserver;
/**
* {@link Graphics2D} wrapper that keeps track of all drawing actions and creates an {@link Area}
* that corresponds to drawn objects. Before each component is drawn,
* {@link #startedDrawingComponent(int)} ()} should be called. After the component is drawn, area may be
* {@link #startedDrawingComponent()} should be called. After the component is drawn, area may be
* retrieved using {@link #finishedDrawingComponent()}. Graphics configuration (color, font, etc) is
* reset between each two components.
*
*
* @author Branislav Stojkovic
*/
class G2DWrapper extends Graphics2D implements IDrawingObserver {
public static int LINE_SENSITIVITY_MARGIN = 2;
public static int CURVE_SENSITIVITY = 6;
public static int CURVE_SENSITIVITY = 6;
private boolean drawingComponent = false;
private boolean trackingAllowed = true;
private boolean trackingContinuityAllowed = false;
private boolean trackingContinuityPositive = true;
private HashMap<String, Integer> trackingStacks = new HashMap<String, Integer>();
private int uniqueCounter = 0;
private Graphics2D canvasGraphics;
@@ -104,13 +105,11 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
private Shape lastShape;
private double zoom;
private int zOrder;
private AffineTransform mirrorTransform;
private int zOrder;
/**
* Creates a wrapper around specified {@link Graphics2D} object.
*
*
* @param canvasGraphics
*/
public G2DWrapper(Graphics2D canvasGraphics, double zoom) {
@@ -123,14 +122,14 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
continuityMarker = null;
currentTx = new AffineTransform();
}
public Graphics2D getCanvasGraphics() {
return canvasGraphics;
}
/**
* Clears out the current area and caches canvas settings.
*
*
* @param zOrder
*/
public void startedDrawingComponent(int zOrder) {
@@ -154,7 +153,7 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
/**
* Reverts {@link Graphics2D} settings and returns area drawn by component in the meantime.
*
*
* @return
*/
public ComponentArea finishedDrawingComponent() {
@@ -164,27 +163,27 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
canvasGraphics.setTransform(originalTx);
canvasGraphics.setComposite(originalComposite);
canvasGraphics.setFont(originalFont);
// Map<String, Integer> sorted = sortByComparator(trackingStacks, false);
return new ComponentArea(zOrder,currentArea, new ArrayList<Area>(continuityPositiveAreas.values()),
new ArrayList<Area>(continuityNegativeAreas.values()));
// Map<String, Integer> sorted = sortByComparator(trackingStacks, false);
return new ComponentArea(zOrder,currentArea, new ArrayList<Area>(continuityPositiveAreas.values()),
new ArrayList<Area>(continuityNegativeAreas.values()));
}
// start - used for caching
public Area getCurrentArea() {
return currentArea;
}
public Map<String, Area> getContinuityPositiveAreas() {
return continuityPositiveAreas;
}
public Map<String, Area> getContinuityNegativeAreas() {
return continuityNegativeAreas;
}
// end - used for caching
public void merge(Area currentArea, Map<String, Area> continuityPositiveAreas, Map<String, Area> continuityNegativeAreas) {
this.currentArea = currentArea;
this.continuityPositiveAreas = continuityPositiveAreas;
@@ -213,22 +212,18 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
}
@Override
public boolean isTrackingContinuityArea() {
public boolean isTrackingContinuityArea() {
return trackingContinuityAllowed;
}
}
@Override
public void setContinuityMarker(String marker) {
continuityMarker = marker;
}
public void setMirrorTransform(AffineTransform mirrorTransform) {
this.mirrorTransform = mirrorTransform;
}
continuityMarker = marker;
}
/**
* Appends shape interior to the current component area.
*
*
* @param s
*/
private void appendShape(Shape s) {
@@ -242,7 +237,7 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
area.transform(currentTx);
if (trackingAllowed)
currentArea.add(area);
currentArea.add(area);
Map<String, Area> toAdd;
if (trackingContinuityAllowed) {
@@ -255,18 +250,18 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
toAdd.put(marker, area);
// markStack();
} else {
Area current = toAdd.getOrDefault(marker, null);
if (current == null) {
Area current = toAdd.getOrDefault(marker, null);
if (current == null) {
toAdd.put(marker, area);
// markStack();
// markStack();
} else
current.add(area);
}
}
}
lastShape = s;
}
}
@SuppressWarnings("unused")
private void markStack() {
StringWriter sw = new StringWriter();
@@ -280,7 +275,7 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
/**
* Appends shape outline to the current component area.
*
*
* @param s
*/
private void appendShapeOutline(Shape s) {
@@ -350,73 +345,22 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
@Override
public void drawString(String str, int x, int y) {
this.drawString(str, (float)x, (float)y);
canvasGraphics.drawString(str, x, y);
if (drawingComponent && trackingAllowed) {
FontMetrics fontMetrics = canvasGraphics.getFontMetrics();
Rectangle2D rect = fontMetrics.getStringBounds(str, canvasGraphics);
Point2D point = new Point2D.Double(x, y);
// currentTx.transform(point, point);
Rectangle2D finalRec =
new Rectangle2D.Double(rect.getX() + point.getX(), rect.getY() + point.getY(), rect.getWidth(),
rect.getHeight());
appendShape(finalRec);
}
}
@Override
public void drawString(String str, float x, float y) {
if (this.mirrorTransform == null) {
canvasGraphics.drawString(str, x, y);
} else {
drawStringUnmirrored(str, x, y);
}
handleDrawString(str, x, y);
}
private void drawStringUnmirrored(String str, float x, float y) {
// Save the current transform (T), which includes the mirror.
AffineTransform originalTransform = new AffineTransform(getTransform());
// Compute the non-mirrored transform A by "canceling" the mirror:
// Since T = A ? M and M is self-inverse, we have A = T ? M.
AffineTransform nonMirroredTransform = new AffineTransform(originalTransform);
nonMirroredTransform.concatenate(mirrorTransform);
GlyphVector gv = getFont().createGlyphVector(this.getFontRenderContext(), str);
Rectangle2D visualBounds = gv.getVisualBounds();
// Use a temporary Graphics2D (with transform A) to obtain correct FontMetrics.
Graphics2D gTemp = (Graphics2D) canvasGraphics.create();
gTemp.setTransform(nonMirroredTransform);
FontMetrics fm = gTemp.getFontMetrics();
double textWidth = fm.stringWidth(str);
// Use ascent + descent as the bounding box height.
double textHeight = visualBounds.getHeight();//fm.getAscent() + fm.getDescent();
double ascent = fm.getAscent();
gTemp.dispose();
// 1. Compute the center of the text?s bounding box in the mirrored (T) space.
Point2D centerMirrored = new Point2D.Double(x + textWidth / 2.0,
y + textHeight / 2.0);
// 2. Convert that center to screen coordinates using the original transform T.
Point2D centerScreen = originalTransform.transform(centerMirrored, null);
// 3. Map the screen coordinate into the non-mirrored coordinate system (A).
Point2D centerNonMirrored;
try {
centerNonMirrored = nonMirroredTransform.createInverse().transform(centerScreen, null);
} catch (NoninvertibleTransformException e) {
e.printStackTrace();
centerNonMirrored = centerMirrored; // Fallback if inversion fails.
}
// 4. Compute the new top-left in A so that the bounding box (width x height)
// remains centered at centerNonMirrored.
double newTopLeftX = centerNonMirrored.getX() - textWidth / 2.0;
double newTopLeftY = centerNonMirrored.getY() - textHeight / 2.0;
// Adjust for the baseline (drawString uses the baseline for y)
float drawX = (float) newTopLeftX;
float drawY = (float) (newTopLeftY + ascent);
// 5. Set the transform to the non-mirrored transform (A) so that mirror is canceled.
canvasGraphics.setTransform(nonMirroredTransform);
canvasGraphics.drawString(str, drawX, drawY);
// 6. Restore the original transform.
setTransform(originalTransform);
}
private void handleDrawString(String str, float x, float y) {
canvasGraphics.drawString(str, x, y);
if (drawingComponent && trackingAllowed) {
FontMetrics fontMetrics = canvasGraphics.getFontMetrics();
Rectangle2D rect = fontMetrics.getStringBounds(str, canvasGraphics);
@@ -625,7 +569,7 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
canvasGraphics.drawArc(x, y, width, height, startAngle, arcAngle);
if (drawingComponent && (trackingAllowed || trackingContinuityAllowed)) {
appendShapeOutline(new Arc2D.Double(x, y, width, height, startAngle, arcAngle, Arc2D.OPEN));
}
}
}
@Override
@@ -655,14 +599,14 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
@Override
public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2,
ImageObserver observer) {
ImageObserver observer) {
// FIXME: map
return canvasGraphics.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, observer);
}
@Override
public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2,
Color bgcolor, ImageObserver observer) {
Color bgcolor, ImageObserver observer) {
// FIXME: map
return drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, bgcolor, observer);
}
@@ -813,12 +757,12 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
public void setXORMode(Color c1) {
canvasGraphics.setXORMode(c1);
}
@SuppressWarnings("unused")
private static Map<String, Integer> sortByComparator(Map<String, Integer> unsortMap,
final boolean order) {
final boolean order) {
List<Entry<String, Integer>> list =
new LinkedList<Entry<String, Integer>>(unsortMap.entrySet());
new LinkedList<Entry<String, Integer>>(unsortMap.entrySet());
// Sorting the list based on values
Collections.sort(list, new Comparator<Entry<String, Integer>>() {
@@ -840,4 +784,4 @@ class G2DWrapper extends Graphics2D implements IDrawingObserver {
return sortedMap;
}
}
}
@@ -43,7 +43,7 @@ public class CliffJackTransformer implements IComponentTransformer {
@Override
public boolean mirroringChangesCircuit() {
return true;
return false;
}
@Override
+3
View File
@@ -70,6 +70,7 @@ And
Angle
Angle Offset
Anti-Aliasing
Apply Model
Arrow Size
Author
Auto-Create Pads
@@ -81,6 +82,8 @@ Below
Board
Board Color
Board Width
Board1
Board2
Boards
Bobbin 1
Bobbin 2