X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=src%2Forg%2Fxwt%2FPixelBuffer.java;h=9bb41be98f87fc0e5f7705de41935bd75ecbed3a;hb=8ca06b850fb51673a7cfe751643ea45ec528070d;hp=5e78e988f2521da0a3280e1e6cefab0d3e21c2a7;hpb=55c3195af733f3de6b7894f4c4a96f7b50f58c11;p=org.ibex.core.git diff --git a/src/org/xwt/PixelBuffer.java b/src/org/xwt/PixelBuffer.java index 5e78e98..9bb41be 100644 --- a/src/org/xwt/PixelBuffer.java +++ b/src/org/xwt/PixelBuffer.java @@ -3,9 +3,7 @@ package org.xwt; /** *

- * A block of pixels which can be drawn on and rapidly copied to the - * screen. Drawing operations are performed on this class; it is - * then rendered to the screen with Surface.blit(). + * A block of pixels which can be drawn on. *

* *

@@ -16,28 +14,76 @@ package org.xwt; *

* *

- * A note on coordinates: all members on PixelBuffer specify - * coordinates in terms of x1,y1,x2,y2 even though the Box class - * represents regions internally as x,y,w,h. + * Many of these functions come in pairs, one that uses ints and one + * that uses floats. The int functions are intended for situations + * in which the CTM is the identity transform. *

*/ public abstract class PixelBuffer { - /** Draw the region of source within (sx1, sy1, sx2, sy2) onto the region of this PixelBuffer within (dx1, dy1, dx2, dy2), scaling as needed. */ + /** Draw the region of source within s onto the region d on this PixelBuffer, scaling as needed */ public abstract void drawPicture(Picture source, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2); - /** Draw source onto this PixelBuffer at (x,y) */ - public abstract void drawPicture(Picture source, int x, int y); + /** fill a trapezoid whose top and bottom edges are horizontal */ + public abstract void fillTrapezoid(int x1, int x2, int y1, int x3, int x4, int y2, int color); - /** Draw text in font and color on this PixelBuffer, with the upper left corner of the text at (x, y) */ - public abstract void drawString(String font, String text, int x, int y, int color); + /** + * Same as drawPicture, but only uses the alpha channel of the Picture, and is allowed to destructively modify the RGB + * channels of the Picture in the process. This method may assume that the RGB channels of the image are all zero IFF it + * restores this invariant before returning. + */ + public abstract void drawPictureAlphaOnly(Picture source, int dx1, int dy1, int dx2, int dy2, + int sx1, int sy1, int sx2, int sy2, int rgb); - /** Fill the region (x1, y1, x2, y2) with color (AARRGGBB format); the alpha channel component is ignored */ - public abstract void fillRect(int x1, int y1, int x2, int y2, int color); + // FIXME: we want floats (inter-pixel spacing) for antialiasing, but this hoses the fastpath line drawing... argh! + /** draws a line of width w; note that the coordinates here are post-transform */ + public void drawLine(int x1, int y1, int x2, int y2, int w, int color, boolean capped) { - /** Sets the clip region for this PixelBuffer to (x,y,x2,y2) */ - public abstract void setClip(int x, int y, int x2, int y2); + if (y1 > y2) { int t = x1; x1 = x2; x2 = t; t = y1; y1 = y2; y2 = t; } + + if (x1 == x2) { + fillTrapezoid(x1 - w / 2, x2 + w / 2, y1 - (capped ? w / 2 : 0), x1 - w / 2, x2 + w / 2, y2 + (capped ? w / 2 : 0), color); + return; + } + + // fastpath for single-pixel width lines + if (w == 1) { + float slope = (float)(y2 - y1) / (float)(x2 - x1); + int last_x = x1; + for(int y=y1; y<=y2; y++) { + int new_x = (int)((float)(y - y1) / slope) + x1; + if (slope >= 0) fillTrapezoid(last_x + 1, y != y2 ? new_x + 1 : new_x, y, + last_x + 1, y != y2 ? new_x + 1 : new_x, y + 1, color); + else fillTrapezoid(y != y2 ? new_x : new_x + 1, last_x, y, + y != y2 ? new_x : new_x + 1, last_x, y + 1, color); + last_x = new_x; + } + return; + } + + // actually half-width + float width = (float)w / 2; + float phi = (float)Math.atan((y2 - y1) / (x2 - x1)); + if (phi < 0.0) phi += (float)Math.PI * 2; + float theta = (float)Math.PI / 2 - phi; + + // dx and dy are the x and y distance between each endpoint and the corner of the stroke + int dx = (int)(width * Math.cos(theta)); + int dy = (int)(width * Math.sin(theta)); + + // slice is the longest possible length of a horizontal line across the stroke + int slice = (int)(2 * width / Math.cos(theta)); + + if (capped) { + x1 -= width * Math.cos(phi); + x2 += width * Math.cos(phi); + y1 -= width * Math.sin(phi); + y2 += width * Math.sin(phi); + } + + fillTrapezoid(x1 + dx, x1 + dx, y1 - dy, x1 - dx, x1 - dx + slice, y1 + dy, color); // top corner + fillTrapezoid(x2 + dx - slice, x2 + dx, y2 - dy, x2 - dx, x2 - dx, y2 + dy, color); // bottom corner + fillTrapezoid(x1 - dx, x1 - dx + slice, y1 + dy, x2 + dx - slice, x2 + dx, y2 - dy, color); // middle + } - public abstract int getHeight(); - public abstract int getWidth(); }