/** * Synchronize the textLayout and the shape (=frame box, by calling syncFrame) with the model When * <code>TextLayout</code> is used, this delegates to <code>getRotation()</code> where computing * rotation angle is concerned, and updates the AffineTransform returned by <code> * getTextToModelTransform()</code>. */ protected void syncShape() { PicText te = (PicText) element; // textLayout = new TextLayout(te.getText().length()==0 ? " " : te.getText(), // textFont, // new FontRenderContext(null,false,false)); text2ModelTr.setToIdentity(); // reset PicPoint anchor = te.getCtrlPt(TextEditable.P_ANCHOR, ptBuf); text2ModelTr.rotate(getRotation(), anchor.x, anchor.y); // rotate along P_ANCHOR ! // the reference point of an image is the top-left one, but the refpoint of a text layout is on // the baseline if (image != null) { text2ModelTr.translate(te.getLeftX(), te.getTopY()); if (te.getWidth() != 0 && image.getWidth() != 0 && (te.getDepth() + te.getHeight()) != 0 && image.getHeight() != 0) text2ModelTr.scale( te.getWidth() / image.getWidth(), -(te.getHeight() + te.getDepth()) / image.getHeight()); } else { // Hack ? Just cheating a little bit ? Ou juste ruse ? // we want here to use the dimensions of the textLayout instead of latex dimensions if // areDimensionsComputed // sinon on va aligner le textlayout en fonction des parametres latex, et l'Utilisateur (qui // est bien bete) ne va rien comprendre. double latexH = 0; double latexD = 0; double latexW = 0; if (areDimensionsComputed) { // store latex dimensions, and setDimensions to textLayout ones latexH = te.getHeight(); latexD = te.getDepth(); latexW = te.getWidth(); te.setDimensions( textLayout.getBounds().getWidth(), textLayout.getAscent(), textLayout.getDescent()); } text2ModelTr.translate(te.getLeftX(), te.getBaseLineY()); if (areDimensionsComputed) { // restore latex dimensions te.setDimensions(latexW, latexH, latexD); } // Autre possibilite= comprimer le texte pour qu'il rentre dans la boite (evite le hack // ci-dessus): // text2ModelTr.scale(te.getWidth()/textLayout.getWidth(),-(te.getHeight()+te.getDepth())/textLayout.getHeight()); text2ModelTr.scale(1.0, -1.0); } syncFrame(); }
// --------------------------------------------------------- private synchronized AffineTransform bufferTransform() { AffineTransform r = new AffineTransform(); for (int i = 0; i < a1.size(); i++) { int s1 = a1.get(i); Object s2 = a2.get(i); Object s3[] = null; if (s2 instanceof Object[]) s3 = (Object[]) s2; if (s1 == setTransform) { r = makeTransform(s2); } if (s1 == shear) r.shear((Double) s3[0], (Double) s3[1]); if (s1 == rotate1) r.rotate((Double) s2); if (s1 == rotate2) r.rotate((Double) s3[0], (Double) s3[1], (Double) s3[2]); if (s1 == scale1) r.scale((Double) s3[0], (Double) s3[1]); if (s1 == translate1) r.translate((Double) s3[0], (Double) s3[1]); if (s1 == translate2) r.translate((Integer) s3[0], (Integer) s3[1]); } return r; }
@Override public void paintComponent(Graphics g) { g.setColor(getBackground()); g.fillRect(0, 0, getWidth(), getHeight()); int w = bufferedImage.getWidth(this); int h = bufferedImage.getHeight(this); if (mode == Flip.NONE) { g.drawImage(bufferedImage, 0, 0, w, h, this); } else if (mode == Flip.VERTICAL) { AffineTransform at = AffineTransform.getScaleInstance(1d, -1d); at.translate(0, -h); Graphics2D g2 = (Graphics2D) g.create(); g2.drawImage(bufferedImage, at, this); g2.dispose(); } else if (mode == Flip.HORIZONTAL) { AffineTransform at = AffineTransform.getScaleInstance(-1d, 1d); at.translate(-w, 0); AffineTransformOp atOp = new AffineTransformOp(at, null); g.drawImage(atOp.filter(bufferedImage, null), 0, 0, w, h, this); } }
private Shape getTextShape() { if (cachedTextShape == null) { String text = getText(); if (text == null || text.length() == 0) { text = " "; } FontRenderContext frc = getFontRenderContext(); HashMap<TextAttribute, Object> textAttributes = new HashMap<TextAttribute, Object>(); textAttributes.put(TextAttribute.FONT, getFont()); if (FONT_UNDERLINE.get(this)) { textAttributes.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON); } TextLayout textLayout = new TextLayout(text, textAttributes, frc); AffineTransform tx = new AffineTransform(); tx.translate(coordinates[0].x, coordinates[0].y); switch (TEXT_ANCHOR.get(this)) { case END: tx.translate(-textLayout.getAdvance(), 0); break; case MIDDLE: tx.translate(-textLayout.getAdvance() / 2d, 0); break; case START: break; } tx.rotate(rotates[0]); /* if (TRANSFORM.get(this) != null) { tx.preConcatenate(TRANSFORM.get(this)); }*/ cachedTextShape = tx.createTransformedShape(textLayout.getOutline(tx)); cachedTextShape = textLayout.getOutline(tx); } return cachedTextShape; }
/** * Zoom, preserving the center point on the screen. (When we draw, the center point may be moved * in order to maximize the amount of image seen on screen.) * */ void adjustZoom(double z, Point2D cp) { if (cp == null) cp = new Point2D.Double(getWidth() / 2, getHeight() / 2); Point2D cxt = componentToImage(cp); double tx = cp.getX() - cxt.getX() * z; double ty = cp.getY() - cxt.getY() * z; t = new AffineTransform(); t.translate(tx, ty); t.scale(z, z); fit = false; repaint(); }
/** * All other write methods delegate their work to here. */ public void write(OutputStream out, java.util.List<Figure> figures) throws IOException { Rectangle2D.Double drawingRect = null; for (Figure f : figures) { if (drawingRect == null) { drawingRect = f.getBounds(); } else { drawingRect.add(f.getBounds()); } } AffineTransform drawingTransform = new AffineTransform(); drawingTransform.translate( -Math.min(0, drawingRect.x), -Math.min(0, drawingRect.y) ); write(out, figures, drawingTransform, new Dimension( (int) (Math.abs(drawingRect.x) + drawingRect.width), (int) (Math.abs(drawingRect.y) + drawingRect.height)) ); }
public static AffineTransform getTransform(String str) throws IOException { AffineTransform t = new AffineTransform(); if (str != null) { StreamTokenizer tt = new StreamTokenizer(new StringReader(str)); tt.resetSyntax(); tt.wordChars('a', 'z'); tt.wordChars('A', 'Z'); tt.wordChars(128 + 32, 255); tt.whitespaceChars(0, ' '); tt.whitespaceChars(',', ','); tt.parseNumbers(); while (tt.nextToken() != StreamTokenizer.TT_EOF) { if (tt.ttype != StreamTokenizer.TT_WORD) { throw new IOException("Illegal transform " + str); } String type = tt.sval; if (tt.nextToken() != '(') { throw new IOException("'(' not found in transform " + str); } if (type.equals("matrix")) { double[] m = new double[6]; for (int i = 0; i < 6; i++) { if (tt.nextToken() != StreamTokenizer.TT_NUMBER) { throw new IOException( "Matrix value " + i + " not found in transform " + str + " token:" + tt.ttype + " " + tt.sval); } if (tt.nextToken() == StreamTokenizer.TT_WORD && tt.sval.startsWith("E")) { double mantissa = tt.nval; tt.nval = Double.valueOf(tt.nval + tt.sval); } else { tt.pushBack(); } m[i] = tt.nval; } t.concatenate(new AffineTransform(m)); } else if (type.equals("translate")) { double tx, ty; if (tt.nextToken() != StreamTokenizer.TT_NUMBER) { throw new IOException("X-translation value not found in transform " + str); } tx = tt.nval; if (tt.nextToken() == StreamTokenizer.TT_NUMBER) { ty = tt.nval; } else { tt.pushBack(); ty = 0; } t.translate(tx, ty); } else if (type.equals("scale")) { double sx, sy; if (tt.nextToken() != StreamTokenizer.TT_NUMBER) { throw new IOException("X-scale value not found in transform " + str); } sx = tt.nval; if (tt.nextToken() == StreamTokenizer.TT_NUMBER) { sy = tt.nval; } else { tt.pushBack(); sy = sx; } t.scale(sx, sy); } else if (type.equals("rotate")) { double angle, cx, cy; if (tt.nextToken() != StreamTokenizer.TT_NUMBER) { throw new IOException("Angle value not found in transform " + str); } angle = tt.nval; if (tt.nextToken() == StreamTokenizer.TT_NUMBER) { cx = tt.nval; if (tt.nextToken() != StreamTokenizer.TT_NUMBER) { throw new IOException("Y-center value not found in transform " + str); } cy = tt.nval; } else { tt.pushBack(); cx = cy = 0; } t.rotate(angle * Math.PI / 180d, cx * Math.PI / 180d, cy * Math.PI / 180d); } else if (type.equals("skewX")) { double angle; if (tt.nextToken() != StreamTokenizer.TT_NUMBER) { throw new IOException("Skew angle not found in transform " + str); } angle = tt.nval; t.concatenate(new AffineTransform(1, 0, Math.tan(angle * Math.PI / 180), 1, 0, 0)); } else if (type.equals("skewY")) { double angle; if (tt.nextToken() != StreamTokenizer.TT_NUMBER) { throw new IOException("Skew angle not found in transform " + str); } angle = tt.nval; t.concatenate(new AffineTransform(1, Math.tan(angle * Math.PI / 180), 0, 1, 0, 0)); } else { throw new IOException("Unknown transform " + type + " in " + str); } if (tt.nextToken() != ')') { throw new IOException("')' not found in transform " + str); } } } return t; }
// Thread's run method aimed at creating a bitmap asynchronously public void run() { Drawing drawing = new Drawing(); PicText rawPicText = new PicText(); String s = ((PicText) element).getText(); rawPicText.setText(s); drawing.add( rawPicText); // bug fix: we must add a CLONE of the PicText, otherwise it loses it former // parent... (then pb with the view ) drawing.setNotparsedCommands( "\\newlength{\\jpicwidth}\\settowidth{\\jpicwidth}{" + s + "}" + CR_LF + "\\newlength{\\jpicheight}\\settoheight{\\jpicheight}{" + s + "}" + CR_LF + "\\newlength{\\jpicdepth}\\settodepth{\\jpicdepth}{" + s + "}" + CR_LF + "\\typeout{JPICEDT INFO: \\the\\jpicwidth, \\the\\jpicheight, \\the\\jpicdepth }" + CR_LF); RunExternalCommand.Command commandToRun = RunExternalCommand.Command.BITMAP_CREATION; // RunExternalCommand command = new RunExternalCommand(drawing, contentType,commandToRun); boolean isWriteTmpTeXfile = true; String bitmapExt = "png"; // [pending] preferences String cmdLine = "{i}/unix/tetex/create_bitmap.sh {p} {f} " + bitmapExt + " " + fileDPI; // [pending] preferences ContentType contentType = getContainer().getContentType(); RunExternalCommand.isGUI = false; // System.out, no dialog box // [pending] debug RunExternalCommand command = new RunExternalCommand(drawing, contentType, cmdLine, isWriteTmpTeXfile); command .run(); // synchronous in an async. thread => it's ok (anyway, we must way until the LaTeX // process has completed) if (wantToComputeLatexDimensions) { // load size of text: try { File logFile = new File(command.getTmpPath(), command.getTmpFilePrefix() + ".log"); BufferedReader reader = null; try { reader = new BufferedReader(new FileReader(logFile)); } catch (FileNotFoundException fnfe) { System.out.println("Cannot find log file! " + fnfe.getMessage()); System.out.println(logFile); } catch (IOException ioex) { System.out.println("Log file IO exception"); ioex.printStackTrace(); } // utile ? System.out.println("Log file created! file=" + logFile); getDimensionsFromLogFile(reader, (PicText) element); syncStringLocation(); // update dimensions syncBounds(); syncFrame(); SwingUtilities.invokeLater( new Thread() { public void run() { repaint(null); } }); // repaint(null); // now that dimensions are available, we force a repaint() [pending] // smart-repaint ? } catch (Exception e) { e.printStackTrace(); } } if (wantToGetBitMap) { // load image: try { File bitmapFile = new File(command.getTmpPath(), command.getTmpFilePrefix() + "." + bitmapExt); this.image = ImageIO.read(bitmapFile); System.out.println( "Bitmap created! file=" + bitmapFile + ", width=" + image.getWidth() + "pixels, height=" + image.getHeight() + "pixels"); if (image == null) return; syncStringLocation(); // sets strx, stry, and dimensions of text syncBounds(); // update the AffineTransform that will be applied to the bitmap before displaying on screen PicText te = (PicText) element; text2ModelTr.setToIdentity(); // reset PicPoint anchor = te.getCtrlPt(TextEditable.P_ANCHOR, ptBuf); text2ModelTr.rotate(getRotation(), anchor.x, anchor.y); // rotate along P_ANCHOR ! text2ModelTr.translate(te.getLeftX(), te.getTopY()); text2ModelTr.scale( te.getWidth() / image.getWidth(), -(te.getHeight() + te.getDepth()) / image.getHeight()); // [pending] should do something special to avoid dividing by 0 or setting a rescaling // factor to 0 [non invertible matrix] (java will throw an exception) syncFrame(); SwingUtilities.invokeLater( new Thread() { public void run() { repaint(null); } }); // repaint(null); // now that bitmap is available, we force a repaint() [pending] // smart-repaint ? } catch (Exception e) { e.printStackTrace(); } } }