📄 gdkgraphics2d.java
字号:
} private void stateRestore() { ((DrawState) (stateStack.pop())).restore(this); cairoRestore(); } // Some operations (drawing rather than filling) require that their // coords be shifted to land on 0.5-pixel boundaries, in order to land on // "middle of pixel" coordinates and light up complete pixels. private boolean shiftDrawCalls = false; private double shifted(double coord, boolean doShift) { if (doShift) return Math.floor(coord) + 0.5; else return coord; } private void walkPath(PathIterator p, boolean doShift) { double x = 0; double y = 0; double[] coords = new double[6]; cairoSetFillRule(p.getWindingRule()); for (; ! p.isDone(); p.next()) { int seg = p.currentSegment(coords); switch (seg) { case PathIterator.SEG_MOVETO: x = shifted(coords[0], doShift); y = shifted(coords[1], doShift); cairoMoveTo(x, y); break; case PathIterator.SEG_LINETO: x = shifted(coords[0], doShift); y = shifted(coords[1], doShift); cairoLineTo(x, y); break; case PathIterator.SEG_QUADTO: // splitting a quadratic bezier into a cubic: // see: http://pfaedit.sourceforge.net/bezier.html double x1 = x + (2.0 / 3.0) * (shifted(coords[0], doShift) - x); double y1 = y + (2.0 / 3.0) * (shifted(coords[1], doShift) - y); double x2 = x1 + (1.0 / 3.0) * (shifted(coords[2], doShift) - x); double y2 = y1 + (1.0 / 3.0) * (shifted(coords[3], doShift) - y); x = shifted(coords[2], doShift); y = shifted(coords[3], doShift); cairoCurveTo(x1, y1, x2, y2, x, y); break; case PathIterator.SEG_CUBICTO: x = shifted(coords[4], doShift); y = shifted(coords[5], doShift); cairoCurveTo(shifted(coords[0], doShift), shifted(coords[1], doShift), shifted(coords[2], doShift), shifted(coords[3], doShift), x, y); break; case PathIterator.SEG_CLOSE: cairoClosePath(); break; } } } private Map getDefaultHints() { HashMap defaultHints = new HashMap(); defaultHints.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT); defaultHints.put(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT); defaultHints.put(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_OFF); defaultHints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); defaultHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_DEFAULT); return defaultHints; } public static int[] findSimpleIntegerArray (ColorModel cm, Raster raster) { if (cm == null || raster == null) return null; if (! cm.getColorSpace().isCS_sRGB()) return null; if (! (cm instanceof DirectColorModel)) return null; DirectColorModel dcm = (DirectColorModel) cm; if (dcm.getRedMask() != 0x00FF0000 || dcm.getGreenMask() != 0x0000FF00 || dcm.getBlueMask() != 0x000000FF) return null; if (! (raster instanceof WritableRaster)) return null; if (raster.getSampleModel().getDataType() != DataBuffer.TYPE_INT) return null; if (! (raster.getDataBuffer() instanceof DataBufferInt)) return null; DataBufferInt db = (DataBufferInt) raster.getDataBuffer(); if (db.getNumBanks() != 1) return null; // Finally, we have determined that this is a single bank, [A]RGB-int // buffer in sRGB space. It's worth checking all this, because it means // that cairo can paint directly into the data buffer, which is very // fast compared to all the normal copying and converting. return db.getData(); } private void updateBufferedImage() { if (bimage != null && pixelConversionRequired) { int height = bimage.getHeight(); int width = bimage.getWidth(); int index = 0; for (int y = 0; y < height; ++y) for (int x = 0; x < width; ++x) bimage.setRGB(x, y, pixelBuffer[index++]); } } private boolean drawImage(Image img, AffineTransform xform, Color bgcolor, ImageObserver obs) { if (img == null) return false; // FIXME: I'll fix this, /Sven// if (img instanceof GtkOffScreenImage// && img.getGraphics() instanceof GdkGraphics2D// && (xform == null || xform.getType() == AffineTransform.TYPE_IDENTITY// || xform.getType() == AffineTransform.TYPE_TRANSLATION))// {// // we are being asked to flush a double buffer from Gdk// GdkGraphics2D g2 = (GdkGraphics2D) img.getGraphics();// gdkDrawDrawable(g2, (int) xform.getTranslateX(),// (int) xform.getTranslateY());// updateBufferedImage();// return true;// }// else { // In this case, xform is an AffineTransform that transforms bounding // box of the specified image from image space to user space. However // when we pass this transform to cairo, cairo will use this transform // to map "user coordinates" to "pixel" coordinates, which is the // other way around. Therefore to get the "user -> pixel" transform // that cairo wants from "image -> user" transform that we currently // have, we will need to invert the transformation matrix. AffineTransform invertedXform = new AffineTransform(); try { invertedXform = xform.createInverse(); if (img instanceof BufferedImage) { // draw an image which has actually been loaded // into memory fully BufferedImage b = (BufferedImage) img; return drawRaster(b.getColorModel(), b.getTile(0, 0), invertedXform, bgcolor); } else return this.drawImage(GdkPixbufDecoder.createBufferedImage(img .getSource()), xform, bgcolor, obs); } catch (NoninvertibleTransformException e) { throw new ImagingOpException("Unable to invert transform " + xform.toString()); } } } ////////////////////////////////////////////////// ////// Implementation of Graphics2D Methods ////// ////////////////////////////////////////////////// public void draw(Shape s) { if (stroke != null && ! (stroke instanceof BasicStroke)) { fill(stroke.createStrokedShape(s)); return; } cairoNewPath(); if (s instanceof Rectangle2D) { Rectangle2D r = (Rectangle2D) s; cairoRectangle(shifted(r.getX(), shiftDrawCalls), shifted(r.getY(), shiftDrawCalls), r.getWidth(), r.getHeight()); } else walkPath(s.getPathIterator(null), shiftDrawCalls); cairoStroke(); updateBufferedImage(); } public void fill(Shape s) { cairoNewPath(); if (s instanceof Rectangle2D) { Rectangle2D r = (Rectangle2D) s; cairoRectangle(r.getX(), r.getY(), r.getWidth(), r.getHeight()); } else walkPath(s.getPathIterator(null), false); cairoFill(); updateBufferedImage(); } public void clip(Shape s) { // update it if (clip == null || s == null) clip = s; else if (s instanceof Rectangle2D && clip instanceof Rectangle2D) { Rectangle2D r = (Rectangle2D) s; Rectangle2D curr = (Rectangle2D) clip; clip = curr.createIntersection(r); } else throw new UnsupportedOperationException(); // draw it if (clip != null) { cairoNewPath(); if (clip instanceof Rectangle2D) { Rectangle2D r = (Rectangle2D) clip; cairoRectangle(r.getX(), r.getY(), r.getWidth(), r.getHeight()); } else walkPath(clip.getPathIterator(null), false); // cairoClosePath (); cairoClip(); } } public Paint getPaint() { return paint; } public AffineTransform getTransform() { return (AffineTransform) transform.clone(); } public void setPaint(Paint p) { if (paint == null) return; paint = p; if (paint instanceof Color) { setColor((Color) paint); } else if (paint instanceof TexturePaint) { TexturePaint tp = (TexturePaint) paint; BufferedImage img = tp.getImage(); // map the image to the anchor rectangle int width = (int) tp.getAnchorRect().getWidth(); int height = (int) tp.getAnchorRect().getHeight(); double scaleX = width / (double) img.getWidth(); double scaleY = width / (double) img.getHeight(); AffineTransform at = new AffineTransform(scaleX, 0, 0, scaleY, 0, 0); AffineTransformOp op = new AffineTransformOp(at, getRenderingHints()); BufferedImage texture = op.filter(img, null); int[] pixels = texture.getRGB(0, 0, width, height, null, 0, width); setTexturePixels(pixels, width, height, width); } else if (paint instanceof GradientPaint) { GradientPaint gp = (GradientPaint) paint; Point2D p1 = gp.getPoint1(); Point2D p2 = gp.getPoint2(); Color c1 = gp.getColor1(); Color c2 = gp.getColor2(); setGradient(p1.getX(), p1.getY(), p2.getX(), p2.getY(), c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha(), c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha(), gp.isCyclic()); } else throw new java.lang.UnsupportedOperationException(); } public void setPaintUnlocked(Paint p) { if (paint == null) return; paint = p; if (paint instanceof Color) { setColorUnlocked((Color) paint); } else if (paint instanceof TexturePaint) { TexturePaint tp = (TexturePaint) paint; BufferedImage img = tp.getImage(); // map the image to the anchor rectangle int width = (int) tp.getAnchorRect().getWidth(); int height = (int) tp.getAnchorRect().getHeight(); double scaleX = width / (double) img.getWidth(); double scaleY = width / (double) img.getHeight(); AffineTransform at = new AffineTransform(scaleX, 0, 0, scaleY, 0, 0); AffineTransformOp op = new AffineTransformOp(at, getRenderingHints()); BufferedImage texture = op.filter(img, null); int[] pixels = texture.getRGB(0, 0, width, height, null, 0, width); setTexturePixelsUnlocked(pixels, width, height, width); } else if (paint instanceof GradientPaint) { GradientPaint gp = (GradientPaint) paint; Point2D p1 = gp.getPoint1(); Point2D p2 = gp.getPoint2(); Color c1 = gp.getColor1(); Color c2 = gp.getColor2(); setGradientUnlocked(p1.getX(), p1.getY(), p2.getX(), p2.getY(), c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha(), c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha(), gp.isCyclic()); } else throw new java.lang.UnsupportedOperationException(); } public void setTransform(AffineTransform tx) { transform = tx; if (transform != null) { double[] m = new double[6]; transform.getMatrix(m); cairoSetMatrix(m); } } public void setTransformUnlocked(AffineTransform tx) { transform = tx; if (transform != null) { double[] m = new double[6]; transform.getMatrix(m); cairoSetMatrixUnlocked(m); } } public void transform(AffineTransform tx) { if (transform == null) transform = new AffineTransform(tx); else transform.concatenate(tx); setTransform(transform); if (clip != null) { // FIXME: this should actuall try to transform the shape // rather than degrade to bounds. Rectangle2D r = clip.getBounds2D(); double[] coords = new double[] { r.getX(), r.getY(), r.getX() + r.getWidth(), r.getY() + r.getHeight() }; try { tx.createInverse().transform(coords, 0, coords, 0, 2); r.setRect(coords[0], coords[1], coords[2] - coords[0], coords[3] - coords[1]); clip = r; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -