~ubuntu-branches/ubuntu/jaunty/electric/jaunty

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Onkar Shinde
  • Date: 2009-01-08 02:05:08 UTC
  • mfrom: (1.1.2 upstream) (3.1.4 sid)
  • Revision ID: james.westby@ubuntu.com-20090108020508-0h3li7zt9mu5gf0i
Tags: 8.08-1
New upstream version.

Show diffs side-by-side

added added

removed removed

Lines of Context:
74
74
import java.util.HashSet;
75
75
import java.util.Iterator;
76
76
import java.util.List;
 
77
import java.util.Map;
 
78
import java.util.Set;
77
79
 
78
80
import javax.swing.SwingUtilities;
79
81
 
179
181
 *   When compositing at the top level, however, the POLs are converted back to patterns, so that they line-up.</LI>
180
182
 *   </UL>
181
183
 * </UL>
182
 
 * 
 
184
 *
183
185
 */
184
186
public class PixelDrawing
185
187
{
206
208
    private static class ExpandedCellKey {
207
209
        private Cell cell;
208
210
        private Orientation orient;
209
 
     
 
211
 
210
212
        private ExpandedCellKey(Cell cell, Orientation orient) {
211
213
            this.cell = cell;
212
214
            this.orient = orient;
213
215
        }
214
 
        
 
216
 
215
217
        @Override
216
218
        public boolean equals(Object obj) {
217
219
            if (obj instanceof ExpandedCellKey) {
220
222
            }
221
223
            return false;
222
224
        }
223
 
        
 
225
 
224
226
        @Override
225
227
        public int hashCode() { return cell.hashCode()^orient.hashCode(); }
226
228
    }
227
 
    
 
229
 
228
230
        /**
229
231
         * This class holds information about expanded cell instances.
230
232
         * For efficiency, Electric remembers the bits in an expanded cell instance
245
247
                        offscreen = null;
246
248
                }
247
249
        }
248
 
    
 
250
 
249
251
        /** the size of the EditWindow */                                               private final Dimension sz;
250
252
    /** the scale of the EditWindow */                      private double scale;
251
253
    /** the VarContext of the EditWindow */                 private VarContext varContext = VarContext.globalContext;
252
254
    /** the X origin of the cell in display coordinates. */ private double originX;
253
255
    /** the Y origin of the cell in display coordinates. */ private double originY;
254
256
        /** 0: color display, 1: color printing, 2: B&W printing */     private int nowPrinting;
255
 
    
 
257
 
256
258
    /** the area of the cell to draw, in DB units */        private Rectangle2D drawBounds;
257
259
        /** whether any layers are highlighted/dimmed */                boolean highlightingLayers;
258
260
        /** true if the last display was a full-instantiate */  private boolean lastFullInstantiate = false;
283
285
        private byte[][] layerBitMap;
284
286
        PatternedOpaqueLayer(int height, int numBytesPerRow) { layerBitMap = new byte[height][numBytesPerRow]; }
285
287
    }
286
 
        /** the map from layers to Patterned Opaque bitmaps */  private HashMap<Layer,PatternedOpaqueLayer> patternedOpaqueLayers = new HashMap<Layer,PatternedOpaqueLayer>();
 
288
        /** the map from layers to Patterned Opaque bitmaps */  private Map<Layer,PatternedOpaqueLayer> patternedOpaqueLayers = new HashMap<Layer,PatternedOpaqueLayer>();
287
289
        /** the top-level window being rendered */                              private boolean renderedWindow;
288
290
 
289
291
        /** whether to occasionally update the display. */              private boolean periodicRefresh;
293
295
 
294
296
        /** the size of the top-level EditWindow */                             private static Dimension topSz;
295
297
        /** the last Technology that had transparent layers */  private static Technology techWithLayers = null;
296
 
        /** list of cell expansions. */                                                 private static HashMap<ExpandedCellKey,ExpandedCellInfo> expandedCells = null;
297
 
    /** Set of changed cells. */                            private static final HashSet<CellId> changedCells = new HashSet<CellId>();
 
298
        /** list of cell expansions. */                                                 private static Map<ExpandedCellKey,ExpandedCellInfo> expandedCells = null;
 
299
    /** Set of changed cells. */                            private static final Set<CellId> changedCells = new HashSet<CellId>();
298
300
        /** scale of cell expansions. */                                                private static double expandedScale = 0;
299
301
        /** number of extra cells to render this time */                private static int numberToReconcile;
300
302
        /** zero rectangle */                                                                   private static final Rectangle2D CENTERRECT = new Rectangle2D.Double(0, 0, 0, 0);
309
311
                new int[] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0});
310
312
 
311
313
    private int clipLX, clipHX, clipLY, clipHY;
312
 
    
 
314
 
313
315
    private final EditWindow0 dummyWnd = new EditWindow0() {
314
316
        public VarContext getVarContext() { return varContext; }
315
 
        
 
317
 
316
318
        public double getScale() { return scale; }
 
319
 
 
320
        public double getGlobalTextScale() { return wnd.getGlobalTextScale(); }
317
321
    };
318
322
 
319
323
    static class Drawing extends AbstractDrawing {
320
324
        private final VectorDrawing vd = new VectorDrawing();
321
325
        private volatile PixelDrawing offscreen;
322
 
        
 
326
 
323
327
        Drawing(EditWindow wnd) {
324
328
            super(wnd);
325
329
        }
326
 
        
 
330
 
327
331
        @Override
328
332
        public boolean paintComponent(Graphics2D g, Dimension sz) {
329
333
            assert SwingUtilities.isEventDispatchThread();
331
335
            PixelDrawing offscreen = this.offscreen;
332
336
            if (offscreen == null || !offscreen.getSize().equals(sz))
333
337
                return false;
334
 
            
 
338
 
335
339
            // show the image
336
340
            g.drawImage(offscreen.getBufferedImage(), 0, 0, wnd);
337
341
            return true;
338
342
        }
339
 
        
 
343
 
340
344
        @Override
341
345
        public void render(Dimension sz, WindowFrame.DisplayAttributes da, boolean fullInstantiate, Rectangle2D bounds) {
342
346
            PixelDrawing offscreen_ = this.offscreen;
345
349
            this.da = da;
346
350
            offscreen_.drawImage(this, fullInstantiate, bounds);
347
351
        }
348
 
        
 
352
 
349
353
        @Override
350
354
        public void abortRendering() {
351
355
            if (User.getDisplayAlgorithm() > 0)
352
356
                vd.abortRendering();
353
357
        }
354
358
    }
355
 
    
 
359
 
356
360
    // ************************************* TOP LEVEL *************************************
357
361
 
358
362
        /**
366
370
        clipHX = sz.width - 1;
367
371
        clipLY = 0;
368
372
        clipHY = sz.height - 1;
369
 
        
 
373
 
370
374
                // allocate pointer to the opaque image
371
375
                img = new BufferedImage(sz.width, sz.height, BufferedImage.TYPE_INT_RGB);
372
376
                WritableRaster raster = img.getRaster();
376
380
                numBytesPerRow = (sz.width + 7) / 8;
377
381
                renderedWindow = true;
378
382
        }
379
 
    
 
383
 
380
384
    public PixelDrawing(double scale, Rectangle screenBounds) {
381
385
        this.scale = scale;
382
 
        
 
386
 
383
387
        this.originX = -screenBounds.x;
384
388
        this.originY = screenBounds.y + screenBounds.height;
385
389
        this.sz = new Dimension(screenBounds.width, screenBounds.height);
387
391
        clipHX = sz.width - 1;
388
392
        clipLY = 0;
389
393
        clipHY = sz.height - 1;
390
 
        
 
394
 
391
395
                // allocate pointer to the opaque image
392
396
        img = null;
393
397
                total = sz.height * sz.width;
394
398
        opaqueData = new int[total];
395
399
                numBytesPerRow = (sz.width + 7) / 8;
396
 
        
 
400
 
397
401
                // initialize the data
398
402
                clearImage(null);
399
403
    }
400
 
    
 
404
 
401
405
    void initOrigin(double scale, double offx, double offy) {
402
406
        this.scale = scale;
403
407
        this.originX = sz.width/2 - offx*scale;
408
412
                clearImage(null);
409
413
        initOrigin(scale, 0, 0);
410
414
    }
411
 
    
 
415
 
412
416
    /**
413
417
     * Method to set the printing mode used for all drawing.
414
418
     * @param mode the printing mode:  0=color display (default), 1=color printing, 2=B&W printing.
437
441
         * @return an RGB array for this edit window.
438
442
         */
439
443
    int[] getOpaqueData() { return opaqueData; }
440
 
    
 
444
 
441
445
        /**
442
446
         * Method for obtaining the size of the offscreen bitmap.
443
447
         * @return the size of the offscreen bitmap.
485
489
        double width = sz.width/scale;
486
490
        double height = sz.height/scale;
487
491
        drawBounds = new Rectangle2D.Double(drawing.da.offX - width/2, drawing.da.offY - height/2, width, height);
488
 
//        drawBounds = wnd.getDisplayedBounds();
489
492
 
490
493
                // set colors to use
491
494
        textColor = new Color(User.getColor(User.ColorPrefType.TEXT));
492
495
                textGraphics.setColor(textColor);
493
496
                gridGraphics.setColor(new Color(User.getColor(User.ColorPrefType.GRID)));
494
497
                instanceGraphics.setColor(new Color(User.getColor(User.ColorPrefType.INSTANCE)));
495
 
                
 
498
 
496
499
                // initialize the cache of expanded cell displays
497
500
                if (expandedScale != drawing.da.scale)
498
501
                {
541
544
                objectCount = 0;
542
545
                lastRefreshTime = System.currentTimeMillis();
543
546
 
544
 
        HashSet<CellId> changedCellsCopy;
 
547
        Set<CellId> changedCellsCopy;
545
548
        synchronized (changedCells) {
546
549
            changedCellsCopy = new HashSet<CellId>(changedCells);
547
550
            changedCells.clear();
599
602
        {
600
603
        clearSubCellCache();
601
604
        lastFullInstantiate = false;
602
 
        expandedScale = this.scale = scale; 
 
605
        expandedScale = this.scale = scale;
603
606
 
604
607
                // set colors to use
605
608
        textColor = new Color(User.getColor(User.ColorPrefType.TEXT));
606
609
                textGraphics.setColor(textColor);
607
610
                gridGraphics.setColor(new Color(User.getColor(User.ColorPrefType.GRID)));
608
611
                instanceGraphics.setColor(new Color(User.getColor(User.ColorPrefType.INSTANCE)));
609
 
                
 
612
 
610
613
        if (wnd != null) varContext = wnd.getVarContext();
611
614
        initOrigin(scale, offset.getX(), offset.getY());
612
615
                canDrawText = expandedScale > 1;
635
638
        clipHY = sz.height - 1;
636
639
                clearImage(null);
637
640
 
638
 
        HashSet<CellId> changedCellsCopy;
 
641
        Set<CellId> changedCellsCopy;
639
642
        synchronized (changedCells) {
640
643
            changedCellsCopy = new HashSet<CellId>(changedCells);
641
644
            changedCells.clear();
829
832
                                {
830
833
                                        int index = baseIndex + x;
831
834
                                        int pixelValue = opaqueData[index];
832
 
                                
 
835
 
833
836
                                        // the value of Alpha starts at 0xFF, which means "background"
834
837
                                        // opaque drawing typically sets it to 0, which means "filled"
835
838
                                        // Text drawing can antialias by setting the edge values in the range 0-254
973
976
                                databaseToScreen(tmpPt.getX(), tmpPt.getY(), tempPt1);
974
977
                                int x = tempPt1.x;
975
978
                                int y = tempPt1.y;
976
 
                                if (x < 0 || x > sz.width) continue;
977
 
                                if (y < 0 || y > sz.height) continue;
 
979
                                if (x < 0 || x >= sz.width) continue;
 
980
                                if (y < 0 || y >= sz.height) continue;
978
981
 
979
982
                                double boldValueX = j;
980
983
                                if (j < 0) boldValueX -= boldSpacingThreshX/2; else
1035
1038
                Point2D high = new Point2D.Double();
1036
1039
        screenToDatabase(sz.width-1, sz.height-1, high);
1037
1040
        intoCellTransform.transform(high, high);
1038
 
        
 
1041
 
1039
1042
                double lowX = Math.min(low.getX(), high.getX());
1040
1043
                double lowY = Math.min(low.getY(), high.getY());
1041
1044
                double sizeX = Math.abs(high.getX()-low.getX());
1078
1081
            }
1079
1082
        }
1080
1083
    }
1081
 
    
 
1084
 
1082
1085
        // ************************************* HIERARCHY TRAVERSAL *************************************
1083
1086
 
1084
1087
        /**
1243
1246
                                double ctrY = ctr.getY();
1244
1247
                if (renderedWindow && drawBounds != null) {
1245
1248
                    Rectangle2D databaseBounds = drawBounds;
1246
 
//                    Rectangle2D databaseBounds = wnd.getDisplayedBounds();
1247
1249
                    if (ctrX + halfWidth < databaseBounds.getMinX()) return;
1248
1250
                    if (ctrX - halfWidth > databaseBounds.getMaxX()) return;
1249
1251
                    if (ctrY + halfWidth < databaseBounds.getMinY()) return;
1250
1252
                    if (ctrY - halfWidth > databaseBounds.getMaxY()) return;
1251
1253
                }
1252
 
        
 
1254
 
1253
1255
                                PrimitiveNode prim = (PrimitiveNode)np;
1254
1256
                                totalPrims++;
1255
1257
                                if (!prim.isCanBeZeroSize() && halfWidth < halfMaxObjectSize && !forceVisible)
1341
1343
                                if (arcSize < maxObjectSize)
1342
1344
                                {
1343
1345
                                        linedArcs++;
1344
 
        
 
1346
 
1345
1347
                                        // draw a tiny arc by setting a single dot from each layer
1346
1348
                                        Point2D headEnd = new Point2D.Double(ai.getHeadLocation().getX(), ai.getHeadLocation().getY());
1347
1349
                                        trans.transform(headEnd, headEnd);
1574
1576
                        expandedCellCount.offscreen.drawCell(subCell, null, fullInstantiate, orient, rotTrans, topCell);
1575
1577
                        offscreensCreated++;
1576
1578
            offscreenPixelsCreated += expandedCellCount.offscreen.total;
1577
 
            
 
1579
 
1578
1580
                }
1579
1581
 
1580
1582
                // copy out of the offscreen buffer into the main buffer
1684
1686
        }
1685
1687
        }
1686
1688
 
1687
 
        private static void forceRedraw(HashSet<CellId> changedCells)
 
1689
        private static void forceRedraw(Set<CellId> changedCells)
1688
1690
        {
1689
1691
                // if there is no global for remembering cached cells, do not cache
1690
1692
                if (expandedCells == null) return;
1724
1726
            if (destY < 0 || destY >= sz.height) continue;
1725
1727
            int srcBase = srcY * dim.width;
1726
1728
            int destBase = destY * sz.width;
1727
 
            
 
1729
 
1728
1730
            for (int srcX = minSrcX; srcX <= maxSrcX; srcX++) {
1729
1731
                int destX = srcX + cornerX;
1730
1732
                assert destX >= clipLX && destX <= clipHX;
1740
1742
            byte [][] srcLayerBitMap = srcOffscreen.layerBitMaps[i];
1741
1743
            if (srcLayerBitMap == null) continue;
1742
1744
            byte [][] destLayerBitMap = getLayerBitMap(i);
1743
 
            
 
1745
 
1744
1746
            for (int srcY = minSrcY; srcY <= maxSrcY; srcY++) {
1745
1747
                int destY = srcY + cornerY;
1746
1748
                assert destY >= clipLY && destY <= clipHY;
1747
1749
                if (destY < 0 || destY >= sz.height) continue;
1748
1750
                byte [] srcRow = srcLayerBitMap[srcY];
1749
1751
                byte [] destRow = destLayerBitMap[destY];
1750
 
                
 
1752
 
1751
1753
                for (int srcX = minSrcX; srcX <= maxSrcX; srcX++) {
1752
1754
                    int destX = srcX + cornerX;
1753
1755
                    assert destX >= clipLX && destX <= clipHX;
1754
1756
                    if (destX < 0 || destX >= sz.width) continue;
1755
 
                    
 
1757
 
1756
1758
                    if ((srcRow[srcX>>3] & (1<<(srcX&7))) != 0)
1757
1759
                        destRow[destX>>3] |= (1 << (destX&7));
1758
1760
                }
1826
1828
        }
1827
1829
 
1828
1830
        // ************************************* RENDERING POLY SHAPES *************************************
1829
 
    
 
1831
 
1830
1832
    /**
1831
1833
     * A class representing a rectangular array of pixels. References
1832
1834
     * to pixels outside of the bounding rectangle may result in an
1842
1844
         * @param lX left X coordinate
1843
1845
         * @param hX right X coordiante
1844
1846
         * @param lY top Y coordinate
1845
 
         * @param hY bottom Y coordiante 
 
1847
         * @param hY bottom Y coordiante
1846
1848
         */
1847
1849
        public void fillBox(int lX, int hX, int lY, int hY);
1848
 
        
 
1850
 
1849
1851
        /**
1850
1852
         * Method to fill a horizontal scanline [lX,hX] x [y].
1851
1853
         * Both low and high coordiantes are inclusive.
1855
1857
         * @param hX right X coordiante
1856
1858
         */
1857
1859
        public void fillHorLine(int y, int lX, int hX);
1858
 
        
 
1860
 
1859
1861
        /**
1860
1862
         * Method to fill a verticaltal scanline [x] x [lY,hY].
1861
1863
         * Both low and bigh coordiantes are inclusive.
1865
1867
         * @param hY bottom Y coordiante
1866
1868
         */
1867
1869
        public void fillVerLine(int x, int lY, int hY);
1868
 
        
 
1870
 
1869
1871
        /**
1870
1872
         * Method to fill a point.
1871
1873
         * Filling might be patterned.
1873
1875
         * @param y Y coordinate
1874
1876
         */
1875
1877
        public void fillPoint(int x, int y);
1876
 
        
 
1878
 
1877
1879
        /**
1878
1880
         * Method to draw a horizontal line [lX,hX] x [y].
1879
1881
         * Both low and high coordiantes are inclusive.
1883
1885
         * @param hX right X coordiante
1884
1886
         */
1885
1887
        public void drawHorLine(int y, int lX, int hX);
1886
 
        
 
1888
 
1887
1889
        /**
1888
1890
         * Method to draw a vertical line [x] x [lY,hY].
1889
1891
         * Both low and high coordiantes are inclusive.
1893
1895
         * @param hY bottom Y coordiante
1894
1896
         */
1895
1897
        public void drawVerLine(int x, int lY, int hY);
1896
 
        
 
1898
 
1897
1899
        /**
1898
1900
         * Method to draw a point.
1899
1901
         * @param x X coordinate
1900
1902
         * @param y Y coordinate
1901
1903
         */
1902
1904
        public void drawPoint(int x, int y);
1903
 
        
 
1905
 
1904
1906
        /**
1905
1907
         * Method to return Electric Outline style for this ERaster.
1906
1908
         * @return Electric Outline style for this ERaster or null for no outline.
1907
1909
         */
1908
1910
        public EGraphics.Outline getOutline();
1909
1911
    }
1910
 
    
1911
 
    
 
1912
 
 
1913
 
1912
1914
        // ************************************* RENDERING POLY SHAPES *************************************
1913
1915
 
1914
1916
        /**
1971
1973
        layerBitMaps[layerNum] = layerBitMap;
1972
1974
        numLayerBitMapsCreated++;
1973
1975
        return layerBitMap;
1974
 
        
 
1976
 
1975
1977
    }
1976
 
    
 
1978
 
1977
1979
        /**
1978
1980
         * Render a Poly to the offscreen buffer.
1979
1981
         */
2491
2493
        tempPt3.y = y1;
2492
2494
        tempPt4.x = x2;
2493
2495
        tempPt4.y = y2;
2494
 
        
 
2496
 
2495
2497
                // first clip the line
2496
2498
                if (GenMath.clipLine(tempPt3, tempPt4, 0, sz.width-1, 0, sz.height-1)) return;
2497
2499
 
2904
2906
                                Color full = EGraphics.getColorFromIndex(colorIndex);
2905
2907
                                if (full != null) col = full.getRGB() & 0xFFFFFF;
2906
2908
                        }
2907
 
                        double dSize = descript.getTrueSize(scale);
 
2909
                        double dSize = descript.getTrueSize(scale, wnd);
2908
2910
                        size = (int)dSize;
2909
2911
                        if (size < MINIMUMTEXTSIZE)
2910
2912
                        {
3655
3657
                                pattern = desc.getPattern();
3656
3658
                                if (desc.getOutlined() != EGraphics.Outline.NOPAT)
3657
3659
                                {
3658
 
                                        drawCircle(center, edge, layerBitMap, desc, dimmed);                    
 
3660
                                        drawCircle(center, edge, layerBitMap, desc, dimmed);
3659
3661
                                }
3660
3662
                        }
3661
3663
                }
3979
3981
                result.x = (int)(scrX >= 0 ? scrX + 0.5 : scrX - 0.5);
3980
3982
                result.y = (int)(scrY >= 0 ? scrY + 0.5 : scrY - 0.5);
3981
3983
    }
3982
 
    
 
3984
 
3983
3985
    private void screenToDatabase(int x, int y, Point2D result) {
3984
3986
        result.setLocation((x - originX)/scale, (originY - y)/scale);
3985
3987
    }
3986
 
    
 
3988
 
3987
3989
        /**
3988
3990
         * Method to convert a database rectangle to screen coordinates.
3989
3991
         * @param db the rectangle (in database units).