protected static ColorModel fixColorModel(CachableRed src) { ColorModel cm = src.getColorModel(); if (cm.hasAlpha()) { if (!cm.isAlphaPremultiplied()) cm = GraphicsUtil.coerceColorModel(cm, true); return cm; } ColorSpace cs = cm.getColorSpace(); int b = src.getSampleModel().getNumBands() + 1; if (b == 4) { int[] masks = new int[4]; for (int i = 0; i < b - 1; i++) masks[i] = 0xFF0000 >> (8 * i); masks[3] = 0xFF << (8 * (b - 1)); return new DirectColorModel( cs, 8 * b, masks[0], masks[1], masks[2], masks[3], true, DataBuffer.TYPE_INT); } int[] bits = new int[b]; for (int i = 0; i < b; i++) bits[i] = 8; return new ComponentColorModel( cs, bits, true, true, Transparency.TRANSLUCENT, DataBuffer.TYPE_INT); }
/** * Constructor for superclass. Does some initialization, but leaves most of the heavy-duty math * for calculateGradient(), so the subclass may do some other manipulation beforehand if * necessary. This is not possible if this computation is done in the superclass constructor which * always gets called first. */ public MultipleGradientPaintContext( ColorModel cm, Rectangle deviceBounds, Rectangle2D userBounds, AffineTransform t, RenderingHints hints, float[] fractions, Color[] colors, MultipleGradientPaint.CycleMethodEnum cycleMethod, MultipleGradientPaint.ColorSpaceEnum colorSpace) throws NoninvertibleTransformException { // We have to deal with the cases where the 1st gradient stop is not // equal to 0 and/or the last gradient stop is not equal to 1. // In both cases, create a new point and replicate the previous // extreme point's color. boolean fixFirst = false; boolean fixLast = false; int len = fractions.length; // if the first gradient stop is not equal to zero, fix this condition if (fractions[0] != 0f) { fixFirst = true; len++; } // if the last gradient stop is not equal to one, fix this condition if (fractions[fractions.length - 1] != 1f) { fixLast = true; len++; } for (int i = 0; i < fractions.length - 1; i++) if (fractions[i] == fractions[i + 1]) len--; this.fractions = new float[len]; Color[] loColors = new Color[len - 1]; Color[] hiColors = new Color[len - 1]; normalizedIntervals = new float[len - 1]; gradientUnderflow = colors[0].getRGB(); gradientOverflow = colors[colors.length - 1].getRGB(); int idx = 0; if (fixFirst) { this.fractions[0] = 0; loColors[0] = colors[0]; hiColors[0] = colors[0]; normalizedIntervals[0] = fractions[0]; idx++; } for (int i = 0; i < fractions.length - 1; i++) { if (fractions[i] == fractions[i + 1]) { // System.out.println("EQ Fracts"); if (!colors[i].equals(colors[i + 1])) { hasDiscontinuity = true; } continue; } this.fractions[idx] = fractions[i]; loColors[idx] = colors[i]; hiColors[idx] = colors[i + 1]; normalizedIntervals[idx] = fractions[i + 1] - fractions[i]; idx++; } this.fractions[idx] = fractions[fractions.length - 1]; if (fixLast) { loColors[idx] = hiColors[idx] = colors[colors.length - 1]; normalizedIntervals[idx] = 1 - fractions[fractions.length - 1]; idx++; this.fractions[idx] = 1; } // The inverse transform is needed to from device to user space. // Get all the components of the inverse transform matrix. AffineTransform tInv = t.createInverse(); double m[] = new double[6]; tInv.getMatrix(m); a00 = (float) m[0]; a10 = (float) m[1]; a01 = (float) m[2]; a11 = (float) m[3]; a02 = (float) m[4]; a12 = (float) m[5]; // copy some flags this.cycleMethod = cycleMethod; this.colorSpace = colorSpace; // PATCH Werner Randelshofer: ColorModel can be null! // Setup an example Model, we may refine it later. if (cm != null && cm.getColorSpace() == lrgbmodel_A.getColorSpace()) dataModel = lrgbmodel_A; else if (cm == null || cm.getColorSpace() == srgbmodel_A.getColorSpace()) dataModel = srgbmodel_A; else throw new IllegalArgumentException("Unsupported ColorSpace for interpolation"); calculateGradientFractions(loColors, hiColors); model = GraphicsUtil.coerceColorModel(dataModel, cm != null && cm.isAlphaPremultiplied()); }