~ubuntu-branches/ubuntu/intrepid/electric/intrepid

« back to all changes in this revision

Viewing changes to com/sun/electric/tool/user/redisplay/VectorDrawing.java

  • Committer: Bazaar Package Importer
  • Author(s): Onkar Shinde
  • Date: 2008-07-23 02:09:53 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20080723020953-1gmnv7q2wpsdbnop
Tags: 8.07-0ubuntu1
* New Upstream version. Please check changelog for details. (LP: #242720)
* debian/control
  - Add build dependencies *-jdk, cdbs and bsh.
  - Remove build dependency dpatch. We will be using CDBS simple patchsys.
  - Refreshed runtime dependencies to default-jre | java2-runtime and bsh.
  - Added home page field.
  - Standard version 3.8.0.
  - Modify Maintainer value to match the DebianMaintainerField
    specification.
  - Changed email address for original maintainer to indicate who has
    refreshed the packaging.
* debian/rules
  - Revamped to use cdbs.
  - Added get-orig-source target.
* debian/patches
  - 00list, 02_sensible-browser.dpatch, 01_errors-numbers.dpatch,
    03_manpage.dpatch - Deleted, not relevant anymore.
  - 01_fix_build_xml.patch - Patch to fix the build.xml.
* debian/ant.properties
  - File to set various compilation properties.
* debian/electric.1
  - Remove the entry that causes lintian warning.
* debian/electric.desktop
  - Change as suggested by desktop-file-validate.
* debian/electric.docs
  - Updated as per changes in file names.
* debian/electric.svg
  - Name changed from electric_icon.svg.
* debian/install
  - Added appropriate locations for jar file, desktop file and wrapper shell
    script.
* debian/README.source
  - Added to comply with standards version 3.8.0.
* debian/TODO.Debian
  - Name changed form TODO.
* debain/wrapper/electric
  - Wrapper shell script to launch the application.
* debian/manpages
  - Added for installation of manpage.
* debian/watch
  - Updated to match jar files instead of older tar.gz files.
* debian/dirs
  - Removed, not needed anymore.
* debian/{electric.doc-base, electric.examples, substvars}
  - Removed, not relevant anymore.
* debian/*.debhelper
  - Removed auto generated files. Not relevant anymore.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- tab-width: 4 -*-
 
2
 *
 
3
 * Electric(tm) VLSI Design System
 
4
 *
 
5
 * File: VectorDrawing.java
 
6
 *
 
7
 * Copyright (c) 2005 Sun Microsystems and Static Free Software
 
8
 *
 
9
 * Electric(tm) is free software; you can redistribute it and/or modify
 
10
 * it under the terms of the GNU General Public License as published by
 
11
 * the Free Software Foundation; either version 3 of the License, or
 
12
 * (at your option) any later version.
 
13
 *
 
14
 * Electric(tm) is distributed in the hope that it will be useful,
 
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
 * GNU General Public License for more details.
 
18
 *
 
19
 * You should have received a copy of the GNU General Public License
 
20
 * along with Electric(tm); see the file COPYING.  If not, write to
 
21
 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 
22
 * Boston, Mass 02111-1307, USA.
 
23
 */
 
24
package com.sun.electric.tool.user.redisplay;
 
25
 
 
26
import com.sun.electric.database.geometry.DBMath;
 
27
import com.sun.electric.database.geometry.EGraphics;
 
28
import com.sun.electric.database.geometry.GenMath;
 
29
import com.sun.electric.database.geometry.Orientation;
 
30
import com.sun.electric.database.geometry.Poly;
 
31
import com.sun.electric.database.geometry.GenMath.MutableDouble;
 
32
import com.sun.electric.database.hierarchy.Cell;
 
33
import com.sun.electric.database.hierarchy.Export;
 
34
import com.sun.electric.database.text.TextUtils;
 
35
import com.sun.electric.database.topology.NodeInst;
 
36
import com.sun.electric.database.variable.TextDescriptor;
 
37
import com.sun.electric.database.variable.VarContext;
 
38
import com.sun.electric.technology.Layer;
 
39
import com.sun.electric.technology.Technology;
 
40
import com.sun.electric.tool.Job;
 
41
import com.sun.electric.tool.user.User;
 
42
import com.sun.electric.tool.user.ui.TopLevel;
 
43
 
 
44
import java.awt.Color;
 
45
import java.awt.Dimension;
 
46
import java.awt.Point;
 
47
import java.awt.Rectangle;
 
48
import java.awt.geom.AffineTransform;
 
49
import java.awt.geom.Point2D;
 
50
import java.awt.geom.Rectangle2D;
 
51
import java.util.Arrays;
 
52
import java.util.HashMap;
 
53
import java.util.Iterator;
 
54
import java.util.List;
 
55
import java.util.Map;
 
56
import java.util.Set;
 
57
 
 
58
/**
 
59
 * Class to do rapid redraw by caching the vector coordinates of all objects.
 
60
 */
 
61
class VectorDrawing
 
62
{
 
63
        private static final boolean TAKE_STATS = false;
 
64
        private static final boolean DEBUGIMAGES = false;
 
65
        private static final int MAXGREEKSIZE = 25;
 
66
        private static final int SCALE_SH = 20;
 
67
 
 
68
        /** the rendering object */                                                             private PixelDrawing offscreen;
 
69
        /** the window scale */                                                                 private float scale;
 
70
        /** the window scale */                                                                 private float scale_;
 
71
        /** the window scale and pan factor */                                  private float factorX, factorY;
 
72
        private int factorX_, factorY_;
 
73
        private int scale_int;
 
74
        /** true if "peeking" and expanding to the bottom */    private boolean fullInstantiate;
 
75
        /** A List of NodeInsts to the cell being in-place edited. */private List<NodeInst> inPlaceNodePath;
 
76
        /** The current cell being in-place edited. */                  private Cell inPlaceCurrent;
 
77
        /** time that rendering started */                                              private long startTime;
 
78
        /** true if the user has been told of delays */                 private boolean takingLongTime;
 
79
        /** true to stop rendering */                                                   private boolean stopRendering;
 
80
        /** the half-sizes of the window (in pixels) */                 private int szHalfWidth, szHalfHeight;
 
81
        /** the screen clipping */                                                              private int screenLX, screenHX, screenLY, screenHY;
 
82
        /** statistics */                                                                               private int boxCount, tinyBoxCount, lineBoxCount, lineCount, polygonCount;
 
83
        /** statistics */                                                                               private int crossCount, textCount, circleCount, arcCount;
 
84
        /** statistics */                                                                               private int subCellCount, tinySubCellCount;
 
85
        /** the threshold of object sizes */                                    private float maxObjectSize;
 
86
        /** the threshold of text sizes */                                              private float maxTextSize;
 
87
        /** the maximum cell size above which no greeking */    private float maxCellSize;
 
88
 
 
89
        /** temporary objects (saves allocation) */                             private Point tempPt1 = new Point(), tempPt2 = new Point();
 
90
        /** temporary objects (saves allocation) */                             private Point tempPt3 = new Point();
 
91
        /** temporary object (saves allocation) */                              private Rectangle tempRect = new Rectangle();
 
92
        /** the color of text */                                                                private Color textColor;
 
93
 
 
94
        /** the object that draws the rendered screen */                private static VectorDrawing topVD;
 
95
        /** location for debugging icon displays */                             private static int debugXP, debugYP;
 
96
 
 
97
        private static EGraphics textGraphics = new EGraphics(false, false, null, 0, 0,0,0, 1.0,true,
 
98
                        new int[] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0});
 
99
        private static EGraphics instanceGraphics = new EGraphics(false, false, null, 0, 0,0,0, 1.0,true,
 
100
                        new int[] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0});
 
101
        private static EGraphics portGraphics = new EGraphics(false, false, null, 0, 255,0,0, 1.0,true,
 
102
                new int[] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0});
 
103
 
 
104
        // ************************************* TOP LEVEL *************************************
 
105
 
 
106
        /**
 
107
         * Constructor creates a VectorDrawing object for a given EditWindow.
 
108
         * @param wnd the EditWindow associated with this VectorDrawing.
 
109
         */
 
110
        public VectorDrawing()
 
111
        {
 
112
        }
 
113
 
 
114
        /**
 
115
         * Main entry point for drawing a cell.
 
116
         * @param offscreen offscreen buffer
 
117
         * @param scale edit window scale
 
118
         * @param offset the offset factor for this window
 
119
         * @param cell the cell to draw
 
120
         * @param fullInstantiate true to draw all the way to the bottom of the hierarchy.
 
121
         * @param inPlaceNodePath a List of NodeInsts to the cell being in-place edited
 
122
         * @param screenLimit the area in the cell to display (null to show all).
 
123
         */
 
124
        public void render(PixelDrawing offscreen, double scale, Point2D offset, Cell cell, boolean fullInstantiate,
 
125
                List<NodeInst> inPlaceNodePath, Cell inPlaceCurrent, Rectangle screenLimit, VarContext context)
 
126
        {
 
127
                // set colors to use
 
128
                textGraphics.setColor(new Color(User.getColor(User.ColorPrefType.TEXT)));
 
129
                instanceGraphics.setColor(new Color(User.getColor(User.ColorPrefType.INSTANCE)));
 
130
                textColor = new Color(User.getColor(User.ColorPrefType.TEXT) & 0xFFFFFF);
 
131
 
 
132
                // see if any layers are being highlighted/dimmed
 
133
                this.offscreen = offscreen;
 
134
                offscreen.highlightingLayers = false;
 
135
                for(Iterator<Layer> it = Technology.getCurrent().getLayers(); it.hasNext(); )
 
136
                {
 
137
                        Layer layer = it.next();
 
138
                        if (layer.isDimmed())
 
139
                        {
 
140
                                offscreen.highlightingLayers = true;
 
141
                                break;
 
142
                        }
 
143
                }
 
144
 
 
145
                // set size limit
 
146
                Dimension sz = offscreen.getSize();
 
147
                this.scale = (float)scale;
 
148
                scale_ = (float)(scale/DBMath.GRID);
 
149
                maxObjectSize = (float)User.getGreekSizeLimit() / this.scale;
 
150
                maxTextSize = maxObjectSize / (float)User.getGlobalTextScale();
 
151
                double screenArea = sz.getWidth()/scale * sz.getHeight()/scale;
 
152
                maxCellSize = (float)(User.getGreekCellSizeLimit() * screenArea);
 
153
 
 
154
                // statistics
 
155
                startTime = System.currentTimeMillis();
 
156
                long initialUsed = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
 
157
                takingLongTime = false;
 
158
                boxCount = tinyBoxCount = lineBoxCount = lineCount = polygonCount = 0;
 
159
                crossCount = textCount = circleCount = arcCount = 0;
 
160
                subCellCount = tinySubCellCount = 0;
 
161
 
 
162
                // draw recursively
 
163
                this.fullInstantiate = fullInstantiate;
 
164
                this.inPlaceNodePath = inPlaceNodePath;
 
165
                this.inPlaceCurrent = inPlaceCurrent;
 
166
                szHalfWidth = sz.width / 2;
 
167
                szHalfHeight = sz.height / 2;
 
168
                screenLX = 0;   screenHX = sz.width;
 
169
                screenLY = 0;   screenHY = sz.height;
 
170
                factorX = (float)(offset.getX()*DBMath.GRID - szHalfWidth/scale_);
 
171
                factorY = (float)(offset.getY()*DBMath.GRID + szHalfHeight/scale_);
 
172
                factorX_ = (int)factorX;
 
173
                factorY_ = (int)factorY;
 
174
                scale_int = (int)(scale_ * (1 << SCALE_SH));
 
175
                if (screenLimit != null)
 
176
                {
 
177
                        screenLX = screenLimit.x;
 
178
                        if (screenLX < 0) screenLX = 0;
 
179
                        screenHX = screenLimit.x + screenLimit.width;
 
180
                        if (screenHX >= sz.width) screenHX = sz.width-1;
 
181
                        screenLY = screenLimit.y;
 
182
                        if (screenLY < 0) screenLY = 0;
 
183
                        screenHY = screenLimit.y + screenLimit.height;
 
184
                        if (screenHY >= sz.height) screenHY = sz.height-1;
 
185
                }
 
186
 
 
187
                // draw the screen, starting with the top cell
 
188
                stopRendering = false;
 
189
                try
 
190
                {
 
191
                        VectorCache.VectorCell topVC = drawCell(cell, Orientation.IDENT, context);
 
192
                        topVD = this;
 
193
                        render(topVC, 0, 0, context, 0);
 
194
                        drawList(0, 0, topVC.getTopOnlyShapes(), 0, false);
 
195
                } catch (AbortRenderingException e)
 
196
                {
 
197
                }
 
198
                topVD = null;
 
199
 
 
200
                if (takingLongTime)
 
201
                {
 
202
                        TopLevel.setBusyCursor(false);
 
203
                        System.out.println("Done");
 
204
                }
 
205
 
 
206
                if (TAKE_STATS && Job.getDebug())
 
207
                {
 
208
                        long curUsed = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
 
209
                        long memUsed = curUsed - initialUsed;
 
210
                        long renderTime = System.currentTimeMillis() - startTime;
 
211
                        System.out.println("Time to render: "+TextUtils.getElapsedTime(renderTime) + "    Memory Used: "+ memUsed);
 
212
                        System.out.println("   Rendered "+boxCount+" boxes ("+tinyBoxCount+" tiny, "+lineBoxCount+" lines), "+
 
213
                                lineCount+" lines, "+polygonCount+" polys, "+crossCount+" crosses, "+
 
214
                                textCount+" texts, "+circleCount+" circles, "+arcCount+" arcs, "+
 
215
                                subCellCount+" subcells ("+tinySubCellCount+" tiny)");
 
216
                }
 
217
        }
 
218
 
 
219
        /**
 
220
         * Main entry point for drawing a tech menu entry.
 
221
         * @param offscreen offscreen buffer
 
222
         * @param scale edit window scale
 
223
         * @param offset the offset factor for this window
 
224
         * @param shapes shapes of tech menu
 
225
         * @param forceVisible true to force all layers to be drawn (regardless of user settings)
 
226
         */
 
227
        public void render(PixelDrawing offscreen, double scale, Point2D offset, VectorCache.VectorBase[] shapes, boolean forceVisible)
 
228
        {
 
229
                // set colors to use
 
230
                textGraphics.setColor(new Color(User.getColor(User.ColorPrefType.TEXT)));
 
231
                textColor = new Color(User.getColor(User.ColorPrefType.TEXT) & 0xFFFFFF);
 
232
 
 
233
                // see if any layers are being highlighted/dimmed
 
234
                this.offscreen = offscreen;
 
235
 
 
236
                // set size limit
 
237
                Dimension sz = offscreen.getSize();
 
238
                this.scale = (float)scale;
 
239
                scale_ = (float)(scale/DBMath.GRID);
 
240
 
 
241
                // draw recursively
 
242
                szHalfWidth = sz.width / 2;
 
243
                szHalfHeight = sz.height / 2;
 
244
                screenLX = 0;   screenHX = sz.width;
 
245
                screenLY = 0;   screenHY = sz.height;
 
246
                factorX = (float)(offset.getX()*DBMath.GRID - szHalfWidth/scale_);
 
247
                factorY = (float)(offset.getY()*DBMath.GRID + szHalfHeight/scale_);
 
248
                factorX_ = (int)factorX;
 
249
                factorY_ = (int)factorY;
 
250
                scale_int = (int)(scale_ * (1 << SCALE_SH));
 
251
 
 
252
                // draw the screen, starting with the top cell
 
253
                try
 
254
                {
 
255
                        List<VectorCache.VectorBase> shapeList = Arrays.asList(shapes);
 
256
                        drawList(0, 0, shapeList, 0, forceVisible);
 
257
                } catch (AbortRenderingException e)
 
258
                {
 
259
                }
 
260
        }
 
261
 
 
262
        /**
 
263
         * Class to define a signal to abort rendering.
 
264
         */
 
265
        class AbortRenderingException extends Exception {}
 
266
 
 
267
        /**
 
268
         * Method to request that the current rendering be aborted because it must be restarted.
 
269
         *
 
270
         */
 
271
        public void abortRendering()
 
272
        {
 
273
                stopRendering = true;
 
274
        }
 
275
 
 
276
        /**
 
277
         * Method to recursively render a cached cell.
 
278
         * @param vc the cached cell to render
 
279
         * @param oX the X offset for rendering the cell (in database grid coordinates).
 
280
         * @param oY the Y offset for rendering the cell (in database grid coordinates).
 
281
         * @param context the VarContext for this point in the rendering.
 
282
         * @param level: 0=top-level cell in window; 1=low level cell; -1=greeked cell.
 
283
         */
 
284
        private void render(VectorCache.VectorCell vc, int oX, int oY, VarContext context, int level)
 
285
                throws AbortRenderingException
 
286
        {
 
287
                // render main list of shapes
 
288
                drawList(oX, oY, vc.filledShapes, level, false);
 
289
                drawList(oX, oY, vc.shapes, level, false);
 
290
 
 
291
                // now render subcells
 
292
                Cell cell = VectorCache.theCache.database.getCell(vc.vcg.cellId);
 
293
                for(VectorCache.VectorSubCell vsc : vc.subCells)
 
294
                {
 
295
                        if (stopRendering) throw new AbortRenderingException();
 
296
                        NodeInst ni = cell.getNodeById(vsc.n.nodeId);
 
297
                        Cell subCell = (Cell)ni.getProto();
 
298
                        subCellCount++;
 
299
 
 
300
                        // get instance location
 
301
                        int soX = vsc.offsetX + oX;
 
302
                        int soY = vsc.offsetY + oY;
 
303
                        VectorCache.VectorCell subVC = VectorCache.theCache.findVectorCell(vsc.subCellId, vc.orient.concatenate(vsc.n.orient));
 
304
                        gridToScreen(subVC.lX + soX, subVC.hY + soY, tempPt1);
 
305
                        gridToScreen(subVC.hX + soX, subVC.lY + soY, tempPt2);
 
306
                        int lX = tempPt1.x;
 
307
                        int lY = tempPt1.y;
 
308
                        int hX = tempPt2.x;
 
309
                        int hY = tempPt2.y;
 
310
 
 
311
                        // see if the subcell is clipped
 
312
                        if (hX < screenLX || lX >= screenHX) continue;
 
313
                        if (hY < screenLY || lY >= screenHY) continue;
 
314
 
 
315
                        // see if the cell is too tiny to draw
 
316
                        if (subVC.vcg.cellMinSize < maxObjectSize)
 
317
                        {
 
318
                                Orientation thisOrient = vsc.n.orient;
 
319
                                Orientation recurseTrans = vc.orient.concatenate(thisOrient);
 
320
                                VarContext subContext = context.push(ni);
 
321
                                VectorCache.VectorCell subVC_ = drawCell(subCell, recurseTrans, subContext);
 
322
                                assert subVC_ == subVC;
 
323
                                makeGreekedImage(subVC);
 
324
 
 
325
                                int fadeColor = getFadeColor(subVC, subContext);
 
326
                                drawTinyBox(lX, hX, lY, hY, fadeColor, subVC);
 
327
                                tinySubCellCount++;
 
328
                                continue;
 
329
                        }
 
330
 
 
331
                        // see if drawing "down in place"
 
332
                        boolean onPathDown = false;
 
333
                        if (inPlaceNodePath != null)
 
334
                        {
 
335
                                for(NodeInst niOnPath : inPlaceNodePath)
 
336
                                {
 
337
                                        if (niOnPath.getProto().getId() == vsc.subCellId)
 
338
                                        {
 
339
                                                onPathDown = true;
 
340
                                                break;
 
341
                                        }
 
342
                                }
 
343
                        }
 
344
 
 
345
                        // see if cell contents should be drawn
 
346
                        boolean expanded = ni.isExpanded() || fullInstantiate;
 
347
 
 
348
                        // if not expanded, but viewing this cell in-place, expand it
 
349
                        if (!expanded && onPathDown) expanded = true;
 
350
 
 
351
                        if (expanded)
 
352
                        {
 
353
                                Orientation thisOrient = vsc.n.orient;
 
354
                                Orientation recurseTrans = vc.orient.concatenate(thisOrient);
 
355
                                VarContext subContext = context.push(ni);
 
356
                                VectorCache.VectorCell subVC_ = drawCell(subCell, recurseTrans, subContext);
 
357
                                assert subVC_ == subVC;
 
358
 
 
359
                                // expanded cells may be replaced with greeked versions (not icons)
 
360
                                if (!subCell.isIcon())
 
361
                                {
 
362
                                        // may also be "tiny" if all features in the cell are tiny
 
363
                                        boolean allFeaturesTiny = subVC.maxFeatureSize > 0 && subVC.maxFeatureSize < maxObjectSize &&
 
364
                                                subVC.vcg.cellArea < maxCellSize && isContentsTiny(subCell, subVC, recurseTrans, context);
 
365
 
 
366
                                        // may also be "tiny" if the cell is smaller than the greeked image
 
367
                                        boolean smallerThanGreek = User.isUseCellGreekingImages() && hX-lX <= MAXGREEKSIZE && hY-lY <= MAXGREEKSIZE;
 
368
                                        if (allFeaturesTiny || smallerThanGreek)
 
369
                                        {
 
370
                                                makeGreekedImage(subVC);
 
371
                                                int fadeColor = getFadeColor(subVC, context);
 
372
                                                drawTinyBox(lX, hX, lY, hY, fadeColor, subVC);
 
373
                                                tinySubCellCount++;
 
374
                                                continue;
 
375
                                        }
 
376
                                }
 
377
 
 
378
                                int subLevel = level;
 
379
                                if (subLevel == 0) subLevel = 1;
 
380
                                render(subVC, soX, soY, subContext, subLevel);
 
381
                        } else
 
382
                        {
 
383
                                // now draw with the proper line type
 
384
                                int[] op = subVC.outlinePoints;
 
385
                                int p1x = op[0] + soX;
 
386
                                int p1y = op[1] + soY;
 
387
                                int p2x = op[2] + soX;
 
388
                                int p2y = op[3] + soY;
 
389
                                int p3x = op[4] + soX;
 
390
                                int p3y = op[5] + soY;
 
391
                                int p4x = op[6] + soX;
 
392
                                int p4y = op[7] + soY;
 
393
                                gridToScreen(p1x, p1y, tempPt1);   gridToScreen(p2x, p2y, tempPt2);
 
394
                                offscreen.drawLine(tempPt1, tempPt2, null, instanceGraphics, 0, false);
 
395
                                gridToScreen(p2x, p2y, tempPt1);   gridToScreen(p3x, p3y, tempPt2);
 
396
                                offscreen.drawLine(tempPt1, tempPt2, null, instanceGraphics, 0, false);
 
397
                                gridToScreen(p3x, p3y, tempPt1);   gridToScreen(p4x, p4y, tempPt2);
 
398
                                offscreen.drawLine(tempPt1, tempPt2, null, instanceGraphics, 0, false);
 
399
                                gridToScreen(p1x, p1y, tempPt1);   gridToScreen(p4x, p4y, tempPt2);
 
400
                                offscreen.drawLine(tempPt1, tempPt2, null, instanceGraphics, 0, false);
 
401
 
 
402
                                // draw the instance name
 
403
                                if (User.isTextVisibilityOnInstance())
 
404
                                {
 
405
                                        tempRect.setBounds(lX, lY, hX-lX, hY-lY);
 
406
                                        TextDescriptor descript = vsc.n.protoDescriptor;
 
407
                                        offscreen.drawText(tempRect, Poly.Type.TEXTBOX, descript, subCell.describe(false), null, textGraphics, false);
 
408
                                }
 
409
                        }
 
410
                        if (level == 0 || onPathDown || inPlaceCurrent == cell)
 
411
                                drawPortList(vsc, subVC, soX, soY, ni.isExpanded());
 
412
                }
 
413
        }
 
414
 
 
415
        /**
 
416
         * Method to draw a list of cached shapes.
 
417
         * @param oX the X offset to draw the shapes (in database grid coordinates).
 
418
         * @param oY the Y offset to draw the shapes (in database grid coordinates).
 
419
         * @param shapes the List of shapes (VectorBase objects).
 
420
         * @param level: 0=top-level cell in window; 1=low level cell; -1=greeked cell.
 
421
         * @param forceVisible true to force all layers to be drawn (regardless of user settings)
 
422
         */
 
423
        private void drawList(int oX, int oY, List<VectorCache.VectorBase> shapes, int level, boolean forceVisible)
 
424
                throws AbortRenderingException
 
425
        {
 
426
                // render all shapes in reverse order (because PixelDrawing don't overwrite opaque layers)
 
427
                for (int k = shapes.size() - 1; k >= 0; k--)
 
428
                {
 
429
                        VectorCache.VectorBase vb = shapes.get(k);
 
430
                        if (stopRendering) throw new AbortRenderingException();
 
431
 
 
432
                        // get visual characteristics of shape
 
433
                        Layer layer = vb.layer;
 
434
                        boolean dimmed = false;
 
435
                        if (layer != null)
 
436
                        {
 
437
                                if (level < 0)
 
438
                                {
 
439
                                        // greeked cells ignore cut and implant layers
 
440
                                        Layer.Function fun = layer.getFunction();
 
441
                                        if (fun.isContact() || fun.isWell() || fun.isSubstrate()) continue;
 
442
                                }
 
443
                                if (!forceVisible && !layer.isVisible()) continue;
 
444
                                dimmed = layer.isDimmed();
 
445
                        }
 
446
                        byte [][] layerBitMap = null;
 
447
                        EGraphics graphics = vb.graphics;
 
448
                        if (graphics != null)
 
449
                        {
 
450
                                int layerNum = graphics.getTransparentLayer() - 1;
 
451
                                if (layerNum < offscreen.numLayerBitMaps) layerBitMap = offscreen.getLayerBitMap(layerNum);
 
452
                        }
 
453
 
 
454
                        // handle each shape
 
455
                        if (vb instanceof VectorCache.VectorManhattan)
 
456
                        {
 
457
                                boxCount++;
 
458
                                VectorCache.VectorManhattan vm = (VectorCache.VectorManhattan)vb;
 
459
 
 
460
                                double maxSize = maxObjectSize*DBMath.GRID;
 
461
                                int fadeCol = -1;
 
462
                                if (layer != null)
 
463
                                {
 
464
                                        Layer.Function fun = layer.getFunction();
 
465
                                        if (fun.isImplant() || fun.isSubstrate())
 
466
                                        {
 
467
                                                // well and substrate layers are made smaller so that they "greek" sooner
 
468
                                                if (!vm.pureLayer)
 
469
                                                        maxSize *= 10;
 
470
                                        } else if (vm.graphics != null) {
 
471
                                                fadeCol = vm.graphics.getRGB();
 
472
                                        }
 
473
                                }
 
474
                                for (int i = 0; i < vm.coords.length; i += 4) {
 
475
                                        int c1X = vm.coords[i];
 
476
                                        int c1Y = vm.coords[i+1];
 
477
                                        int c2X = vm.coords[i+2];
 
478
                                        int c2Y = vm.coords[i+3];
 
479
                                        long dX = c2X - c1X;
 
480
                                        long dY = c2Y - c1Y;
 
481
                                        if (dX < maxSize || dY < maxSize)
 
482
                                        {
 
483
                                                if (fadeCol < 0) continue;
 
484
                                                if (dX < maxSize && dY < maxSize)
 
485
                                                {
 
486
                                                        // both dimensions tiny: just draw a dot
 
487
                                                        gridToScreen(c1X+oX, c1Y+oY, tempPt1);
 
488
                                                        int x = tempPt1.x;
 
489
                                                        int y = tempPt1.y;
 
490
                                                        if (x < screenLX || x >= screenHX) continue;
 
491
                                                        if (y < screenLY || y >= screenHY) continue;
 
492
                                                        offscreen.drawPoint(x, y, null, fadeCol);
 
493
                                                        tinyBoxCount++;
 
494
                                                } else
 
495
                                                {
 
496
                                                        // one dimension tiny: draw a line
 
497
                                                        gridToScreen(c1X+oX, c2Y+oY, tempPt1);
 
498
                                                        gridToScreen(c2X+oX, c1Y+oY, tempPt2);
 
499
                                                        assert tempPt1.x <= tempPt2.x && tempPt1.y <= tempPt2.y;
 
500
                                                        int lX = tempPt1.x;
 
501
                                                        int hX = tempPt2.x;
 
502
                                                        int lY = tempPt1.y;
 
503
                                                        int hY = tempPt2.y;
 
504
                                                        if (hX < screenLX || lX >= screenHX) continue;
 
505
                                                        if (hY < screenLY || lY >= screenHY) continue;
 
506
                                                        drawTinyBox(lX, hX, lY, hY, fadeCol, null);
 
507
                                                        lineBoxCount++;
 
508
                                                }
 
509
                                                continue;
 
510
                                        }
 
511
 
 
512
                                        // determine coordinates of rectangle on the screen
 
513
                                        gridToScreen(c1X+oX, c2Y+oY, tempPt1);
 
514
                                        gridToScreen(c2X+oX, c1Y+oY, tempPt2);
 
515
                                        assert tempPt1.x <= tempPt2.x && tempPt1.y <= tempPt2.y;
 
516
                                        int lX = tempPt1.x;
 
517
                                        int hX = tempPt2.x;
 
518
                                        int lY = tempPt1.y;
 
519
                                        int hY = tempPt2.y;
 
520
 
 
521
                                        // reject if completely off the screen
 
522
                                        if (hX < screenLX || lX >= screenHX) continue;
 
523
                                        if (hY < screenLY || lY >= screenHY) continue;
 
524
 
 
525
                                        // clip to screen
 
526
                                        if (lX < screenLX) lX = screenLX;
 
527
                                        if (hX >= screenHX) hX = screenHX-1;
 
528
                                        if (lY < screenLY) lY = screenLY;
 
529
                                        if (hY >= screenHY) hY = screenHY-1;
 
530
 
 
531
                                        // draw the box
 
532
                                        offscreen.drawBox(lX, hX, lY, hY, layerBitMap, graphics, dimmed);
 
533
                                }
 
534
                        } else if (vb instanceof VectorCache.VectorLine)
 
535
                        {
 
536
                                lineCount++;
 
537
                                VectorCache.VectorLine vl = (VectorCache.VectorLine)vb;
 
538
 
 
539
                                // determine coordinates of line on the screen
 
540
                                gridToScreen(vl.fX+oX, vl.fY+oY, tempPt1);
 
541
                                gridToScreen(vl.tX+oX, vl.tY+oY, tempPt2);
 
542
 
 
543
                                // clip and draw the line
 
544
                                offscreen.drawLine(tempPt1, tempPt2, layerBitMap, graphics, vl.texture, dimmed);
 
545
                        } else if (vb instanceof VectorCache.VectorPolygon)
 
546
                        {
 
547
                                polygonCount++;
 
548
                                VectorCache.VectorPolygon vp = (VectorCache.VectorPolygon)vb;
 
549
                                Point [] intPoints = new Point[vp.points.length];
 
550
                                for(int i=0; i<vp.points.length; i++)
 
551
                                {
 
552
                                        intPoints[i] = new Point();
 
553
                                        gridToScreen(vp.points[i].x+oX, vp.points[i].y+oY, intPoints[i]);
 
554
                                }
 
555
                                Point [] clippedPoints = GenMath.clipPoly(intPoints, screenLX, screenHX-1, screenLY, screenHY-1);
 
556
                                offscreen.drawPolygon(clippedPoints, layerBitMap, graphics, dimmed);
 
557
                        } else if (vb instanceof VectorCache.VectorCross)
 
558
                        {
 
559
                                crossCount++;
 
560
                                VectorCache.VectorCross vcr = (VectorCache.VectorCross)vb;
 
561
                                gridToScreen(vcr.x+oX, vcr.y+oY, tempPt1);
 
562
                                int size = 5;
 
563
                                if (vcr.small) size = 3;
 
564
                                offscreen.drawLine(new Point(tempPt1.x-size, tempPt1.y), new Point(tempPt1.x+size, tempPt1.y), null, graphics, 0, dimmed);
 
565
                                offscreen.drawLine(new Point(tempPt1.x, tempPt1.y-size), new Point(tempPt1.x, tempPt1.y+size), null, graphics, 0, dimmed);
 
566
                        } else if (vb instanceof VectorCache.VectorText)
 
567
                        {
 
568
                                VectorCache.VectorText vt = (VectorCache.VectorText)vb;
 
569
                                switch (vt.textType)
 
570
                                {
 
571
                                        case VectorCache.VectorText.TEXTTYPEARC:
 
572
                                                if (!User.isTextVisibilityOnArc()) continue;
 
573
                                                break;
 
574
                                        case VectorCache.VectorText.TEXTTYPENODE:
 
575
                                                if (!User.isTextVisibilityOnNode()) continue;
 
576
                                                break;
 
577
                                        case VectorCache.VectorText.TEXTTYPECELL:
 
578
                                                if (!User.isTextVisibilityOnCell()) continue;
 
579
                                                break;
 
580
                                        case VectorCache.VectorText.TEXTTYPEEXPORT:
 
581
                                                if (!User.isTextVisibilityOnExport()) continue;
 
582
                                                break;
 
583
                                        case VectorCache.VectorText.TEXTTYPEANNOTATION:
 
584
                                                if (!User.isTextVisibilityOnAnnotation()) continue;
 
585
                                                break;
 
586
                                        case VectorCache.VectorText.TEXTTYPEINSTANCE:
 
587
                                                if (!User.isTextVisibilityOnInstance()) continue;
 
588
                                                break;
 
589
                                }
 
590
                                if (vt.height < maxTextSize) continue;
 
591
 
 
592
                                String drawString = vt.str;
 
593
                                int lX = vt.bounds.x;
 
594
                                int lY = vt.bounds.y;
 
595
                                int hX = lX + vt.bounds.width;
 
596
                                int hY = lY + vt.bounds.height;
 
597
                                gridToScreen(lX + oX, hY + oY, tempPt1);
 
598
                                gridToScreen(hX + oX, lY + oY, tempPt2);
 
599
                                lX = tempPt1.x;
 
600
                                lY = tempPt1.y;
 
601
                                hX = tempPt2.x;
 
602
                                hY = tempPt2.y;
 
603
//                              int lX, hX, lY, hY;
 
604
//                              if (tempPt1.x < tempPt2.x) { lX = tempPt1.x;   hX = tempPt2.x; } else
 
605
//                                      { lX = tempPt2.x;   hX = tempPt1.x; }
 
606
//                              if (tempPt1.y < tempPt2.y) { lY = tempPt1.y;   hY = tempPt2.y; } else
 
607
//                                      { lY = tempPt2.y;   hY = tempPt1.y; }
 
608
 
 
609
                                // for ports, switch between the different port display methods
 
610
//                              if (vt.textType == VectorCache.VectorText.TEXTTYPEPORT)
 
611
//                              {
 
612
//                                      int portDisplayLevel = User.getPortDisplayLevel();
 
613
//                                      Color portColor = vt.e.getBasePort().getPortColor();
 
614
//                                      if (vt.ni.isExpanded()) portColor = textColor;
 
615
//                                      if (portColor != null) portGraphics.setColor(portColor);
 
616
//                                      int cX = (lX + hX) / 2;
 
617
//                                      int cY = (lY + hY) / 2;
 
618
//                                      if (portDisplayLevel == 2)
 
619
//                                      {
 
620
//                                              // draw port as a cross
 
621
//                                              int size = 3;
 
622
//                                              offscreen.drawLine(new Point(cX-size, cY), new Point(cX+size, cY), null, portGraphics, 0, false);
 
623
//                                              offscreen.drawLine(new Point(cX, cY-size), new Point(cX, cY+size), null, portGraphics, 0, false);
 
624
//                                              crossCount++;
 
625
//                                              continue;
 
626
//                                      }
 
627
//
 
628
//                                      // draw port as text
 
629
//                                      if (portDisplayLevel == 1) drawString = vt.e.getShortName(); else
 
630
//                                              drawString = vt.e.getName();
 
631
//                                      graphics = portGraphics;
 
632
//                                      layerBitMap = null;
 
633
//                                      lX = hX = cX;
 
634
//                                      lY = hY = cY;
 
635
//                              } else
 
636
                                if (vt.textType == VectorCache.VectorText.TEXTTYPEEXPORT && vt.basePort != null)
 
637
                                {
 
638
                                        if (!vt.basePort.getParent().isVisible()) continue;
 
639
                                        int exportDisplayLevel = User.getExportDisplayLevel();
 
640
                                        if (exportDisplayLevel == 2)
 
641
                                        {
 
642
                                                // draw export as a cross
 
643
                                                int cX = (lX + hX) / 2;
 
644
                                                int cY = (lY + hY) / 2;
 
645
                                                int size = 3;
 
646
                                                offscreen.drawLine(new Point(cX-size, cY), new Point(cX+size, cY), null, textGraphics, 0, false);
 
647
                                                offscreen.drawLine(new Point(cX, cY-size), new Point(cX, cY+size), null, textGraphics, 0, false);
 
648
                                                crossCount++;
 
649
                                                continue;
 
650
                                        }
 
651
 
 
652
                                        // draw export as text
 
653
                                        if (exportDisplayLevel == 1)
 
654
                                                drawString = Export.getShortName(drawString);
 
655
                                        graphics = textGraphics;
 
656
                                        layerBitMap = null;
 
657
                                }
 
658
 
 
659
                                textCount++;
 
660
                                tempRect.setBounds(lX, lY, hX-lX, hY-lY);
 
661
                                offscreen.drawText(tempRect, vt.style, vt.descript, drawString, layerBitMap, graphics, dimmed);
 
662
                        } else if (vb instanceof VectorCache.VectorCircle)
 
663
                        {
 
664
                                circleCount++;
 
665
                                VectorCache.VectorCircle vci = (VectorCache.VectorCircle)vb;
 
666
                                gridToScreen(vci.cX+oX, vci.cY+oY, tempPt1);
 
667
                                gridToScreen(vci.eX+oX, vci.eY+oY, tempPt2);
 
668
                                switch (vci.nature)
 
669
                                {
 
670
                                        case 0: offscreen.drawCircle(tempPt1, tempPt2, layerBitMap, graphics, dimmed);        break;
 
671
                                        case 1: offscreen.drawThickCircle(tempPt1, tempPt2, layerBitMap, graphics, dimmed);   break;
 
672
                                        case 2: offscreen.drawDisc(tempPt1, tempPt2, layerBitMap, graphics, dimmed);          break;
 
673
                                }
 
674
                        } else if (vb instanceof VectorCache.VectorCircleArc)
 
675
                        {
 
676
                                arcCount++;
 
677
                                VectorCache.VectorCircleArc vca = (VectorCache.VectorCircleArc)vb;
 
678
                                gridToScreen(vca.cX+oX, vca.cY+oY, tempPt1);
 
679
                                gridToScreen(vca.eX1+oX, vca.eY1+oY, tempPt2);
 
680
                                gridToScreen(vca.eX2+oX, vca.eY2+oY, tempPt3);
 
681
                                offscreen.drawCircleArc(tempPt1, tempPt2, tempPt3, vca.thick, layerBitMap, graphics, dimmed);
 
682
                        }
 
683
                }
 
684
        }
 
685
 
 
686
        /**
 
687
         * Method to draw a list of cached port shapes.
 
688
         * @param oX the X offset to draw the shapes (in database grid coordinates).
 
689
         * @param oY the Y offset to draw the shapes (in database grid coordinates).
 
690
         * @parem true to draw a list on expanded instance
 
691
         */
 
692
        private void drawPortList(VectorCache.VectorSubCell vsc, VectorCache.VectorCell subVC_, int oX, int oY, boolean expanded)
 
693
                throws AbortRenderingException
 
694
        {
 
695
                if (!User.isTextVisibilityOnPort()) return;
 
696
                // render all shapes
 
697
                List<VectorCache.VectorCellExport> portShapes = subVC_.vcg.getPortShapes();
 
698
                int[] portCenters = subVC_.getPortCenters();
 
699
                assert portShapes.size()*2 == portCenters.length;
 
700
                for (int i = 0; i < portShapes.size(); i++) {
 
701
                        VectorCache.VectorCellExport vce = portShapes.get(i);
 
702
                        if (stopRendering) throw new AbortRenderingException();
 
703
 
 
704
                        // get visual characteristics of shape
 
705
                        if (vsc.shownPorts.get(vce.getChronIndex())) continue;
 
706
                        if (vce.height < maxTextSize) continue;
 
707
 
 
708
                        int cX = portCenters[i*2];
 
709
                        int cY = portCenters[i*2 + 1];
 
710
                        gridToScreen(cX + oX, cY + oY, tempPt1);
 
711
                        cX = tempPt1.x;
 
712
                        cY = tempPt1.y;
 
713
 
 
714
                        int portDisplayLevel = User.getPortDisplayLevel();
 
715
                        Color portColor = vce.getPortColor();
 
716
                        if (expanded) portColor = textColor;
 
717
                        if (portColor != null) portGraphics.setColor(portColor);
 
718
                        if (portDisplayLevel == 2)
 
719
                        {
 
720
                                // draw port as a cross
 
721
                                int size = 3;
 
722
                                offscreen.drawLine(new Point(cX-size, cY), new Point(cX+size, cY), null, portGraphics, 0, false);
 
723
                                offscreen.drawLine(new Point(cX, cY-size), new Point(cX, cY+size), null, portGraphics, 0, false);
 
724
                                crossCount++;
 
725
                                continue;
 
726
                        }
 
727
 
 
728
                        // draw port as text
 
729
                        boolean shortName = portDisplayLevel == 1;
 
730
                        String drawString = vce.getName(shortName);
 
731
 
 
732
                        textCount++;
 
733
                        tempRect.setBounds(cX, cY, 0, 0);
 
734
                        offscreen.drawText(tempRect, vce.style, vce.descript, drawString, null, portGraphics, false);
 
735
                }
 
736
        }
 
737
 
 
738
        /**
 
739
         * Method to convert a database grid coordinate to screen coordinates.
 
740
         * @param dbX the X coordinate (in database grid units).
 
741
         * @param dbY the Y coordinate (in database grid units).
 
742
         * @param result the Point in which to store the screen coordinates.
 
743
         */
 
744
        private void gridToScreen(int dbX, int dbY, Point result)
 
745
        {
 
746
                if (false) {
 
747
                        result.x = ((dbX - factorX_) * scale_int) >> SCALE_SH;
 
748
                        result.y = ((factorY_ - dbY) * scale_int) >> SCALE_SH;
 
749
                } else {
 
750
                        double scrX = (dbX - factorX) * scale_;
 
751
                        double scrY = (factorY - dbY) * scale_;
 
752
                        result.x = (int)(scrX >= 0 ? scrX + 0.5 : scrX - 0.5);
 
753
                        result.y = (int)(scrY >= 0 ? scrY + 0.5 : scrY - 0.5);
 
754
                }
 
755
        }
 
756
 
 
757
        /**
 
758
         * Method to draw a tiny box on the screen in a given color.
 
759
         * Done when the object is too small to draw in full detail.
 
760
         * @param lX the low X coordinate of the box.
 
761
         * @param hX the high X coordinate of the box.
 
762
         * @param lY the low Y coordinate of the box.
 
763
         * @param hY the high Y coordinate of the box.
 
764
         * @param col the color to draw.
 
765
         */
 
766
        private void drawTinyBox(int lX, int hX, int lY, int hY, int col, VectorCache.VectorCell greekedCell)
 
767
        {
 
768
                if (lX < screenLX) lX = screenLX;
 
769
                if (hX >= screenHX) hX = screenHX-1;
 
770
                if (lY < screenLY) lY = screenLY;
 
771
                if (hY >= screenHY) hY = screenHY-1;
 
772
                if (User.isUseCellGreekingImages())
 
773
                {
 
774
                        if (greekedCell != null && greekedCell.fadeImageColors != null)
 
775
                        {
 
776
                                int backgroundColor = User.getColor(User.ColorPrefType.BACKGROUND);
 
777
                                int backgroundRed = (backgroundColor >> 16) & 0xFF;
 
778
                                int backgroundGreen = (backgroundColor >> 8) & 0xFF;
 
779
                                int backgroundBlue = backgroundColor & 0xFF;
 
780
 
 
781
                                // render the icon properly with scale
 
782
                                int greekWid = greekedCell.fadeImageWid;
 
783
                                int greekHei = greekedCell.fadeImageHei;
 
784
                                int wid = hX - lX;
 
785
                                int hei = hY - lY;
 
786
                                float xInc = greekWid / (float)wid;
 
787
                                float yInc = greekHei / (float)hei;
 
788
                                float yPos = 0;
 
789
                                for(int y=0; y<hei; y++)
 
790
                                {
 
791
                                        float yEndPos = yPos + yInc;
 
792
                                        int yS = (int)yPos;
 
793
                                        int yE = (int)yEndPos;
 
794
 
 
795
                                        float xPos = 0;
 
796
                                        for(int x=0; x<wid; x++)
 
797
                                        {
 
798
                                                float xEndPos = xPos + xInc;
 
799
                                                int xS = (int)xPos;
 
800
                                                int xE = (int)xEndPos;
 
801
 
 
802
                                                float r = 0, g = 0, b = 0;
 
803
                                                float totalArea = 0;
 
804
                                                for(int yGrab = yS; yGrab <= yE; yGrab++)
 
805
                                                {
 
806
                                                        if (yGrab >= greekHei) continue;
 
807
                                                        float yArea = 1;
 
808
                                                        if (yGrab == yS) yArea = (1 - (yPos - yS));
 
809
                                                        if (yGrab == yE) yArea *= (yEndPos-yE);
 
810
 
 
811
                                                        for(int xGrab = xS; xGrab <= xE; xGrab++)
 
812
                                                        {
 
813
                                                                if (xGrab >= greekWid) continue;
 
814
                                                                int index = xGrab + yGrab*greekedCell.fadeImageWid;
 
815
                                                                if (greekedCell.fadeImageColors==null || index >= greekedCell.fadeImageColors.length)
 
816
                                                                        continue;
 
817
                                                                int value = greekedCell.fadeImageColors[index];
 
818
                                                                int red = (value >> 16) & 0xFF;
 
819
                                                                int green = (value >> 8) & 0xFF;
 
820
                                                                int blue = value & 0xFF;
 
821
                                                                float area = yArea;
 
822
                                                                if (xGrab == xS) area *= (1 - (xPos - xS));
 
823
                                                                if (xGrab == xE) area *= (xEndPos-xE);
 
824
                                                                if (area <= 0) continue;
 
825
                                                                r += red * area;
 
826
                                                                g += green * area;
 
827
                                                                b += blue * area;
 
828
                                                                totalArea += area;
 
829
                                                        }
 
830
                                                }
 
831
                                                if (totalArea > 0)
 
832
                                                {
 
833
                                                        int red = (int)(r / totalArea);
 
834
                                                        if (red > 255) red = 255;
 
835
                                                        int green = (int)(g / totalArea);
 
836
                                                        if (green > 255) green = 255;
 
837
                                                        int blue = (int)(b / totalArea);
 
838
                                                        if (blue > 255) blue = 255;
 
839
                                                        if (Math.abs(backgroundRed-red) > 2 || Math.abs(backgroundGreen-green) > 2 ||
 
840
                                                                Math.abs(backgroundBlue-blue) > 2)
 
841
                                                        {
 
842
                                                                offscreen.drawPoint(lX+x, lY+y, null, (red << 16) | (green << 8) | blue);
 
843
                                                        }
 
844
                                                }
 
845
                                                xPos = xEndPos;
 
846
                                        }
 
847
                                        yPos = yEndPos;
 
848
                                }
 
849
                                if (DEBUGIMAGES)
 
850
                                {
 
851
                                        for(int y=0; y<greekedCell.fadeImageHei; y++)
 
852
                                        {
 
853
                                                for(int x=0; x<greekedCell.fadeImageWid; x++)
 
854
                                                {
 
855
                                                        int valToSet = greekedCell.fadeImageColors[x+y*greekedCell.fadeImageWid];
 
856
                                                        topVD.offscreen.drawPoint(greekedCell.fadeOffsetX+x+1, greekedCell.fadeOffsetY+y+1, null, valToSet);
 
857
                                                }
 
858
                                                topVD.offscreen.drawPoint(greekedCell.fadeOffsetX, greekedCell.fadeOffsetY+y+1, null, 0);
 
859
                                                topVD.offscreen.drawPoint(greekedCell.fadeOffsetX+greekedCell.fadeImageWid+1, greekedCell.fadeOffsetY+y+1, null, 0);
 
860
                                        }
 
861
                                        for(int x=0; x<greekedCell.fadeImageWid; x++)
 
862
                                        {
 
863
                                                topVD.offscreen.drawPoint(greekedCell.fadeOffsetX+x, greekedCell.fadeOffsetY, null, 0);
 
864
                                                topVD.offscreen.drawPoint(greekedCell.fadeOffsetX+x, greekedCell.fadeOffsetY+greekedCell.fadeImageHei+1, null, 0);
 
865
                                        }
 
866
                                }
 
867
                                return;
 
868
                        }
 
869
                }
 
870
 
 
871
                // no greeked image: just use the greeked color
 
872
                for(int y=lY; y<=hY; y++)
 
873
                {
 
874
                        for(int x=lX; x<=hX; x++)
 
875
                                offscreen.drawPoint(x, y, null, col);
 
876
                }
 
877
        }
 
878
 
 
879
        /**
 
880
         * Method to determine whether a cell has tiny contents.
 
881
         * Recursively examines the cache of this and all subcells to see if the
 
882
         * maximum feature sizes are all below the global threshold "maxObjectSize".
 
883
         * @param cell the Cell in question.
 
884
         * @param vc the cached representation of the cell.
 
885
         * @param trans the Orientation of the cell.
 
886
         * @return true if the cell has all tiny contents.
 
887
         */
 
888
        private boolean isContentsTiny(Cell cell, VectorCache.VectorCell vc, Orientation trans, VarContext context)
 
889
                throws AbortRenderingException
 
890
        {
 
891
                if (vc.maxFeatureSize > maxObjectSize) return false;
 
892
                for(VectorCache.VectorSubCell vsc : vc.subCells)
 
893
                {
 
894
                        NodeInst ni = cell.getNodeById(vsc.n.nodeId);
 
895
                        VectorCache.VectorCell subVC = VectorCache.theCache.findVectorCell(vsc.subCellId, vc.orient.concatenate(vsc.n.orient));
 
896
                        if (ni.isExpanded() || fullInstantiate)
 
897
                        {
 
898
                                Orientation thisOrient = ni.getOrient();
 
899
                                Orientation recurseTrans = trans.concatenate(thisOrient);
 
900
                                VarContext subContext = context.push(ni);
 
901
                                Cell subCell = (Cell)ni.getProto();
 
902
                                VectorCache.VectorCell subVC_ = drawCell(subCell, recurseTrans, subContext);
 
903
                                assert subVC_ == subVC;
 
904
                                boolean subCellTiny = isContentsTiny(subCell, subVC, recurseTrans, subContext);
 
905
                                if (!subCellTiny) return false;
 
906
                                continue;
 
907
                        }
 
908
                        if (subVC.vcg.cellMinSize > maxObjectSize) return false;
 
909
                }
 
910
                return true;
 
911
        }
 
912
 
 
913
        private void makeGreekedImage(VectorCache.VectorCell subVC)
 
914
                throws AbortRenderingException
 
915
        {
 
916
                if (subVC.fadeImage) return;
 
917
                if (!User.isUseCellGreekingImages()) return;
 
918
 
 
919
                // determine size and scale of greeked cell image
 
920
                Rectangle2D cellBounds = subVC.vcg.bounds;
 
921
                Rectangle2D ownBounds = new Rectangle2D.Double(cellBounds.getMinX(), cellBounds.getMinY(), cellBounds.getWidth(), cellBounds.getHeight());
 
922
                AffineTransform trans = subVC.orient.rotateAbout(0, 0);
 
923
                DBMath.transformRect(ownBounds, trans);
 
924
                double greekScale = MAXGREEKSIZE / ownBounds.getHeight();
 
925
                if (ownBounds.getWidth() > ownBounds.getHeight())
 
926
                        greekScale = MAXGREEKSIZE / ownBounds.getWidth();
 
927
                int lX = (int)Math.floor(cellBounds.getMinX()*greekScale);
 
928
                int hX = (int)Math.ceil(cellBounds.getMaxX()*greekScale);
 
929
                int lY = (int)Math.floor(cellBounds.getMinY()*greekScale);
 
930
                int hY = (int)Math.ceil(cellBounds.getMaxY()*greekScale);
 
931
                if (hX <= lX) hX = lX + 1;
 
932
                int greekWid = hX - lX;
 
933
                if (hY <= lY) hY = lY + 1;
 
934
                int greekHei = hY - lY;
 
935
                Rectangle screenBounds = new Rectangle(lX, lY, greekWid, greekHei);
 
936
 
 
937
                // construct the offscreen buffers for the greeked cell image
 
938
                PixelDrawing offscreen = new PixelDrawing(greekScale, screenBounds);
 
939
                Point2D cellCtr = new Point2D.Double(ownBounds.getCenterX(), ownBounds.getCenterY());
 
940
                VectorDrawing subVD = new VectorDrawing();
 
941
 
 
942
                subVC.fadeOffsetX = debugXP;
 
943
                subVC.fadeOffsetY = debugYP;
 
944
                debugXP += MAXGREEKSIZE + 5;
 
945
                if (topVD != null)
 
946
                {
 
947
                        if (debugXP + MAXGREEKSIZE+2 >= topVD.offscreen.getSize().width)
 
948
                        {
 
949
                                debugXP = 0;
 
950
                                debugYP += MAXGREEKSIZE + 5;
 
951
                        }
 
952
                }
 
953
 
 
954
                // set rendering information for the greeked cell image
 
955
                subVD.offscreen = offscreen;
 
956
                subVD.screenLX = 0;   subVD.screenHX = greekWid;
 
957
                subVD.screenLY = 0;   subVD.screenHY = greekHei;
 
958
                subVD.szHalfWidth = greekWid / 2;
 
959
                subVD.szHalfHeight = greekHei / 2;
 
960
                subVD.maxObjectSize = 0;
 
961
                subVD.maxTextSize = 0;
 
962
                subVD.scale = (float)greekScale;
 
963
                subVD.scale_ = (float)(greekScale/DBMath.GRID);
 
964
                subVD.factorX = (float)(cellCtr.getX()*DBMath.GRID - subVD.szHalfWidth/subVD.scale_);
 
965
                subVD.factorY = (float)(cellCtr.getY()*DBMath.GRID + subVD.szHalfHeight/subVD.scale_);
 
966
                subVD.factorX_ = (int)subVD.factorX;
 
967
                subVD.factorY_ = (int)subVD.factorY;
 
968
                subVD.scale_int = (int)(subVD.scale_ * (1 << SCALE_SH));
 
969
                subVD.fullInstantiate = true;
 
970
                subVD.takingLongTime = true;
 
971
 
 
972
                // render the greeked cell
 
973
                subVD.offscreen.clearImage(null);
 
974
                subVD.render(subVC, 0, 0, VarContext.globalContext, -1);
 
975
                subVD.offscreen.composite(null);
 
976
 
 
977
                // remember the greeked cell image
 
978
                int[] img = offscreen.getOpaqueData();
 
979
                subVC.fadeImageWid = greekWid;
 
980
                subVC.fadeImageHei = greekHei;
 
981
                subVC.fadeImageColors = new int[subVC.fadeImageWid * subVC.fadeImageHei];
 
982
                int i = 0;
 
983
                for(int y=0; y<subVC.fadeImageHei; y++)
 
984
                {
 
985
                        for(int x=0; x<subVC.fadeImageWid; x++)
 
986
                        {
 
987
                                int value = img[i];
 
988
                                subVC.fadeImageColors[i++] = value & 0xFFFFFF;
 
989
                        }
 
990
                }
 
991
                subVC.fadeImage = true;
 
992
        }
 
993
 
 
994
        /**
 
995
         * Method to determine the "fade" color for a cached cell.
 
996
         * Fading is done when the cell is too tiny to draw (or all of its contents are too tiny).
 
997
         * Instead of drawing the cell contents, the entire cell is painted with the "fade" color.
 
998
         * @param vc the cached cell.
 
999
         * @return the fade color (an integer with red/green/blue).
 
1000
         */
 
1001
        private int getFadeColor(VectorCache.VectorCell vc, VarContext context)
 
1002
                throws AbortRenderingException
 
1003
        {
 
1004
                if (vc.hasFadeColor) return vc.fadeColor;
 
1005
 
 
1006
                // examine all shapes
 
1007
                Map<Layer,MutableDouble> layerAreas = new HashMap<Layer,MutableDouble>();
 
1008
                gatherContents(vc, layerAreas, context);
 
1009
 
 
1010
                // now compute the color
 
1011
                Set<Layer> keys = layerAreas.keySet();
 
1012
                double totalArea = 0;
 
1013
                for(Layer layer : keys)
 
1014
                {
 
1015
                        MutableDouble md = layerAreas.get(layer);
 
1016
                        totalArea += md.doubleValue();
 
1017
                }
 
1018
                double r = 0, g = 0, b = 0;
 
1019
                if (totalArea != 0)
 
1020
                {
 
1021
                        for(Layer layer : keys)
 
1022
                        {
 
1023
                                MutableDouble md = layerAreas.get(layer);
 
1024
                                double portion = md.doubleValue() / totalArea;
 
1025
                                EGraphics desc = layer.getGraphics();
 
1026
                                Color col = desc.getColor();
 
1027
                                r += col.getRed() * portion;
 
1028
                                g += col.getGreen() * portion;
 
1029
                                b += col.getBlue() * portion;
 
1030
                        }
 
1031
                }
 
1032
                if (r < 0) r = 0;   if (r > 255) r = 255;
 
1033
                if (g < 0) g = 0;   if (g > 255) g = 255;
 
1034
                if (b < 0) b = 0;   if (b > 255) b = 255;
 
1035
                vc.fadeColor = (((int)r) << 16) | (((int)g) << 8) | (int)b;
 
1036
                vc.hasFadeColor = true;
 
1037
                return vc.fadeColor;
 
1038
        }
 
1039
 
 
1040
        /**
 
1041
         * Helper method to recursively examine a cached cell and its subcells and compute
 
1042
         * the coverage of each layer.
 
1043
         * @param vc the cached cell to examine.
 
1044
         * @param layerAreas a HashMap of all layers and the areas they cover.
 
1045
         */
 
1046
        private void gatherContents(VectorCache.VectorCell vc, Map<Layer,MutableDouble> layerAreas, VarContext context)
 
1047
                throws AbortRenderingException
 
1048
        {
 
1049
                for(VectorCache.VectorBase vb : vc.filledShapes)
 
1050
                {
 
1051
                        Layer layer = vb.layer;
 
1052
                        if (layer == null) continue;
 
1053
                        Layer.Function fun = layer.getFunction();
 
1054
                        if (fun.isImplant() || fun.isSubstrate()) continue;
 
1055
 
 
1056
                        // handle each shape
 
1057
                        double area = 0;
 
1058
                        if (vb instanceof VectorCache.VectorManhattan)
 
1059
                        {
 
1060
                                VectorCache.VectorManhattan vm = (VectorCache.VectorManhattan)vb;
 
1061
                                for (int i = 0; i < vm.coords.length; i += 4) {
 
1062
                                        double c1X = vm.coords[i];
 
1063
                                        double c1Y = vm.coords[i + 1];
 
1064
                                        double c2X = vm.coords[i + 2];
 
1065
                                        double c2Y = vm.coords[i + 3];
 
1066
                                        area += (c1X-c2X) * (c1Y-c2Y);
 
1067
                                }
 
1068
                        } else if (vb instanceof VectorCache.VectorPolygon)
 
1069
                        {
 
1070
                                VectorCache.VectorPolygon vp = (VectorCache.VectorPolygon)vb;
 
1071
                                area = GenMath.getAreaOfPoints(vp.points);
 
1072
                        } else if (vb instanceof VectorCache.VectorCircle)
 
1073
                        {
 
1074
                                VectorCache.VectorCircle vci = (VectorCache.VectorCircle)vb;
 
1075
                                double radius = new Point2D.Double(vci.cX, vci.cY).distance(new Point2D.Double(vci.eX, vci.eY));
 
1076
                                area = radius * radius * Math.PI;
 
1077
                        }
 
1078
                        if (area == 0) continue;
 
1079
                        MutableDouble md = layerAreas.get(layer);
 
1080
                        if (md == null)
 
1081
                        {
 
1082
                                md = new MutableDouble(0);
 
1083
                                layerAreas.put(layer, md);
 
1084
                        }
 
1085
                        md.setValue(md.doubleValue() + area);
 
1086
                }
 
1087
 
 
1088
                Cell cell = VectorCache.theCache.database.getCell(vc.vcg.cellId);
 
1089
                for(VectorCache.VectorSubCell vsc : vc.subCells)
 
1090
                {
 
1091
                        VectorCache.VectorCellGroup vcg = VectorCache.theCache.findCellGroup(vsc.subCellId);
 
1092
                        VectorCache.VectorCell subVC = vcg.getAnyCell();
 
1093
                        NodeInst ni = cell.getNodeById(vsc.n.nodeId);
 
1094
                        VarContext subContext = context.push(ni);
 
1095
                        if (subVC == null)
 
1096
                                subVC = drawCell((Cell)ni.getProto(), Orientation.IDENT, subContext);
 
1097
                        gatherContents(subVC, layerAreas, subContext);
 
1098
                }
 
1099
        }
 
1100
 
 
1101
        // ************************************* CACHE CREATION *************************************
 
1102
 
 
1103
        /**
 
1104
         * Method to cache the contents of a cell.
 
1105
         * @param cell the Cell to cache
 
1106
         * @param prevTrans the orientation of the cell (just a rotation, no offsets here).
 
1107
         * @return a cached cell object for the given Cell.
 
1108
         */
 
1109
        private VectorCache.VectorCell drawCell(Cell cell, Orientation prevTrans, VarContext context)
 
1110
                throws AbortRenderingException
 
1111
        {
 
1112
                // caching the cell: check for abort and delay reporting
 
1113
                if (stopRendering) throw new AbortRenderingException();
 
1114
                if (!takingLongTime)
 
1115
                {
 
1116
                        long currentTime = System.currentTimeMillis();
 
1117
                        if (currentTime - startTime > 1000)
 
1118
                        {
 
1119
                                System.out.print("Display caching, please wait...");
 
1120
                                TopLevel.setBusyCursor(true);
 
1121
                                takingLongTime = true;
 
1122
                        }
 
1123
                }
 
1124
 
 
1125
                return VectorCache.theCache.drawCell(cell.getId(), prevTrans, context, scale);
 
1126
        }
 
1127
}