package com.kreative.paint.material.pattern; import java.awt.Paint; import java.awt.PaintContext; import java.awt.Point; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.Raster; public class PatternPaint implements Paint { public final Paint foreground; public final Paint background; public final Pattern pattern; public PatternPaint(Paint foreground, Paint background, Pattern pattern) { this.foreground = foreground; this.background = background; this.pattern = pattern; } public PatternPaint deriveForeground(Paint foreground) { return new PatternPaint(foreground, background, pattern); } public PatternPaint deriveBackground(Paint background) { return new PatternPaint(foreground, background, pattern); } public PatternPaint derivePattern(Pattern pattern) { return new PatternPaint(foreground, background, pattern); } @Override public PaintContext createContext(ColorModel cm, Rectangle deviceBounds, Rectangle2D userBounds, AffineTransform xform, RenderingHints hints) { PaintContext fg = foreground.createContext(cm, deviceBounds, userBounds, xform, hints); PaintContext bg = background.createContext(cm, deviceBounds, userBounds, xform, hints); if (pattern.isForeground()) return fg; if (pattern.isBackground()) return bg; return new PatternPaintContext(fg, bg, pattern, xform); } @Override public int getTransparency() { int fg = foreground.getTransparency(); int bg = foreground.getTransparency(); if (pattern.isForeground()) return fg; if (pattern.isBackground()) return bg; if (fg == bg) return fg; if (fg == TRANSLUCENT || bg == TRANSLUCENT) return TRANSLUCENT; if (fg == BITMASK || bg == BITMASK) return BITMASK; return OPAQUE; } private static class PatternPaintContext implements PaintContext { private final PaintContext foreground; private final PaintContext background; private final Pattern pattern; private final AffineTransform itx; public PatternPaintContext(PaintContext foreground, PaintContext background, Pattern pattern, AffineTransform tx) { this.foreground = foreground; this.background = background; this.pattern = pattern; if (tx == null || tx.isIdentity()) { this.itx = null; } else { try { tx = tx.createInverse(); } catch (Exception e) { tx = null; } this.itx = tx; } } @Override public Raster getRaster(int x, int y, int w, int h) { Raster foreRaster = foreground.getRaster(x, y, w, h); Raster backRaster = background.getRaster(x, y, w, h); ColorModel foreModel = foreground.getColorModel(); ColorModel backModel = background.getColorModel(); BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); Point p = new Point(); for (int ry = y, ny = 0; ny < h; ry++, ny++) { for (int rx = x, nx = 0; nx < w; rx++, nx++) { int foreRGB = foreModel.getRGB(foreRaster.getDataElements(nx, ny, null)); int backRGB = backModel.getRGB(backRaster.getDataElements(nx, ny, null)); p.x = rx; p.y = ry; if (itx != null) itx.transform(p, p); int rgb = pattern.getRGB(p.x, p.y, backRGB, foreRGB); img.setRGB(nx, ny, rgb); } } return img.getData(); } @Override public ColorModel getColorModel() { BufferedImage img = new BufferedImage(8, 8, BufferedImage.TYPE_INT_ARGB); return img.getColorModel(); } @Override public void dispose() { foreground.dispose(); background.dispose(); } } }