public static void main(String[] args) throws Exception { int size = Util.getPropertyInt("size", 100); double min = Util.getPropertyDouble("min", 0.01); double max = Util.getPropertyDouble("max", 0.9); Font font = new Font("serif", Font.PLAIN, size); String fpath = Util.getProperty("font", null); if (fpath != null) { font = Font.createFont(Font.TRUETYPE_FONT, new FileInputStream(fpath)); } for (char c = Character.MIN_VALUE + 1; c < Character.MAX_VALUE; ++c) { int type = Character.getType(c); if (type != Character.CONTROL && type != Character.FORMAT && type != Character.PRIVATE_USE && type != Character.SURROGATE && type != Character.UNASSIGNED && !Character.isMirrored(c) && !Character.isSpaceChar(c)) { String s = "" + c; if (Normalizer.normalize(s, NFKC).contains("\u0308")) continue; // TODO: adhoc UnigramMetrics m = new UnigramMetrics(s, size, false, true, font); if (min < m.getBlackness() && m.getBlackness() < max) { System.out.println("" + c + " " + (int) c); } } } }
/** * This is the write() method of the stream. All Writer subclasses implement this. All other * versions of write() are variants of this one */ public void write(char[] buffer, int index, int len) { synchronized (this.lock) { // Loop through all the characters passed to us for (int i = index; i < index + len; i++) { // If we haven't begun a page (or a new page), do that now. if (page == null) newpage(); // If the character is a line terminator, then begin new line, // unless it is a \n immediately after a \r. if (buffer[i] == '\n') { if (!last_char_was_return) newline(); continue; } if (buffer[i] == '\r') { newline(); last_char_was_return = true; continue; } else last_char_was_return = false; // If it some other non-printing character, ignore it. if (Character.isWhitespace(buffer[i]) && !Character.isSpaceChar(buffer[i]) && (buffer[i] != '\t')) continue; // If no more characters will fit on the line, start a new line. if (charnum >= chars_per_line) { newline(); if (page == null) newpage(); // and start a new page, if necessary } // Now print the character: // If it is a space, skip one space, without output. // If it is a tab, skip the necessary number of spaces. // Otherwise, print the character. // It is inefficient to draw only one character at a time, but // because our FontMetrics don't match up exactly to what the // printer uses we need to position each character individually. if (Character.isSpaceChar(buffer[i])) charnum++; else if (buffer[i] == '\t') charnum += 8 - (charnum % 8); else { page.drawChars( buffer, i, 1, x0 + charnum * charwidth, y0 + (linenum * lineheight) + lineascent); charnum++; } } } }
/** * Provides a way to determine the next visually represented model location that one might place a * caret. Some views may not be visible, they might not be in the same order found in the model, * or they just might not allow access to some of the locations in the model. * * @param v the view to use * @param pos the position to convert >= 0 * @param a the allocated region to render into * @param direction the direction from the current position that can be thought of as the arrow * keys typically found on a keyboard. This may be SwingConstants.WEST, SwingConstants.EAST, * SwingConstants.NORTH, or SwingConstants.SOUTH. * @return the location within the model that best represents the next location visual position. * @exception BadLocationException * @exception IllegalArgumentException for an invalid direction */ public int getNextVisualPositionFrom( GlyphView v, int pos, Position.Bias b, Shape a, int direction, Position.Bias[] biasRet) throws BadLocationException { int startOffset = v.getStartOffset(); int endOffset = v.getEndOffset(); Segment text; AbstractDocument doc; boolean viewIsLeftToRight; TextHitInfo currentHit, nextHit; switch (direction) { case View.NORTH: break; case View.SOUTH: break; case View.EAST: doc = (AbstractDocument) v.getDocument(); viewIsLeftToRight = doc.isLeftToRight(startOffset, endOffset); if (startOffset == doc.getLength()) { if (pos == -1) { biasRet[0] = Position.Bias.Forward; return startOffset; } // End case for bidi text where newline is at beginning // of line. return -1; } if (pos == -1) { // Entering view from the left. if (viewIsLeftToRight) { biasRet[0] = Position.Bias.Forward; return startOffset; } else { text = v.getText(endOffset - 1, endOffset); char c = text.array[text.offset]; SegmentCache.releaseSharedSegment(text); if (c == '\n') { biasRet[0] = Position.Bias.Forward; return endOffset - 1; } biasRet[0] = Position.Bias.Backward; return endOffset; } } if (b == Position.Bias.Forward) currentHit = TextHitInfo.afterOffset(pos - startOffset); else currentHit = TextHitInfo.beforeOffset(pos - startOffset); nextHit = layout.getNextRightHit(currentHit); if (nextHit == null) { return -1; } if (viewIsLeftToRight != layout.isLeftToRight()) { // If the layout's base direction is different from // this view's run direction, we need to use the weak // carrat. nextHit = layout.getVisualOtherHit(nextHit); } pos = nextHit.getInsertionIndex() + startOffset; if (pos == endOffset) { // A move to the right from an internal position will // only take us to the endOffset in a left to right run. text = v.getText(endOffset - 1, endOffset); char c = text.array[text.offset]; SegmentCache.releaseSharedSegment(text); if (c == '\n') { return -1; } biasRet[0] = Position.Bias.Backward; } else { biasRet[0] = Position.Bias.Forward; } return pos; case View.WEST: doc = (AbstractDocument) v.getDocument(); viewIsLeftToRight = doc.isLeftToRight(startOffset, endOffset); if (startOffset == doc.getLength()) { if (pos == -1) { biasRet[0] = Position.Bias.Forward; return startOffset; } // End case for bidi text where newline is at beginning // of line. return -1; } if (pos == -1) { // Entering view from the right if (viewIsLeftToRight) { text = v.getText(endOffset - 1, endOffset); char c = text.array[text.offset]; SegmentCache.releaseSharedSegment(text); if ((c == '\n') || Character.isSpaceChar(c)) { biasRet[0] = Position.Bias.Forward; return endOffset - 1; } biasRet[0] = Position.Bias.Backward; return endOffset; } else { biasRet[0] = Position.Bias.Forward; return startOffset; } } if (b == Position.Bias.Forward) currentHit = TextHitInfo.afterOffset(pos - startOffset); else currentHit = TextHitInfo.beforeOffset(pos - startOffset); nextHit = layout.getNextLeftHit(currentHit); if (nextHit == null) { return -1; } if (viewIsLeftToRight != layout.isLeftToRight()) { // If the layout's base direction is different from // this view's run direction, we need to use the weak // carrat. nextHit = layout.getVisualOtherHit(nextHit); } pos = nextHit.getInsertionIndex() + startOffset; if (pos == endOffset) { // A move to the left from an internal position will // only take us to the endOffset in a right to left run. text = v.getText(endOffset - 1, endOffset); char c = text.array[text.offset]; SegmentCache.releaseSharedSegment(text); if (c == '\n') { return -1; } biasRet[0] = Position.Bias.Backward; } else { biasRet[0] = Position.Bias.Forward; } return pos; default: throw new IllegalArgumentException("Bad direction: " + direction); } return pos; }