?? omtext.java
字號:
ret.append("-*"); // -average width(of each letter, in tenths of a pixel) ret.append("-*"); // -character set(like an ISO designation. ret.append("-*"); // System.out.println("SText.fontString: " + ret); return ret.toString(); } /** * Counts occurences of a character in a string. * * @param str the String * @param ch the character to count * @return the number of occurences */ protected int countChar(String str, int ch) { int fromIndex = 0; int count = 0; while ((fromIndex = str.indexOf(ch, fromIndex)) != -1) { count++; fromIndex++; // increment past current index // so we don't pick up the same // instance again. } return count; } /** * Breaks the text down into separate lines. Sets the cache field * <code>parsedData</code>. * * @see #parsedData */ protected void parseData() { if (parsedData == null) { if (data == null) data = ""; int nLines = countChar(data, '\n') + 1; if (nLines <= 1) { parsedData = new String[1]; parsedData[0] = data; } else { int i = 0; int fromIndex = 0; int toIndex = 0; parsedData = new String[nLines]; while ((toIndex = data.indexOf('\n', fromIndex)) != -1) { parsedData[i] = data.substring(fromIndex, toIndex); fromIndex = toIndex + 1; i++; } parsedData[nLines - 1] = data.substring(fromIndex, data.length()); } } } /** * Computes the widths of each line of the text. Sets the cache field * <code>widths</code>. * * @param fm the metrics to use for computation. * * @see #widths */ protected void computeStringWidths(FontMetrics fm) { if (widths == null && fm != null) { int nLines = parsedData.length; widths = new int[nLines]; for (int i = 0; i < nLines; i++) { widths[i] = fm.stringWidth(parsedData[i]); } } } /** * This function can be called to initialize the internals such as height * and width of OMText. Lets you use the graphics, and thus the FontMetrics * object, to figure out the dimensions of the text in order to manipulate * the placement of the text on the map. These internals were otherwise * initialized only when render function was called. * * @param g the java.awt.Graphics to put the string on. */ public synchronized void prepareForRender(Graphics g) { parseData(); g.setFont(getFont()); if (fm == null) { fm = g.getFontMetrics(); } computeBounds(); } /** * Renders the text onto the given graphics. Sets the cache field * <code>fm</code>. * * @param g the java.awt.Graphics to put the string on. * * @see #fm */ public synchronized void render(Graphics g) { // copy the graphic, so our transform doesn't cascade to // others... g = g.create(); if (getNeedToRegenerate() || pt == null || !isVisible()) return; g.setFont(getFont()); setGraphicsForEdge(g); if (fm == null) { fm = g.getFontMetrics(); } computeBounds(); // If there is a rotation angle, the shape will be calculated // for that rotation. Don't need to rotate the Graphics for // the shape. if (shouldRenderFill()) { setGraphicsForFill(g); fill(g); if (textureMask != null && textureMask != fillPaint) { setGraphicsColor(g, textureMask); fill(g); } } if (isMatted()) { if (isSelected()) { setGraphicsColor(g, getSelectPaint()); } else { setGraphicsColor(g, getMattingPaint()); } draw(g); } // to use later to unset the transform, if used. double rx = 0.0; double rw = 0.0; double woffset = 0.0; if (g instanceof Graphics2D && rotationAngle != DEFAULT_ROTATIONANGLE) { Rectangle rect = polyBounds.getBounds(); rx = rect.getX(); rw = rect.getWidth(); woffset = 0.0; switch (justify) { case JUSTIFY_LEFT: // woffset = 0.0; break; case JUSTIFY_CENTER: woffset = rw / 2; break; case JUSTIFY_RIGHT: woffset = rw; } // rotate about our text anchor point ((Graphics2D) g).rotate(rotationAngle, rx + woffset, pt.y); } setGraphicsForEdge(g); int height; if (fmHeight == HEIGHT) { height = fm.getHeight(); } else if (fmHeight == ASCENT_LEADING) { height = fm.getHeight() - fm.getDescent(); } else if (fmHeight == ASCENT_DESCENT) { height = fm.getAscent() + fm.getDescent(); } else { height = fm.getAscent(); } int baselineLocation = pt.y; // baseline == // BASELINE_BOTTOM, // normal. if (baseline == BASELINE_MIDDLE) { baselineLocation += (fm.getAscent() - fm.getDescent()) / 2; } else if (baseline == BASELINE_TOP) { baselineLocation += (fm.getAscent() - fm.getDescent()); } switch (justify) { case JUSTIFY_LEFT: // Easy case, just draw them. for (int i = 0; i < parsedData.length; i++) { renderString(g, parsedData[i], pt.x, baselineLocation + (height * i)); } break; case JUSTIFY_CENTER: computeStringWidths(fm); for (int i = 0; i < parsedData.length; i++) { renderString(g, parsedData[i], pt.x - (widths[i] / 2), baselineLocation + (height * i)); } break; case JUSTIFY_RIGHT: computeStringWidths(fm); for (int i = 0; i < parsedData.length; i++) { renderString(g, parsedData[i], pt.x - widths[i], baselineLocation + (height * i)); } break; } } protected void renderString(Graphics g, String string, int x, int y) { if (g instanceof Graphics2D) { Graphics2D g2 = (Graphics2D) g; if (getTextMatteColor() != null) { FontRenderContext context = g2.getFontRenderContext(); GlyphVector glyphVector = g2.getFont() .createGlyphVector(context, string); Shape outline = glyphVector.getOutline(); g2.translate(x, y); g2.setStroke(getTextMatteStroke()); g2.setColor(getTextMatteColor()); g2.draw(outline); g2.translate(-x, -y); g2.setColor(getLineColor()); } } g.drawString(string, x, y); } /** * Computes the bounding polygon. Sets the cache field * <code>polyBounds</code>. * * @see #polyBounds */ protected void computeBounds() { if (parsedData == null) { parseData(); } if (polyBounds == null && pt != null && fm != null) { // System.out.println("\tcomputing poly bounds"); int xoffset = 0; int i; int height; int descent; if (fmHeight == HEIGHT) { height = fm.getHeight(); descent = fm.getDescent(); } else if (fmHeight == ASCENT_DESCENT) { height = fm.getAscent(); descent = fm.getDescent(); } else if (fmHeight == ASCENT_LEADING) { height = fm.getHeight() - fm.getDescent(); descent = 0; } else { height = fm.getAscent(); descent = 0; } int nLines = parsedData.length; polyBounds = new Polygon(); computeStringWidths(fm); int baselineOffset = 0; // baseline == BASELINE_BOTTOM, // normal. if (baseline == BASELINE_MIDDLE) { baselineOffset = descent / 2; } else if (baseline == BASELINE_TOP) { baselineOffset = descent; } // or, baselineOffset = height - (baseline * height /2); // But that depends on the actual values of the BASELINE // values, which doesn't seem safe. /* * pt.y is bottom of first line, currenty is initialized to top of * first line, minus any offset introduced by baseline adjustments. */ int currenty = pt.y + descent - height - baselineOffset; // First, all the line endpoints. for (i = 0; i < nLines; i++) { switch (justify) { case JUSTIFY_LEFT: xoffset = widths[i]; break; case JUSTIFY_CENTER: xoffset = widths[i] / 2; break; case JUSTIFY_RIGHT: xoffset = 0; break; } // top of line polyBounds.addPoint(pt.x + xoffset, currenty); currenty += height; // bottom of line polyBounds.addPoint(pt.x + xoffset, currenty); } // Next, all line startpoints (the left side) for (i = nLines - 1; i >= 0; i--) { switch (justify) { case JUSTIFY_LEFT: xoffset = 0; break; case JUSTIFY_CENTER: xoffset = -widths[i] / 2; break; case JUSTIFY_RIGHT: xoffset = -widths[i]; break; } polyBounds.addPoint(pt.x + xoffset, currenty); currenty -= height; polyBounds.addPoint(pt.x + xoffset, currenty); } if (polyBounds != null) { if (useMaxWidthForBounds) { setShape(new GeneralPath(polyBounds.getBounds())); } else { setShape(new GeneralPath(polyBounds)); } // Make sure the shape takes into account the current // rotation angle. Code taken from generate() method, // so it should match up with the drawn text. if (rotationAngle != DEFAULT_ROTATIONANGLE) { Rectangle rect = polyBounds.getBounds(); double rx = rect.getX(); double rw = rect.getWidth(); double woffset = 0.0; switch (justify) { case JUSTIFY_LEFT: // woffset = 0.0; break; case JUSTIFY_CENTER: woffset = rw / 2; break; case JUSTIFY_RIGHT: woffset = rw; } AffineTransform at = new AffineTransform(); at.rotate(rotationAngle, rx + woffset, pt.y); PathIterator pi = shape.getPathIterator(at); GeneralPath gp = new GeneralPath(); gp.append(pi, false); shape = gp; } } } else { if (Debug.debugging("omtext")) { Debug.output("OMText.computeBounds() didn't compute because polybounds = " + polyBounds + " or pt = " + pt + " or fm = " + fm + ", (only polybounds should be null)"); } } } /** * Return the shortest distance from the OMText to an XY-point. * <p> * * This method uses the OMText's internal Shape object, created from the * boundary of the text, as its boundary. * * @param x X coordinate of the point. * @param y Y coordinate of the point. * @return float distance, in pixels, from graphic to the point. Returns * Float.POSITIVE_INFINITY if the graphic isn't ready (ungenerated). */ public float distance(int x, int y) { return _distance(x, y); } protected boolean hasLineTypeChoice() { return false; } /** * Write this object to a stream. */ private void writeObject(ObjectOutputStream oos) throws IOException { oos.defaultWriteObject(); // Write the Font. Take into account the font member could be // null, although this is unlikely it never hurts to // protect one's self. boolean writeFont = (f != OMText.DEFAULT_FONT); // First write a flag indicating if a Font is on the stream. oos.writeBoolean(writeFont); // Write the Font data if a font is on this object. if (writeFont) { oos.writeObject(f.getName()); oos.writeInt(f.getSize()); oos.writeInt(f.getStyle()); } } /** * Reconstitute from an ObjectInputStream. */ private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { ois.defaultReadObject(); // Get the flag form the stream boolean hasFont = ois.readBoolean(); if (hasFont) { String name = (String) ois.readObject(); int size = ois.readInt(); int style = ois.readInt(); f = new Font(name, style, size); } else { f = OMText.DEFAULT_FONT; } }}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -