use of java.awt.image.WritableRaster in project intellij-code-outline by sitano.
the class CodeOutlineImage method updateImg.
/**
* Updates the code outline image to reflect the given document change.
*
* @param e a document change event
* @param oldend the logical position of the end of the "old" changed region
* before the change was actually made
*/
private synchronized void updateImg(DocumentEvent e, LogicalPosition oldend) {
// if there's no image we don't need to do anything
if (img == null)
return;
final int offset = e.getOffset();
final int newLength = e.getNewLength();
final int oldLength = e.getOldLength();
final int width = visibleImgWidth;
final int height = visibleImgHeight;
final double scale = this.scale;
// compute the logical positions of the old and new offsets
final LogicalPosition start = editor.offsetToLogicalPosition(offset);
final LogicalPosition newend = editor.offsetToLogicalPosition(offset + newLength);
// to do
if (getScaledLine(start.line, scale) >= height)
return;
// the number of affected lines
int affected = Math.abs(newend.line - oldend.line) + 1;
// to do
if (affected == 1 && start.column >= width)
return;
// the number of lines added (a negative value means lines were removed)
int addedLines = newend.line - oldend.line;
/*
* If lines count changed, then redraw all the stuff if there are:
* 1. deleted lines
* 2. scale factor changed (scaling)
*/
if (addedLines != 0) {
if (addedLines < 0 || scale < 1.0 || getScaleFactor(height, document.getLineCount()) < 1.0) {
refreshImage();
// TODO: Delayed redraw for last timed out change
listener.shouldRepaint(this, new Rectangle(0, 0, width, height));
return;
}
}
/*
This method does the following things:
1. Copy the (unmodified) rest of the line at the end of the modified
region
2. Move all unmodified lines, below the changed region, up or down, if
lines were added or removed
3. Clear data at end of line on first line of changed region
4. Clear middle lines, if any, in the changed region
5. Clear data at beginning of line on last line of changed region
6. Paste the data copied in #1 at the new end of region
7. Re-render any data which was not copied in #6 because of insufficient
window width
8. Render the new data in the changed region
*/
// how much of the end of the last line needs to be cleared
int needsFilling = Math.max(0, width - newend.column);
// how much of the end of the old last line needs to be copied to the
// new end of the last line (this takes into account how much is there,
// and how much space there is at the end of the new line, so no unused
// data is copied)
int charsToCopy = Math.min(needsFilling, Math.max(0, width - oldend.column));
// copy the (unmodified) rest of the line at the end of the modified
// region
WritableRaster raster = img.getRaster();
Object endOfLine = null;
int oldEndLine = getScaledLine(oldend.line, scale);
int newEndLine = getScaledLine(newend.line, scale);
if (oldEndLine < height && newEndLine < height && charsToCopy > 0) {
endOfLine = raster.getDataElements(oldend.column, oldEndLine, charsToCopy, 1, null);
}
// this never modifies any of the lines containing the modified text.
if (addedLines != 0) {
int ol = getScaledLine(oldend.line + 1, scale);
int nl = getScaledLine(newend.line + 1, scale);
int fh = height - ol;
int th = height - nl;
if (fh > 0 && th > 0) {
BufferedImage from = img.getSubimage(0, ol, width, fh);
BufferedImage to = img.getSubimage(0, nl, width, th);
if (addedLines > 0)
moveDataDown(from, to);
else
moveDataUp(from, to);
}
}
// 1. clear first line chars at end of line
// 2. clear middle lines
// 3. clear last line chars at beginning of line
// 4. copy line data at old end to new end
// 5. re-render any data which was not copied because of insufficient
// window width
// 1.
int toFill = 0;
if (affected > 1) {
toFill = width - Math.min(width, start.column);
} else if (start.column < newend.column) {
toFill = Math.min(width - start.column, newend.column - start.column);
}
if (toFill > 0) {
img.setRGB(start.column, getScaledLine(start.line, scale), toFill, 1, emptyLine, 0, toFill);
}
if (newend.line != start.line) {
// 2.
int last = getScaledLine(Math.min(newend.line, height - 1) - 1, scale);
for (int i = getScaledLine(start.line + 1, scale); i <= last; i++) {
img.setRGB(0, i, width, 1, emptyLine, 0, width);
}
// 3.
if (newEndLine < height) {
int toFillEnd = Math.min(width, newend.column);
img.setRGB(0, newEndLine, toFillEnd, 1, emptyLine, 0, toFillEnd);
}
}
// 4.
if (endOfLine != null) {
// copy old end of line data to new end of line
raster.setDataElements(newend.column, newEndLine, charsToCopy, 1, endOfLine);
// clear the rest of the line, if necessary
int diff = needsFilling - charsToCopy;
if (diff > 0) {
img.setRGB(newend.column + charsToCopy, newEndLine, diff, 1, emptyLine, 0, diff);
}
}
// 5.
int minCharsToCopy = Math.max(0, charsToCopy);
int missing = needsFilling - minCharsToCopy;
if (missing > 0) {
int toClear = newend.column + minCharsToCopy;
raster.setDataElements(toClear, newEndLine, width - toClear, 1, emptyLine);
// re-render the last line, since we don't know what the data on
// that line was, since it was past our right margin
int renderWidth = renderRestOfLineToImg(offset + newLength + minCharsToCopy);
int clearx = newend.column + minCharsToCopy + renderWidth;
if (clearx < width) {
raster.setDataElements(clearx, newEndLine, width - clearx, 1, emptyLine);
}
}
// render the new text
final CharSequence nc = e.getNewFragment();
renderToImg(nc, 0, nc.length(), start);
// repaint the changed region
final Rectangle toRepaint = getImgRepaintRect(offset, Math.max(newLength, oldLength));
if (affected > 1) {
toRepaint.height = visibleImgHeight - toRepaint.y;
}
listener.shouldRepaint(this, toRepaint);
}
use of java.awt.image.WritableRaster in project scriptographer by scriptographer.
the class Raster method createCompatibleImage.
/**
* @jshide
*/
public BufferedImage createCompatibleImage(int width, int height) {
ColorModel cm = getColorModel();
WritableRaster raster = cm.createCompatibleWritableRaster(width, height);
return new BufferedImage(cm, raster, false, null);
}
use of java.awt.image.WritableRaster in project scriptographer by scriptographer.
the class Raster method getAverageColor.
/**
* @jshide
*/
public Color getAverageColor(Shape shape) {
// Rectangle2D rect = shape.getBounds2D();
GeneralPath path;
int width = getWidth();
int height = getHeight();
int startX = 0;
int startY = 0;
if (shape != null) {
Matrix inverse = getInverseMatrix();
if (inverse == null)
return null;
// Create a transformed path. This is faster than
// path.clone() / path.transform(at);
PathIterator pi = shape.getPathIterator(inverse.toAffineTransform());
path = new GeneralPath();
path.setWindingRule(pi.getWindingRule());
path.append(pi, false);
Rectangle2D bounds = path.getBounds2D();
// Fetch the sub image to iterate over and calculate average colors
// from
// Crop to the maximum size.
Rectangle2D.intersect(bounds, new Rectangle2D.Double(startX, startY, width, height), bounds);
width = (int) Math.ceil(bounds.getWidth());
height = (int) Math.ceil(bounds.getHeight());
// Are we completely outside the raster? If so, return null
if (width <= 0 || height <= 0)
return null;
startX = (int) Math.floor(bounds.getX());
startY = (int) Math.floor(bounds.getY());
} else {
path = null;
}
BufferedImage img = getSubImage(startX, startY, width, height);
// Raster check = new Raster(img);
// check.setPosition(rect.getCenterX(), rect.getCenterY());
WritableRaster raster = img.getRaster();
byte[] data = (byte[]) raster.getDataElements(0, 0, null);
float[] components = new float[data.length];
for (int i = 0; i < data.length; i++) components[i] = data[i] & 0xff;
long total = 1;
for (int y = 0; y < height; y++) {
for (int x = (y == 0) ? 1 : 0; x < width; x++) {
if (path == null || path.contains(x + startX, y + startY)) {
data = (byte[]) raster.getDataElements(x, height - 1 - y, data);
for (int i = 0; i < data.length; i++) components[i] += data[i] & 0xff;
total++;
}
}
}
total *= 255;
for (int i = 0; i < components.length; i++) components[i] = components[i] / total;
// Return colors
if (components.length == 4)
return new CMYKColor(components);
else if (components.length == 3)
return new RGBColor(components);
else
return new GrayColor(components);
}
use of java.awt.image.WritableRaster in project libgdx by libgdx.
the class PreAlpha method generatePremultiplyAlpha.
private void generatePremultiplyAlpha(File out) {
try {
BufferedImage outImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB);
float[] color = new float[4];
WritableRaster raster = image.getRaster();
WritableRaster outRaster = outImage.getRaster();
for (int x = 0, w = image.getWidth(); x < w; ++x) for (int y = 0, h = image.getHeight(); y < h; ++y) {
raster.getPixel(x, y, color);
float alpha = color[3] / 255f;
for (int i = 0; i < 3; ++i) color[i] *= alpha;
outRaster.setPixel(x, y, color);
}
ImageIO.write(outImage, "png", out);
} catch (IOException e) {
e.printStackTrace();
}
}
use of java.awt.image.WritableRaster in project libgdx by libgdx.
the class GlyphPage method renderGlyph.
/** Loads a single glyph to the backing texture, if it fits. */
private boolean renderGlyph(Glyph glyph, int pageX, int pageY, int width, int height) {
scratchGraphics.setComposite(AlphaComposite.Clear);
scratchGraphics.fillRect(0, 0, MAX_GLYPH_SIZE, MAX_GLYPH_SIZE);
scratchGraphics.setComposite(AlphaComposite.SrcOver);
ByteBuffer glyphPixels = scratchByteBuffer;
int format;
if (unicodeFont.getRenderType() == RenderType.FreeType && unicodeFont.bitmapFont != null) {
BitmapFontData data = unicodeFont.bitmapFont.getData();
BitmapFont.Glyph g = data.getGlyph((char) glyph.getCodePoint());
Pixmap fontPixmap = unicodeFont.bitmapFont.getRegions().get(g.page).getTexture().getTextureData().consumePixmap();
int fontWidth = fontPixmap.getWidth();
int padTop = unicodeFont.getPaddingTop(), padBottom = unicodeFont.getPaddingBottom();
int padLeftBytes = unicodeFont.getPaddingLeft() * 4;
int padXBytes = padLeftBytes + unicodeFont.getPaddingRight() * 4;
int glyphRowBytes = width * 4, fontRowBytes = g.width * 4;
ByteBuffer fontPixels = fontPixmap.getPixels();
byte[] row = new byte[glyphRowBytes];
glyphPixels.position(0);
for (int i = 0; i < padTop; i++) glyphPixels.put(row);
glyphPixels.position((height - padBottom) * glyphRowBytes);
for (int i = 0; i < padBottom; i++) glyphPixels.put(row);
glyphPixels.position(padTop * glyphRowBytes);
for (int y = 0, n = g.height; y < n; y++) {
fontPixels.position(((g.srcY + y) * fontWidth + g.srcX) * 4);
fontPixels.get(row, padLeftBytes, fontRowBytes);
glyphPixels.put(row);
}
fontPixels.position(0);
glyphPixels.position(height * glyphRowBytes);
glyphPixels.flip();
format = GL11.GL_RGBA;
} else {
// Draw the glyph to the scratch image using Java2D.
if (unicodeFont.getRenderType() == RenderType.Native) {
for (Iterator iter = unicodeFont.getEffects().iterator(); iter.hasNext(); ) {
Effect effect = (Effect) iter.next();
if (effect instanceof ColorEffect)
scratchGraphics.setColor(((ColorEffect) effect).getColor());
}
scratchGraphics.setColor(java.awt.Color.white);
scratchGraphics.setFont(unicodeFont.getFont());
scratchGraphics.drawString("" + (char) glyph.getCodePoint(), 0, unicodeFont.getAscent());
} else if (unicodeFont.getRenderType() == RenderType.Java) {
scratchGraphics.setColor(java.awt.Color.white);
for (Iterator iter = unicodeFont.getEffects().iterator(); iter.hasNext(); ) ((Effect) iter.next()).draw(scratchImage, scratchGraphics, unicodeFont, glyph);
// The shape will never be needed again.
glyph.setShape(null);
}
width = Math.min(width, texture.getWidth());
height = Math.min(height, texture.getHeight());
WritableRaster raster = scratchImage.getRaster();
int[] row = new int[width];
for (int y = 0; y < height; y++) {
raster.getDataElements(0, y, width, 1, row);
scratchIntBuffer.put(row);
}
format = GL12.GL_BGRA;
}
// Simple deduplication, doesn't work across pages of course.
String hash = "";
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(glyphPixels);
BigInteger bigInt = new BigInteger(1, md.digest());
hash = bigInt.toString(16);
} catch (NoSuchAlgorithmException ex) {
}
scratchByteBuffer.clear();
scratchIntBuffer.clear();
try {
for (int i = 0, n = hashes.size(); i < n; i++) {
String other = hashes.get(i);
if (other.equals(hash)) {
Glyph dupe = pageGlyphs.get(i);
glyph.setTexture(dupe.texture, dupe.u, dupe.v, dupe.u2, dupe.v2);
return false;
}
}
} finally {
hashes.add(hash);
pageGlyphs.add(glyph);
}
Gdx.gl.glTexSubImage2D(texture.glTarget, 0, pageX, pageY, width, height, format, GL11.GL_UNSIGNED_BYTE, glyphPixels);
float u = pageX / (float) texture.getWidth();
float v = pageY / (float) texture.getHeight();
float u2 = (pageX + width) / (float) texture.getWidth();
float v2 = (pageY + height) / (float) texture.getHeight();
glyph.setTexture(texture, u, v, u2, v2);
return true;
}
Aggregations