cwindow.java
来自「This is a resource based on j2me embedde」· Java 代码 · 共 745 行 · 第 1/2 页
JAVA
745 行
* @return element of the window layers list that contains swept * layer, it can be used for further layer processing */ CLayerElement sweepLayer(CLayer layer) { if (layer != null) { if (CGraphicsQ.DEBUG) { System.err.println("Sweep Layer: " + layer); } synchronized (layers) { CLayerElement le = layers.find(layer); if (le != null) { // IMPL NOTE: when a layer gets removed (or has its setVisible(false)) // called, the parent window must loop through all the other // layers and mark them as dirty if they intersect with the // layer being removed (or having its visibility changed). layer.addDirtyRegion(); sweepAndMarkDirtyLayer(le, true); return le; } } } return null; } /** * Propagate dirty region of the layer to other layers in the stack. * The method should be called for dirty layers only. * The dirty layer can be invisible in the case it has been * hidden since the previous paint. * * IMPL_NOTE: The layer been removed or set to invisible state since * the previous paint is considered as "hidden", thus it should be * entirely dirty and must affect other visible layers accordingly. * * @param le dirty layer element to be propagated to other layers * @param hidden indicates whether the dirty layer has been hidden * since the previous repaint * @return the highest layer element above le with modified dirty * region, or null if none */ private CLayerElement sweepAndMarkDirtyLayer( CLayerElement le, boolean hidden) { if (CGraphicsQ.DEBUG) { System.err.println("Sweep and mark dirty layer: " + le.getLayer()); } CLayer l2; CLayerElement res = null; CLayer l = le.getLayer(); // Prepare absolute dirty region coordinates of layer l int dx = l.bounds[X]; int dy = l.bounds[Y]; int dh, dw; if (l.isEmptyDirtyRegions()) { dw = l.bounds[W]; dh = l.bounds[H]; } else { dx += l.dirtyBounds[X]; dy += l.dirtyBounds[Y]; dw = l.dirtyBounds[W]; dh = l.dirtyBounds[H]; } // Sweep dirty region to upper layers for (CLayerElement le2 = le.getUpper(); le2 != null; le2 = le2.getUpper()) { l2 = le2.getLayer(); if (l2.visible) { if (l2.addDirtyRegion( dx-l2.bounds[X], dy-l2.bounds[Y], dw, dh)) { // Remember the highest changed layer res = le2; } } } // Sweep non-opaque dirty region to undelying layers if (!l.opaque || hidden) { for (CLayerElement le2 = le.getLower(); le2 != null; le2 = le2.getLower()) { l2 = le2.getLayer(); if (l2.visible) { l2.addDirtyRegion( dx-l2.bounds[X], dy-l2.bounds[Y], dw, dh); } } // A newly hidden layer should be dirty only for the first // succeeded paint, it should be cleaned as soon as underlying // layers are properly marked as dirty. if (hidden) { l.cleanDirty(); } } return res; } // Heuristic Explanation: Any layer that needs painting also // requires all layers below and above that region to be painted. // This is required because layers may be transparent or even // partially translucent - thus they require that all layers beneath // and above them be repainted as well. // To accomplish this we loop through the stack of layers from the top // most to the bottom most. If a layer is "dirty" (has its dirty bit // set), we find all layers that intersect with the dirty region and // we mark that layer to be painted as well. If that layer is already // marked to be painted and has its own dirty region, we union // the existing region with the new region. If that layer does // not have a dirty region, we simply set a new one. In the case a // dirty region is modified for a higher layer been processed already // we need to restart the loop from the modified layer. // After doing this initial iteration, all layers will now be // marked dirty where appropriate and have their individual dirty // regions set. We then make another iteration from the bottom // most layer to the top, painting the dirty region of each layer. /** * First Pass: We do sweep and mark of all layers requiring a repaint, * the areas behind a visible opaque layers need no repaint */ private void sweepAndMarkLayers() { if (CGraphicsQ.DEBUG) { System.err.println("[Sweep and mark layers]"); } CLayer l; CLayerElement changed; CLayerElement le = layers.getTop(); while (le != null) { l = le.getLayer(); if (l.visible && l.opaque) { cleanLowerDirtyRegions(le); } // The dirty layer can be invisible, that means it // has been hidden since the previous paint. if (l.isDirty()) { // In the case higher layer was changed we need to // restart all the algorithm from the changed layer changed = sweepAndMarkDirtyLayer(le, !l.visible); if (changed != null) { if (CGraphicsQ.DEBUG) { System.err.println("Restart sweep and mark: " + changed.getLayer()); } le = changed; changed = null; continue; } } // Go to next lower layer le = le.getLower(); } } /** * Copy dirty layer references to array for further painting. * The copying is needed to not keep lock on layers list when * layers painting will happen. Dirty states of the layers are * cleaned after the copying. Layers painting can change layers * state again, but it will be served on next repaint only. */ private void copyAndCleanDirtyLayers() { if (CGraphicsQ.DEBUG) { System.err.println("[Copy dirty layers]"); } CLayer l; dirtyCount = 0; int layersCount = layers.size(); // Heuristics to increase array for copied dirty layers if (layersCount > dirtyMaxCount) { dirtyMaxCount += layersCount; dirtyLayers = new CLayer[dirtyMaxCount]; } // Copy dirty layer references and reset dirty layer states for (CLayerElement le = layers.getBottom(); le != null; le = le.getUpper()) { l = le.getLayer(); if (l.visible && l.isDirty()) { l.copyAndCleanDirtyState(); dirtyLayers[dirtyCount++] = l; } else { // !(visible && dirty) if (CGraphicsQ.DEBUG) { System.err.println("Skip Layer: " + l); } } // if } // for } /** * Second Pass: We sweep through the layers from the bottom to * the top and paint each one that is marked as dirty * * Note, that the painting for copied layers is done here to * not hold the layers lock during the painting. * * @param g The graphics object to use to paint this window. * @param refreshQ The custom queue which holds the set of refresh * regions needing to be blitted to the screen */ private void paintLayers(Graphics g, CGraphicsQ refreshQ) { if (CGraphicsQ.DEBUG) { System.err.println("[Paint dirty layers]"); } for (int i = 0; i < dirtyCount; i++) { CLayer l = dirtyLayers[i]; // Prepare relative dirty region coordinates // of the current layer int dx = l.dirtyBoundsCopy[X]; int dy = l.dirtyBoundsCopy[Y]; int dw = l.dirtyBoundsCopy[W]; int dh = l.dirtyBoundsCopy[H]; // Before we call into the layer to paint, we // translate the graphics context into the layer's // coordinate space g.translate(l.boundsCopy[X], l.boundsCopy[Y]); if (CGraphicsQ.DEBUG) { System.err.println("Painting Layer: " + l); System.err.println("\tClip: " + dx + ", " + dy + ", " + dw + ", " + dh); } // Clip the graphics to only contain the dirty region of // the layer (if the dirty region isn't set, clip to the // whole layer contents). g.clipRect(dx, dy, dw, dh); refreshQ.queueRefresh( l.boundsCopy[X] + dx, l.boundsCopy[Y] + dy, dw, dh); l.paint(g); // We restore our graphics context to prepare // for the next layer g.translate(-g.getTranslateX(), -g.getTranslateY()); g.translate(tranX, tranY); // We reset our clip to this window's bounds again. g.setClip(bounds[X], bounds[Y], bounds[W], bounds[H]); g.setFont(font); g.setColor(color); } // for } /** * Sets all visible layers to dirty state. * The method is needed on system events like screen rotation, * when generic layers system is not capabel to properly analyze * layers changes, e.g. of move/resize kind. It could be fixed in * the future and this method will be out of use. */ public void setAllDirty() { synchronized(layers) { CLayer l; for (CLayerElement le = layers.getBottom(); le != null; le = le.getUpper()) { l = le.getLayer(); if (l.visible) { l.addDirtyRegion(); } // if } // for } // synchronized } /** * Paint this window. This method should not generally be overridden by * subclasses. This method carefully stores the clip, translation, and * color before calling into subclasses. The graphics context should be * translated such that it is in this window's coordinate space (0,0 is * the top left corner of this window). * * @param g The graphics object to use to paint this window. * @param refreshQ The custom queue which holds the set of refresh * regions needing to be blitted to the screen */ public void paint(Graphics g, CGraphicsQ refreshQ) { // We reset our dirty flag first. Any layers that become // dirty in the duration of this method will then cause it // to toggle back to true for the subsequent pass. // IMPL NOTE: when layers start to do complex animation, there will // likely need to be better atomic handling of the dirty state, // and layers becoming dirty and getting painted this.dirty = false; // Store the clip, translate, font, color cX = g.getClipX(); cY = g.getClipY(); cW = g.getClipWidth(); cH = g.getClipHeight(); tranX = g.getTranslateX(); tranY = g.getTranslateY(); font = g.getFont(); color = g.getColor(); // We set the basic clip to the size of this window g.setClip(bounds[X], bounds[Y], bounds[W], bounds[H]); synchronized (layers) { sweepAndMarkLayers(); copyAndCleanDirtyLayers(); } paintLayers(g, refreshQ); // We restore the original clip. The original font, color, etc. // have already been restored g.setClip(cX, cY, cW, cH); } /** * Establish a background. This method will evaluate the parameters * and create a background which is appropriate. If the image is non-null, * the image will be used to create the background. If the image is null, * the values for the colors will be used and the background will be * painted in fill color instead. If the image is null, and the background * color is a negative value, this layer will become transparent and no * background will be painted. * * @param bgImage the image to use for the background tile (or null) * @param bgColor if the image is null, use this color as a background * fill color */ synchronized void setBackground(Image bgImage, int bgColor) { bgLayer.setBackground(bgImage, bgColor); } /** * Returns true if any layer of this window is in need of repainting. * * @return true if any layer of this window is marked as 'dirty' * and needs repainting. */ public boolean isDirty() { return this.dirty; } /** * Mark this window as being dirty and requiring a repaint. */ public void setDirty() { this.dirty = true; } /** Constant used to reference the '0' index of the bounds array */ public static final int X = 0; /** Constant used to reference the '1' index of the bounds array */ public static final int Y = 1; /** Constant used to reference the '2' index of the bounds array */ public static final int W = 2; /** Constant used to reference the '3' index of the bounds array */ public static final int H = 3;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?