/** * Find the color band that this value falls in and assign that color. * * @param v * @param color */ private final void absoluteValue(final double v, final int[] color) { final double search; switch (scaling) { case Absolute: search = v; break; case MinMax: search = (v - min) / (max - min); break; case Modulo: search = v % (max - min); break; default: search = 0; break; } final Map.Entry<Double, Color> lower = floorEntry(search); Color c; if (lower == null) { c = entrySet().iterator().next().getValue(); } else { c = lower.getValue(); } color[R] = c.getRed(); color[G] = c.getGreen(); color[B] = c.getBlue(); color[A] = c.getAlpha(); }
/** * Interpolate the color value for the given scalar value. The result is placed in color. * * @param v * @param color * @return */ private final void interpolateValue(final double v, final int[] color) { final double search; switch (scaling) { case Absolute: search = v; break; case MinMax: search = (v - min) / (max - min); break; case Modulo: search = (v - min) % (max - min); break; default: search = 0; break; } final Map.Entry<Double, Color> lower = floorEntry(search); final Map.Entry<Double, Color> upper = higherEntry(search); assert (upper != null || lower != null); if (upper == null) { final Color c = lower.getValue(); color[R] = c.getRed(); color[G] = c.getGreen(); color[B] = c.getBlue(); color[A] = c.getAlpha(); } else if (lower == null) { final Color c = upper.getValue(); color[R] = c.getRed(); color[G] = c.getGreen(); color[B] = c.getBlue(); color[A] = c.getAlpha(); } else { final double diff = upper.getKey().doubleValue() - lower.getKey().doubleValue(); final double lw = 1.0 - ((search - lower.getKey().doubleValue()) / diff); final double uw = 1.0 - lw; final Color lc = lower.getValue(); final Color uc = upper.getValue(); color[R] = (int) Math.round(lc.getRed() * lw + uc.getRed() * uw); color[G] = (int) Math.round(lc.getGreen() * lw + uc.getGreen() * uw); color[B] = (int) Math.round(lc.getBlue() * lw + uc.getBlue() * uw); color[A] = (int) Math.round(lc.getAlpha() * lw + uc.getAlpha() * uw); } }
@Override public void write(final OutputStream out) throws IOException { out.write(TYPE_COLOR); super.write(out); out.write(color.getRed()); out.write(color.getGreen()); out.write(color.getBlue()); out.write(color.getAlpha()); }
/** * Turn a (possibly) translucent or indexed image into a display-compatible bitmask image using * the given alpha threshold and render-to-background colour, or display-compatible translucent * image. The alpha values in the image are set to either 0 (below threshold) or 255 (above * threshold). The render-to-background colour bg_col is used to determine how the pixels * overlapping transparent pixels should be rendered. The fast algorithm just sets the colour * behind the transparent pixels in the image (for bitmask source images); the slow algorithm * actually renders the image to a background of bg_col (for translucent sources). * * @param thresh alpha threshold between 0 and 255 * @param fast use fast algorithm (only set bg_col behind transp. pixels) * @param bitmask true=use bitmask, false=use translucent */ public JGImage toDisplayCompatible(int thresh, JGColor bg_col, boolean fast, boolean bitmask) { Color bgcol = new Color(bg_col.r, bg_col.g, bg_col.b); int bgcol_rgb = (bgcol.getRed() << 16) | (bgcol.getGreen() << 8) | bgcol.getBlue(); JGPoint size = getSize(); int[] buffer = getPixels(); // render image to bg depending on bgcol BufferedImage img_bg; if (bitmask) { img_bg = createCompatibleImage(size.x, size.y, Transparency.BITMASK); } else { img_bg = createCompatibleImage(size.x, size.y, Transparency.TRANSLUCENT); } int[] bg_buf; if (!fast) { Graphics g = img_bg.getGraphics(); g.setColor(bgcol); // the docs say I could use bgcol in the drawImage as an // equivalent to the following two lines, but this // doesn't handle translucency properly and is _slower_ g.fillRect(0, 0, size.x, size.y); g.drawImage(img, 0, 0, null); bg_buf = new JREImage(img_bg).getPixels(); } else { bg_buf = buffer; } // g.dispose(); // ColorModel rgb_bitmask = ColorModel.getRGBdefault(); // rgb_bitmask = new PackedColorModel( // rgb_bitmask.getColorSpace(),25,0xff0000,0x00ff00,0x0000ff, // 0x1000000, false, Transparency.BITMASK, DataBuffer.TYPE_INT); // ColorSpace space, int bits, int rmask, int gmask, int bmask, int amask, boolean // isAlphaPremultiplied, int trans, int transferType) int[] thrsbuf = new int[size.x * size.y]; for (int y = 0; y < size.y; y++) { for (int x = 0; x < size.x; x++) { if (((buffer[y * size.x + x] >> 24) & 0xff) >= thresh) { thrsbuf[y * size.x + x] = bg_buf[y * size.x + x] | (0xff << 24); } else { // explicitly set the colour of the transparent pixel. // This makes a difference when scaling! // thrsbuf[y*size.x+x]=bg_buf[y*size.x+x]&~(0xff<<24); thrsbuf[y * size.x + x] = bgcol_rgb; } } } return new JREImage( output_comp.createImage( new MemoryImageSource( size.x, size.y, // rgb_bitmask, img_bg.getColorModel(), // display compatible bitmask bitmask ? thrsbuf : bg_buf, 0, size.x))); }
public void drawTileNumC(int tileNum, int x, int y, Color c, Graphics g) { BufferedImage coloredTile = tiles[tileNum]; for (int i = 0; i < this.tW; i++) { for (int j = 0; j < this.tH; j++) { Color originalColor = new Color(coloredTile.getRGB(i, j), true); Color nc = new Color(c.getRed(), c.getGreen(), c.getBlue(), originalColor.getAlpha()); coloredTile.setRGB(i, j, nc.getRGB()); } } g.drawImage(tiles[tileNum], x, y, null); }
// Get Color as String public static String getColor(Color color) { ArrayList<String> colors = new ArrayList<String>(); colors.add(Long.toHexString(color.getRed())); colors.add(Long.toHexString(color.getGreen())); colors.add(Long.toHexString(color.getBlue())); StringBuilder buffer = new StringBuilder(); for (String c : colors) { if (c.length() == 1) { buffer.append("0"); } buffer.append(c); } return ("#" + buffer.toString()); }
/** * Calculates the apparent color of this polygon. We ask the camera how much light falls on a * surface wiith this normal and then darken the color accordingly. */ private Color calcLight() { if (noShade) { return c; } int r = c.getRed(); int g = c.getGreen(); int b = c.getBlue(); float light = modelViewer.cameraMan.surfaceLight(normal); r *= light; g *= light; b *= light; return new Color(r, g, b); }
private Color getColor(Element shape) { Color color; if (shape.hasAttribute(ATR_COLOUR)) { String s = shape.getAttribute(ATR_COLOUR); if (s.indexOf(',') > -1) { String[] rgb = s.split(","); color = new Color( Integer.parseInt(rgb[0]), Integer.parseInt(rgb[1]), Integer.parseInt(rgb[2])); } else { color = new Color(Integer.parseInt(s)); } } else color = IMPLIED_COLOR; if (shape.hasAttribute(ATR_TRANSPARENCY)) { int alpha = Integer.parseInt(shape.getAttribute(ATR_TRANSPARENCY)); if (alpha < 255) return new Color(color.getRed(), color.getGreen(), color.getBlue(), alpha); } return color; }
/** Returns index of palette color closest to c */ protected int findClosest(Color c) { if (colorTab == null) return -1; int r = c.getRed(); int g = c.getGreen(); int b = c.getBlue(); int minpos = 0; int dmin = 256 * 256 * 256; int len = colorTab.length; for (int i = 0; i < len; ) { int dr = r - (colorTab[i++] & 0xff); int dg = g - (colorTab[i++] & 0xff); int db = b - (colorTab[i] & 0xff); int d = dr * dr + dg * dg + db * db; int index = i / 3; if (usedEntry[index] && (d < dmin)) { dmin = d; minpos = index; } i++; } return minpos; }
/** * Computes neuron or link color, depending on its value and selected state. * * @param v neuron activation * @return neuron color */ public Color getColor(double v) { Color ci = null_color, ca = pos_color, cn = neg_color; int red, green, blue; if (v >= 0) { red = (int) (ci.getRed() + v * (ca.getRed() - ci.getRed())); red = limit(red); green = (int) (ci.getGreen() + v * (ca.getGreen() - ci.getGreen())); green = limit(green); blue = (int) (ci.getBlue() + v * (ca.getBlue() - ci.getBlue())); blue = limit(blue); } else { red = (int) (ci.getRed() - v * (cn.getRed() - ci.getRed())); red = limit(red); green = (int) (ci.getGreen() - v * (cn.getGreen() - ci.getGreen())); green = limit(green); blue = (int) (ci.getBlue() - v * (cn.getBlue() - ci.getBlue())); blue = limit(blue); } return new Color(red, green, blue); }
/** * Returns the red value of the image at the given coordinates. * * <p>The coordinates should be non-negative and less than the width (x) or height (y) of the * image. The red value is returned as an integer in the range [0,255]. * * @param x the horizontal coordinate of the pixel * @param y the vertical coordinate of the pixel * @return the red value at the given coordinates */ public int getRed(int x, int y) { // works! Color c = new Color(img.getRGB(x, y)); return c.getRed(); // (img.getRGB(x, y) & 0x00ff0000) >> 16; }
public GroundTexture(int size, Ground grnd) { System.out.println("Calculating Ground Texture..."); img = new BufferedImage(size, size, BufferedImage.TYPE_INT_RGB); double r, g, b; Random rnd = new Random(); System.out.print("Initializing..."); for (int x = 0; x < size; x++) { for (int y = 0; y < size; y++) { double slope = 0; for (int nx = x - 1; nx < x + 1; nx++) for (int ny = y - 1; ny < y + 1; ny++) if ((nx >= 0) && (nx < size)) if ((ny >= 0) && (ny < size)) slope += Math.abs(grnd.topo[nx][ny] - grnd.topo[x][y]); if (slope < 1) slope = 1; g = 5d + 80d / (grnd.topo[x][y] / 2000d + 1d) + rnd.nextDouble() * 30d / (slope); r = g * (1.17 + (-.3 + (rnd.nextDouble() * .3)) / (grnd.topo[x][y] / 200d + 1d) / (slope / 5 + 1)); b = r * (.7 + (-.3 + (rnd.nextDouble() * .2)) / (grnd.topo[x][y] / 200d + 1d) / (slope / 5 + 1)); img.setRGB(x, y, colorRGB((int) r, (int) g, (int) b)); } } /**/ // save("bodentextur2","png"); System.out.print(" \rRandom Growth"); for (int i = 0; i < size * size * 8; i++) { if (i % (size * size / 2) == 0) System.out.print("."); int x = 3 + rnd.nextInt(size - 6); int y = 3 + rnd.nextInt(size - 6); int nx = x - 1 + rnd.nextInt(3); int ny = y - 1 + rnd.nextInt(3); while ((nx < 0) || (nx >= size) || (ny < 0) || (ny >= size)) { nx = x - 1 + rnd.nextInt(3); ny = y - 1 + rnd.nextInt(3); } Color dis = getColorAt(x, y); Color col = getColorAt(nx, ny); if (grnd.topo[nx][ny] >= 4.5) if (col.getGreen() / col.getRed() > dis.getGreen() / dis.getRed()) if (Math.abs(grnd.topo[x][y] - grnd.topo[nx][ny]) < .65) { int c = colorRGB(col.getRed(), col.getGreen(), col.getBlue()); // img.setRGB(x,y, colorRGB(col.getRed(), col.getGreen(), col.getBlue())); // img.setRGB(x-1+rnd.nextInt(3),y-1+rnd.nextInt(3), colorRGB(col.getRed(), // col.getGreen(), col.getBlue())); for (nx = x - 1 - rnd.nextInt(3); nx < 1 + x + rnd.nextInt(3); nx++) for (ny = y - 1 - rnd.nextInt(3); ny < y + 1 + rnd.nextInt(3); ny++) { img.setRGB(nx, ny, c); grnd.topo[nx][ny] += 1.8; } } } System.out.print(" \rAntialiasing..."); /* for (int x = 0; x < size; x++){ for (int y = 0; y < size; y++){ double sumr = 0; double sumg = 0; double sumb = 0; double div = 0; for (int nx=x-1;nx<x+1;nx++) for (int ny=y-1;ny<y+1;ny++) if ((nx>=0) && (nx < size)) if ((ny>=0) && (ny < size)) { Color col = getColorAt(nx,ny); sumr+=col.getRed(); sumg+=col.getGreen(); sumb+=col.getBlue(); div++; } r=sumr/div; g=sumg/div; b=sumb/div; img.setRGB(x,y, colorRGB((int)r, (int)g, (int)b) ); } }*/ System.out.print(" \r"); // save("bodentextur3","png"); save("bodentextur", "png"); }
static ColorUIResource getColorTercio(Color a, Color b) { return new ColorUIResource( propInt(a.getRed(), b.getRed(), 3), propInt(a.getGreen(), b.getGreen(), 3), propInt(a.getBlue(), b.getBlue(), 3)); }
static Color getColorMedio(Color a, Color b) { return new Color( propInt(a.getRed(), b.getRed(), 2), propInt(a.getGreen(), b.getGreen(), 2), propInt(a.getBlue(), b.getBlue(), 2)); }
static Color getColorAlfa(Color col, int alfa) { return new Color(col.getRed(), col.getGreen(), col.getBlue(), alfa); }
protected void drawIcon(DrawContext dc) { if (this.getIconFilePath() == null) return; GL gl = dc.getGL(); OGLStackHandler ogsh = new OGLStackHandler(); try { // Initialize texture if necessary Texture iconTexture = dc.getTextureCache().getTexture(this.getIconFilePath()); if (iconTexture == null) { this.initializeTexture(dc); iconTexture = dc.getTextureCache().getTexture(this.getIconFilePath()); if (iconTexture == null) { String msg = Logging.getMessage("generic.ImageReadFailed"); Logging.logger().finer(msg); return; } } gl.glDisable(GL.GL_DEPTH_TEST); double width = this.getScaledIconWidth(); double height = this.getScaledIconHeight(); // Load a parallel projection with xy dimensions (viewportWidth, viewportHeight) // into the GL projection matrix. java.awt.Rectangle viewport = dc.getView().getViewport(); ogsh.pushProjectionIdentity(gl); double maxwh = width > height ? width : height; gl.glOrtho(0d, viewport.width, 0d, viewport.height, -0.6 * maxwh, 0.6 * maxwh); // Translate and scale ogsh.pushModelviewIdentity(gl); double scale = this.computeScale(viewport); Vec4 locationSW = this.computeLocation(viewport, scale); gl.glTranslated(locationSW.x(), locationSW.y(), locationSW.z()); // Scale to 0..1 space gl.glScaled(scale, scale, 1); gl.glScaled(width, height, 1d); if (!dc.isPickingMode()) { gl.glEnable(GL.GL_BLEND); gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA); // Draw background color behind the map gl.glColor4ub( (byte) this.backColor.getRed(), (byte) this.backColor.getGreen(), (byte) this.backColor.getBlue(), (byte) (this.backColor.getAlpha() * this.getOpacity())); dc.drawUnitQuad(); // Draw world map icon gl.glColor4d(1d, 1d, 1d, this.getOpacity()); gl.glEnable(GL.GL_TEXTURE_2D); iconTexture.bind(); TextureCoords texCoords = iconTexture.getImageTexCoords(); dc.drawUnitQuad(texCoords); gl.glBindTexture(GL.GL_TEXTURE_2D, 0); gl.glDisable(GL.GL_TEXTURE_2D); // Draw crosshair for current location gl.glLoadIdentity(); gl.glTranslated(locationSW.x(), locationSW.y(), locationSW.z()); // Scale to width x height space gl.glScaled(scale, scale, 1); // Set color float[] colorRGB = this.color.getRGBColorComponents(null); gl.glColor4d(colorRGB[0], colorRGB[1], colorRGB[2], this.getOpacity()); // Draw crosshair Position groundPos = this.computeGroundPosition(dc, dc.getView()); if (groundPos != null) { int x = (int) (width * (groundPos.getLongitude().degrees + 180) / 360); int y = (int) (height * (groundPos.getLatitude().degrees + 90) / 180); int w = 10; // cross branch length // Draw gl.glBegin(GL.GL_LINE_STRIP); gl.glVertex3d(x - w, y, 0); gl.glVertex3d(x + w + 1, y, 0); gl.glEnd(); gl.glBegin(GL.GL_LINE_STRIP); gl.glVertex3d(x, y - w, 0); gl.glVertex3d(x, y + w + 1, 0); gl.glEnd(); } // Draw view footprint in map icon space if (this.showFootprint) { this.footPrintPositions = this.computeViewFootPrint(dc, 32); if (this.footPrintPositions != null) { gl.glBegin(GL.GL_LINE_STRIP); LatLon p1 = this.footPrintPositions.get(0); for (LatLon p2 : this.footPrintPositions) { int x = (int) (width * (p2.getLongitude().degrees + 180) / 360); int y = (int) (height * (p2.getLatitude().degrees + 90) / 180); // Draw if (LatLon.locationsCrossDateline(p1, p2)) { int y1 = (int) (height * (p1.getLatitude().degrees + 90) / 180); gl.glVertex3d(x < width / 2 ? width : 0, (y1 + y) / 2, 0); gl.glEnd(); gl.glBegin(GL.GL_LINE_STRIP); gl.glVertex3d(x < width / 2 ? 0 : width, (y1 + y) / 2, 0); } gl.glVertex3d(x, y, 0); p1 = p2; } gl.glEnd(); } } // Draw 1px border around and inside the map gl.glBegin(GL.GL_LINE_STRIP); gl.glVertex3d(0, 0, 0); gl.glVertex3d(width, 0, 0); gl.glVertex3d(width, height - 1, 0); gl.glVertex3d(0, height - 1, 0); gl.glVertex3d(0, 0, 0); gl.glEnd(); } else { // Picking this.pickSupport.clearPickList(); this.pickSupport.beginPicking(dc); // Where in the world are we picking ? Position pickPosition = computePickPosition( dc, locationSW, new Dimension((int) (width * scale), (int) (height * scale))); Color color = dc.getUniquePickColor(); int colorCode = color.getRGB(); this.pickSupport.addPickableObject(colorCode, this, pickPosition, false); gl.glColor3ub((byte) color.getRed(), (byte) color.getGreen(), (byte) color.getBlue()); dc.drawUnitQuad(); this.pickSupport.endPicking(dc); this.pickSupport.resolvePick(dc, dc.getPickPoint(), this); } } finally { dc.restoreDefaultDepthTesting(); dc.restoreDefaultCurrentColor(); if (dc.isPickingMode()) dc.restoreDefaultBlending(); ogsh.pop(gl); } }
@Override public void paintComponent(Graphics g) { super.paintComponent(g); int width = getWidth() - rightMargin - leftMargin - 10; int height = getHeight() - topMargin - bottomMargin; if (width <= 0 || height <= 0) { // not enough room to paint anything return; } Color oldColor = g.getColor(); Font oldFont = g.getFont(); Color fg = getForeground(); Color bg = getBackground(); boolean bgIsLight = (bg.getRed() > 200 && bg.getGreen() > 200 && bg.getBlue() > 200); ((Graphics2D) g) .setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); if (smallFont == null) { smallFont = oldFont.deriveFont(9.0F); } r.x = leftMargin - 5; r.y = topMargin - 8; r.width = getWidth() - leftMargin - rightMargin; r.height = getHeight() - topMargin - bottomMargin + 16; if (border == null) { // By setting colors here, we avoid recalculating them // over and over. border = new BevelBorder( BevelBorder.LOWERED, getBackground().brighter().brighter(), getBackground().brighter(), getBackground().darker().darker(), getBackground().darker()); } border.paintBorder(this, g, r.x, r.y, r.width, r.height); // Fill background color g.setColor(bgColor); g.fillRect(r.x + 2, r.y + 2, r.width - 4, r.height - 4); g.setColor(oldColor); long tMin = Long.MAX_VALUE; long tMax = Long.MIN_VALUE; long vMin = Long.MAX_VALUE; long vMax = 1; int w = getWidth() - rightMargin - leftMargin - 10; int h = getHeight() - topMargin - bottomMargin; if (times.size > 1) { tMin = Math.min(tMin, times.time(0)); tMax = Math.max(tMax, times.time(times.size - 1)); } long viewRangeMS; if (viewRange > 0) { viewRangeMS = viewRange * MINUTE; } else { // Display full time range, but no less than a minute viewRangeMS = Math.max(tMax - tMin, 1 * MINUTE); } // Calculate min/max values for (Sequence seq : seqs) { if (seq.size > 0) { for (int i = 0; i < seq.size; i++) { if (seq.size == 1 || times.time(i) >= tMax - viewRangeMS) { long val = seq.value(i); if (val > Long.MIN_VALUE) { vMax = Math.max(vMax, val); vMin = Math.min(vMin, val); } } } } else { vMin = 0L; } if (unit == Unit.BYTES || !seq.isPlotted) { // We'll scale only to the first (main) value set. // TODO: Use a separate property for this. break; } } // Normalize scale vMax = normalizeMax(vMax); if (vMin > 0) { if (vMax / vMin > 4) { vMin = 0; } else { vMin = normalizeMin(vMin); } } g.setColor(fg); // Axes // Draw vertical axis int x = leftMargin - 18; int y = topMargin; FontMetrics fm = g.getFontMetrics(); g.drawLine(x, y, x, y + h); int n = 5; if (("" + vMax).startsWith("2")) { n = 4; } else if (("" + vMax).startsWith("3")) { n = 6; } else if (("" + vMax).startsWith("4")) { n = 4; } else if (("" + vMax).startsWith("6")) { n = 6; } else if (("" + vMax).startsWith("7")) { n = 7; } else if (("" + vMax).startsWith("8")) { n = 8; } else if (("" + vMax).startsWith("9")) { n = 3; } // Ticks ArrayList<Long> tickValues = new ArrayList<Long>(); tickValues.add(vMin); for (int i = 0; i < n; i++) { long v = i * vMax / n; if (v > vMin) { tickValues.add(v); } } tickValues.add(vMax); n = tickValues.size(); String[] tickStrings = new String[n]; for (int i = 0; i < n; i++) { long v = tickValues.get(i); tickStrings[i] = getSizeString(v, vMax); } // Trim trailing decimal zeroes. if (decimals > 0) { boolean trimLast = true; boolean removedDecimalPoint = false; do { for (String str : tickStrings) { if (!(str.endsWith("0") || str.endsWith("."))) { trimLast = false; break; } } if (trimLast) { if (tickStrings[0].endsWith(".")) { removedDecimalPoint = true; } for (int i = 0; i < n; i++) { String str = tickStrings[i]; tickStrings[i] = str.substring(0, str.length() - 1); } } } while (trimLast && !removedDecimalPoint); } // Draw ticks int lastY = Integer.MAX_VALUE; for (int i = 0; i < n; i++) { long v = tickValues.get(i); y = topMargin + h - (int) (h * (v - vMin) / (vMax - vMin)); g.drawLine(x - 2, y, x + 2, y); String s = tickStrings[i]; if (unit == Unit.PERCENT) { s += "%"; } int sx = x - 6 - fm.stringWidth(s); if (y < lastY - 13) { if (checkLeftMargin(sx)) { // Wait for next repaint return; } g.drawString(s, sx, y + 4); } // Draw horizontal grid line g.setColor(Color.lightGray); g.drawLine(r.x + 4, y, r.x + r.width - 4, y); g.setColor(fg); lastY = y; } // Draw horizontal axis x = leftMargin; y = topMargin + h + 15; g.drawLine(x, y, x + w, y); long t1 = tMax; if (t1 <= 0L) { // No data yet, so draw current time t1 = System.currentTimeMillis(); } long tz = timeDF.getTimeZone().getOffset(t1); long tickInterval = calculateTickInterval(w, 40, viewRangeMS); if (tickInterval > 3 * HOUR) { tickInterval = calculateTickInterval(w, 80, viewRangeMS); } long t0 = tickInterval - (t1 - viewRangeMS + tz) % tickInterval; while (t0 < viewRangeMS) { x = leftMargin + (int) (w * t0 / viewRangeMS); g.drawLine(x, y - 2, x, y + 2); long t = t1 - viewRangeMS + t0; String str = formatClockTime(t); g.drawString(str, x, y + 16); // if (tickInterval > (1 * HOUR) && t % (1 * DAY) == 0) { if ((t + tz) % (1 * DAY) == 0) { str = formatDate(t); g.drawString(str, x, y + 27); } // Draw vertical grid line g.setColor(Color.lightGray); g.drawLine(x, topMargin, x, topMargin + h); g.setColor(fg); t0 += tickInterval; } // Plot values int start = 0; int nValues = 0; int nLists = seqs.size(); if (nLists > 0) { nValues = seqs.get(0).size; } if (nValues == 0) { g.setColor(oldColor); return; } else { Sequence seq = seqs.get(0); // Find starting point for (int p = 0; p < seq.size; p++) { if (times.time(p) >= tMax - viewRangeMS) { start = p; break; } } } // Optimization: collapse plot of more than four values per pixel int pointsPerPixel = (nValues - start) / w; if (pointsPerPixel < 4) { pointsPerPixel = 1; } // Draw graphs // Loop backwards over sequences because the first needs to be painted on top for (int i = nLists - 1; i >= 0; i--) { int x0 = leftMargin; int y0 = topMargin + h + 1; Sequence seq = seqs.get(i); if (seq.isPlotted && seq.size > 0) { // Paint twice, with white and with color for (int pass = 0; pass < 2; pass++) { g.setColor((pass == 0) ? Color.white : seq.color); int x1 = -1; long v1 = -1; for (int p = start; p < nValues; p += pointsPerPixel) { // Make sure we get the last value if (pointsPerPixel > 1 && p >= nValues - pointsPerPixel) { p = nValues - 1; } int x2 = (int) (w * (times.time(p) - (t1 - viewRangeMS)) / viewRangeMS); long v2 = seq.value(p); if (v2 >= vMin && v2 <= vMax) { int y2 = (int) (h * (v2 - vMin) / (vMax - vMin)); if (x1 >= 0 && v1 >= vMin && v1 <= vMax) { int y1 = (int) (h * (v1 - vMin) / (vMax - vMin)); if (y1 == y2) { // fillrect is much faster g.fillRect(x0 + x1, y0 - y1 - pass, x2 - x1, 1); } else { Graphics2D g2d = (Graphics2D) g; Stroke oldStroke = null; if (seq.transitionStroke != null) { oldStroke = g2d.getStroke(); g2d.setStroke(seq.transitionStroke); } g.drawLine(x0 + x1, y0 - y1 - pass, x0 + x2, y0 - y2 - pass); if (oldStroke != null) { g2d.setStroke(oldStroke); } } } } x1 = x2; v1 = v2; } } // Current value long v = seq.value(seq.size - 1); if (v >= vMin && v <= vMax) { if (bgIsLight) { g.setColor(seq.color); } else { g.setColor(fg); } x = r.x + r.width + 2; y = topMargin + h - (int) (h * (v - vMin) / (vMax - vMin)); // a small triangle/arrow g.fillPolygon(new int[] {x + 2, x + 6, x + 6}, new int[] {y, y + 3, y - 3}, 3); } g.setColor(fg); } } int[] valueStringSlots = new int[nLists]; for (int i = 0; i < nLists; i++) valueStringSlots[i] = -1; for (int i = 0; i < nLists; i++) { Sequence seq = seqs.get(i); if (seq.isPlotted && seq.size > 0) { // Draw current value // TODO: collapse values if pointsPerPixel >= 4 long v = seq.value(seq.size - 1); if (v >= vMin && v <= vMax) { x = r.x + r.width + 2; y = topMargin + h - (int) (h * (v - vMin) / (vMax - vMin)); int y2 = getValueStringSlot(valueStringSlots, y, 2 * 10, i); g.setFont(smallFont); if (bgIsLight) { g.setColor(seq.color); } else { g.setColor(fg); } String curValue = getFormattedValue(v, true); if (unit == Unit.PERCENT) { curValue += "%"; } int valWidth = fm.stringWidth(curValue); String legend = (displayLegend ? seq.name : ""); int legendWidth = fm.stringWidth(legend); if (checkRightMargin(valWidth) || checkRightMargin(legendWidth)) { // Wait for next repaint return; } g.drawString(legend, x + 17, Math.min(topMargin + h, y2 + 3 - 10)); g.drawString(curValue, x + 17, Math.min(topMargin + h + 10, y2 + 3)); // Maybe draw a short line to value if (y2 > y + 3) { g.drawLine(x + 9, y + 2, x + 14, y2); } else if (y2 < y - 3) { g.drawLine(x + 9, y - 2, x + 14, y2); } } g.setFont(oldFont); g.setColor(fg); } } g.setColor(oldColor); }