📄 pdfgraphics2d.java
字号:
} /** * @see Graphics#drawImage(Image, int, int, int, int, int, int, int, int, ImageObserver) */ public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver observer) { return drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null, observer); } /** * @see Graphics#drawImage(Image, int, int, int, int, int, int, int, int, Color, ImageObserver) */ public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, Color bgcolor, ImageObserver observer) { double dwidth = (double)dx2-dx1; double dheight = (double)dy2-dy1; double swidth = (double)sx2-sx1; double sheight = (double)sy2-sy1; //if either width or height is 0, then there is nothing to draw if (dwidth == 0 || dheight == 0 || swidth == 0 || sheight == 0) return true; double scalex = dwidth/swidth; double scaley = dheight/sheight; double transx = sx1*scalex; double transy = sy1*scaley; AffineTransform tx = AffineTransform.getTranslateInstance(dx1-transx,dy1-transy); tx.scale(scalex,scaley); BufferedImage mask = new BufferedImage(img.getWidth(observer), img.getHeight(observer), BufferedImage.TYPE_BYTE_BINARY); Graphics g = mask.getGraphics(); g.fillRect(sx1,sy1, (int)swidth, (int)sheight); drawImage(img, mask, tx, null, observer); return true; } /** * @see Graphics#dispose() */ public void dispose() { if (kid) return; if (!disposeCalled) { disposeCalled = true; cb.restoreState(); cb.restoreState(); for (int k = 0; k < kids.size(); ++k) { PdfGraphics2D g2 = (PdfGraphics2D)kids.get(k); g2.cb.restoreState(); g2.cb.restoreState(); cb.add(g2.cb); } } } /////////////////////////////////////////////// // // // implementation specific methods // // private void followPath(Shape s, int drawType) { if (s==null) return; if (drawType==STROKE) { s = stroke.createStrokedShape(s); followPath(s, FILL); return; } cb.newPath(); PathIterator points; if (drawType == CLIP) points = s.getPathIterator(IDENTITY); else points = s.getPathIterator(transform); float[] coords = new float[6]; while(!points.isDone()) { int segtype = points.currentSegment(coords); normalizeY(coords); switch(segtype) { case PathIterator.SEG_CLOSE: cb.closePath(); break; case PathIterator.SEG_CUBICTO: cb.curveTo(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]); break; case PathIterator.SEG_LINETO: cb.lineTo(coords[0], coords[1]); break; case PathIterator.SEG_MOVETO: cb.moveTo(coords[0], coords[1]); break; case PathIterator.SEG_QUADTO: cb.curveTo(coords[0], coords[1], coords[2], coords[3]); break; } points.next(); } if (drawType==FILL) { if (points.getWindingRule()==PathIterator.WIND_EVEN_ODD) { cb.eoFill(); } else { cb.fill(); } } else { //drawType==CLIP if (points.getWindingRule()==PathIterator.WIND_EVEN_ODD) { cb.eoClip(); } else { cb.clip(); } } cb.newPath(); } private float normalizeY(float y) { return this.height - y; } private void normalizeY(float[] coords) { coords[1] = normalizeY(coords[1]); coords[3] = normalizeY(coords[3]); coords[5] = normalizeY(coords[5]); } private AffineTransform normalizeMatrix() { double[] mx = new double[6]; AffineTransform result = AffineTransform.getTranslateInstance(0,0); result.getMatrix(mx); mx[3]=-1; mx[5]=height; result = new AffineTransform(mx); result.concatenate(transform); return result; } private boolean drawImage(Image img, Image mask, AffineTransform xform, Color bgColor, ImageObserver obs) { if (xform==null) return true; xform.translate(0, img.getHeight(obs)); xform.scale(img.getWidth(obs), img.getHeight(obs)); AffineTransform inverse = this.normalizeMatrix(); AffineTransform flipper = AffineTransform.getScaleInstance(1,-1); inverse.concatenate(xform); inverse.concatenate(flipper); double[] mx = new double[6]; inverse.getMatrix(mx); try { com.lowagie.text.Image image = com.lowagie.text.Image.getInstance(img, bgColor); if (mask!=null) { com.lowagie.text.Image msk = com.lowagie.text.Image.getInstance(mask, null, true); msk.makeMask(); msk.setInvertMask(true); image.setImageMask(msk); } cb.addImage(image, (float)mx[0], (float)mx[1], (float)mx[2], (float)mx[3], (float)mx[4], (float)mx[5]); } catch (Exception ex) { throw new IllegalArgumentException(); } return true; } private void setPaint(Paint paint, boolean invert, double xoffset, double yoffset) { this.paint = paint; if (paint instanceof Color) { cb.setColorFill((Color)paint); } else if (paint instanceof GradientPaint) { GradientPaint gp = (GradientPaint)paint; Point2D p1 = gp.getPoint1(); transform.transform(p1, p1); Point2D p2 = gp.getPoint2(); transform.transform(p2, p2); Color c1 = gp.getColor1(); Color c2 = gp.getColor2(); PdfShading shading = PdfShading.simpleAxial(cb.getPdfWriter(), (float)p1.getX(), (float)p1.getY(), (float)p2.getX(), (float)p2.getY(), c1, c2); PdfShadingPattern pat = new PdfShadingPattern(shading); cb.setShadingFill(pat); } else { try { BufferedImage img = null; int type = BufferedImage.TYPE_4BYTE_ABGR; if (paint.getTransparency() == Transparency.OPAQUE) { type = BufferedImage.TYPE_3BYTE_BGR; } img = new BufferedImage((int)width, (int)height, type); Graphics2D g = (Graphics2D)img.getGraphics(); Shape fillRect = new Rectangle2D.Double(0,0,img.getWidth(), img.getHeight()); g.setPaint(paint); g.fill(fillRect); if (invert) { AffineTransform tx = new AffineTransform(); tx.scale(1,-1); tx.translate(-xoffset,-yoffset); g.drawImage(img,tx,null); } com.lowagie.text.Image image = com.lowagie.text.Image.getInstance(img, null); PdfPatternPainter pattern = cb.createPattern(width, height); image.setAbsolutePosition(0,0); pattern.addImage(image); cb.setPatternFill(pattern); } catch (Exception ex) { cb.setColorFill(Color.gray); } } } /////////////////////////////////////////////// // // // PdfFontMetrics class // // class PdfFontMetrics extends FontMetrics { private BaseFont bf; private float fontSize; private int ascent = -1; private int descent = -1; private int leading = -1; private int maxAdvance = -1; private int widths[]; private double scaleX; private double scaleY; private PdfFontMetrics(Font f, BaseFont bf) { super(f); this.bf = bf; this.fontSize = f.getSize2D(); AffineTransform af = f.getTransform(); scaleX = af.getScaleX(); scaleY = af.getScaleY(); } public int getAscent() { if (ascent < 0) ascent = (int)(bf.getFontDescriptor(BaseFont.AWT_ASCENT, fontSize) * scaleY); return ascent; } public int getDescent() { if (descent < 0) descent = -(int)(bf.getFontDescriptor(BaseFont.AWT_DESCENT, fontSize) * scaleY); return descent; } public int getLeading() { if (leading < 0) leading = (int)(bf.getFontDescriptor(BaseFont.AWT_LEADING, fontSize) * scaleY); return leading; } public int getMaxAdvance() { if (maxAdvance < 0) maxAdvance = (int)(bf.getFontDescriptor(BaseFont.AWT_MAXADVANCE, fontSize) * scaleX); return maxAdvance; } public int[] getWidths() { if (widths == null) { widths = new int[256]; for (char ch = 0 ; ch < 256 ; ch++) { widths[ch] = charWidth(ch); } } return widths; } public int charWidth(char c) { return (int)(bf.getWidthPoint(c, fontSize) * scaleX); } public int stringWidth(String s) { return (int)(bf.getWidthPoint(s, fontSize) * scaleX); } /** * Returns the bounds of the specified <code>String</code> in the * specified <code>Graphics</code> context. The bounds is used * to layout the <code>String</code>. * @param str the specified <code>String</code> * @param context the specified <code>Graphics</code> context * @return a {@link Rectangle2D} that is the bounding box of the * specified <code>String</code> in the specified * <code>Graphics</code> context. * @see java.awt.Font#getStringBounds(String, FontRenderContext) */ public Rectangle2D getStringBounds( String str, Graphics context) { char[] array = str.toCharArray(); return getStringBounds(array, 0, array.length, context); } /** * Returns the bounds of the specified <code>String</code> in the * specified <code>Graphics</code> context. The bounds is used * to layout the <code>String</code>. * @param str the specified <code>String</code> * @param beginIndex the offset of the beginning of <code>str</code> * @param limit the length of <code>str</code> * @param context the specified <code>Graphics</code> context * @return a <code>Rectangle2D</code> that is the bounding box of the * specified <code>String</code> in the specified * <code>Graphics</code> context. * @see java.awt.Font#getStringBounds(String, int, int, FontRenderContext) */ public Rectangle2D getStringBounds( String str, int beginIndex, int limit, Graphics context) { String substr = str.substring(beginIndex, limit); return getStringBounds(substr, context); } /** * Returns the bounds of the specified array of characters * in the specified <code>Graphics</code> context. * The bounds is used to layout the <code>String</code> * created with the specified array of characters, * <code>beginIndex</code> and <code>limit</code>. * @param chars an array of characters * @param beginIndex the initial offset of the array of * characters * @param limit the length of the array of characters * @param context the specified <code>Graphics</code> context * @return a <code>Rectangle2D</code> that is the bounding box of the * specified character array in the specified * <code>Graphics</code> context. * @see java.awt.Font#getStringBounds(char[], int, int, FontRenderContext) */ public Rectangle2D getStringBounds(char chars[], int beginIndex, int limit, Graphics context) { if (beginIndex < 0) { throw new IndexOutOfBoundsException("beginIndex: " + beginIndex); } if (limit > chars.length) { throw new IndexOutOfBoundsException("limit: " + limit); } if (beginIndex > limit) { throw new IndexOutOfBoundsException("range length: " + (limit - beginIndex)); } String str = new String(chars, beginIndex, limit - beginIndex); return new Rectangle2D.Float(0, -ascent, (float)(bf.getWidthPoint(str, fontSize) * scaleX), getHeight()); } /** * Returns the bounds of the characters indexed in the specified * <code>CharacterIterator</code> in the * specified <code>Graphics</code> context. * @param ci the specified <code>CharacterIterator</code> * @param beginIndex the initial offset in <code>ci</code> * @param limit the end index of <code>ci</code> * @param context the specified <code>Graphics</code> context * @return a <code>Rectangle2D</code> that is the bounding box of the * characters indexed in the specified <code>CharacterIterator</code> * in the specified <code>Graphics</code> context. * @see java.awt.Font#getStringBounds(CharacterIterator, int, int, FontRenderContext) */ public Rectangle2D getStringBounds(CharacterIterator ci, int beginIndex, int limit, Graphics context) { int start = ci.getBeginIndex(); int end = ci.getEndIndex(); if (beginIndex < start) { throw new IndexOutOfBoundsException("beginIndex: " + beginIndex); } if (limit > end) { throw new IndexOutOfBoundsException("limit: " + limit); } if (beginIndex > limit) { throw new IndexOutOfBoundsException("range length: " + (limit - beginIndex)); } char[] arr = new char[limit - beginIndex]; ci.setIndex(beginIndex); for(int idx = 0; idx < arr.length; idx++) { arr[idx] = ci.current(); ci.next(); } return getStringBounds(arr,0,arr.length,context); } /** * Returns the bounds for the character with the maximum bounds * in the specified <code>Graphics</code> context. * @param context the specified <code>Graphics</code> context * @return a <code>Rectangle2D</code> that is the * bounding box for the character with the maximum bounds. * @see java.awt.Font#getMaxCharBounds(FontRenderContext) */ public Rectangle2D getMaxCharBounds(Graphics context) { return getStringBounds("M", context); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -