/** * Draw a legend for this data set * * @param g Graphics context * @param w Data Window */ protected void draw_legend(Graphics g, Rectangle w) { Color c = g.getColor(); Markers m = null; if (legend_text == null) return; if (legend_text.isNull()) return; if (legend_ix == 0 && legend_iy == 0) { legend_ix = (int) (w.x + ((legend_dx - xmin) / xrange) * w.width); legend_iy = (int) (w.y + (1.0 - (legend_dy - ymin) / yrange) * w.height); } if (linestyle != DataSet.NOLINE) { if (linecolor != null) g.setColor(linecolor); g.drawLine(legend_ix, legend_iy, legend_ix + legend_length, legend_iy); } if (marker > 0) { m = g2d.getMarkers(); if (m != null) { if (markercolor != null) g.setColor(markercolor); else g.setColor(c); m.draw(g, marker, 1.0, legend_ix + legend_length / 2, legend_iy); } } legend_text.draw( g, legend_ix + legend_length + legend_text.charWidth(g, ' '), legend_iy + legend_text.getAscent(g) / 3); g.setColor(c); }
private int getOverlapping() { if (myIsOpening) { return myBraceTextLine.getPaddingLeft() + myTextLine.getPaddingRight(); } else { return myBraceTextLine.getPaddingRight() + myTextLine.getPaddingLeft(); } }
/** * Draws the text block, aligning it with the specified anchor point and rotating it about the * specified rotation point. * * @param g2 the graphics device. * @param anchorX the x-coordinate for the anchor point. * @param anchorY the y-coordinate for the anchor point. * @param anchor the point on the text block that is aligned to the anchor point. * @param rotateX the x-coordinate for the rotation point. * @param rotateY the x-coordinate for the rotation point. * @param angle the rotation (in radians). */ public void draw( final Graphics2D g2, final float anchorX, final float anchorY, final TextBlockAnchor anchor, final float rotateX, final float rotateY, final double angle) { final Size2D d = calculateDimensions(g2); final float[] offsets = calculateOffsets(anchor, d.getWidth(), d.getHeight()); final Iterator iterator = this.lines.iterator(); float yCursor = 0.0f; while (iterator.hasNext()) { TextLine line = (TextLine) iterator.next(); Size2D dimension = line.calculateDimensions(g2); float lineOffset = 0.0f; if (this.lineAlignment == HorizontalAlignment.CENTER) { lineOffset = (float) (d.getWidth() - dimension.getWidth()) / 2.0f; } else if (this.lineAlignment == HorizontalAlignment.RIGHT) { lineOffset = (float) (d.getWidth() - dimension.getWidth()); } line.draw( g2, anchorX + offsets[0] + lineOffset, anchorY + offsets[1] + yCursor, TextAnchor.TOP_LEFT, rotateX, rotateY, angle); yCursor = yCursor + (float) dimension.getHeight(); } }
public CharRef charAt(int absoluteIndex) { final TextLine line = findLine(absoluteIndex); if (line == null) { throw new ArrayIndexOutOfBoundsException(absoluteIndex); } final int idx = absoluteIndex - line.start(); return new CharRef( line.content().charAt(idx), new SourceLocation(absoluteIndex, line.index(), idx)); }
/** * Returns the graphical width of a line beginning at <code>start</code> and including characters * up to <code>limit</code>. <code>start</code> and <code>limit</code> are absolute indices, not * relative to the start of the paragraph. * * @param start the character index at which to start measuring * @param limit the character index at which to stop measuring * @return the graphical width of a line beginning at <code>start</code> and including characters * up to <code>limit</code> * @throws IndexOutOfBoundsException if <code>limit</code> is less than <code>start</code> * @throws IllegalArgumentException if <code>start</code> or <code>limit</code> is not between the * beginning of the paragraph and the end of the paragraph. */ public float getAdvanceBetween(int start, int limit) { int localStart = start - fStart; int localLimit = limit - fStart; ensureComponents(localStart, localLimit); TextLine line = makeTextLineOnRange(localStart, localLimit); return line.getMetrics().advance; // could cache line in case getLayout is called with same start, limit }
/** * Returns the width and height of the text block. * * @param g2 the graphics device. * @return The width and height. */ public Size2D calculateDimensions(final Graphics2D g2) { double width = 0.0; double height = 0.0; final Iterator iterator = this.lines.iterator(); while (iterator.hasNext()) { final TextLine line = (TextLine) iterator.next(); final Size2D dimension = line.calculateDimensions(g2); width = Math.max(width, dimension.getWidth()); height = height + dimension.getHeight(); } return new Size2D(width, height); }
/** * Define a data legend in the graph window * * @param x data position of the legend. * @param y data position of the legend. * @param text text to display in the legend */ public void legend(double x, double y, String text) { if (text == null) { legend_text = null; return; } if (legend_text == null) legend_text = new TextLine(text); else legend_text.setText(text); legend_text.setJustification(TextLine.LEFT); legend_dx = x; legend_dy = y; legend_ix = 0; legend_iy = 0; }
/** Generate components for the paragraph. fChars, fBidi should have been initialized already. */ private void generateComponents(int startingAt, int endingAt) { if (collectStats) { formattedChars += (endingAt - startingAt); } int layoutFlags = 0; // no extra info yet, bidi determines run and line direction TextLabelFactory factory = new TextLabelFactory(fFrc, fChars, fBidi, layoutFlags); int[] charsLtoV = null; if (fBidi != null) { fLevels = BidiUtils.getLevels(fBidi); int[] charsVtoL = BidiUtils.createVisualToLogicalMap(fLevels); charsLtoV = BidiUtils.createInverseMap(charsVtoL); fIsDirectionLTR = fBidi.baseIsLeftToRight(); } else { fLevels = null; fIsDirectionLTR = true; } try { fComponents = TextLine.getComponents( fParagraph, fChars, startingAt, endingAt, charsLtoV, fLevels, factory); } catch (IllegalArgumentException e) { System.out.println("startingAt=" + startingAt + "; endingAt=" + endingAt); System.out.println("fComponentLimit=" + fComponentLimit); throw e; } fComponentStart = startingAt; fComponentLimit = endingAt; // debugFormatCount += (endingAt-startingAt); }
@Override public Boolean caseRichStringLiteral(RichStringLiteral object) { String value = object.getValue(); List<TextLine> lines = TextLines.splitString(value); if (lines.isEmpty()) { Literal literal = factory.createLiteral(); literal.setLength(0); literal.setOffset(0); literal.setLiteral(object); addToCurrentLine(literal); } else { for (TextLine textLine : lines) { Literal literal = factory.createLiteral(); literal.setLength(textLine.length()); literal.setOffset(textLine.getRelativeOffset()); literal.setLiteral(object); addToCurrentLine(literal); if (textLine.hasTrailingLineBreak()) { LineBreak lineBreak = factory.createLineBreak(); lineBreak.setLength(textLine.getDelimiterLength()); lineBreak.setOffset(textLine.getRelativeOffset() + textLine.length()); lineBreak.setLiteral(object); addToCurrentLine(lineBreak); currentLine = null; } } } return Boolean.TRUE; }
protected List<TextLine> handleTextFormatting(MOGuideEntry entry, String text, int width) { List<Object> shortCodeSplits = new ArrayList<>(); Matcher matcher = Pattern.compile(shortcodePattern).matcher(text); int lastEnd = 0; while (matcher.find()) { shortCodeSplits.add(text.substring(lastEnd, matcher.start())); String shortcode = matcher.group(); shortCodeSplits.add(handleShortCode(decodeShortcode(shortcode))); lastEnd = matcher.end(); } shortCodeSplits.add(text.substring(lastEnd, text.length())); List<TextChunk> textChunks = new ArrayList<>(); for (Object o : shortCodeSplits) { if (o instanceof String) { for (String s : ((String) o).split(" ")) { if (!s.isEmpty()) { textChunks.add(new TextChunk(handleVariables(s.trim(), entry), getFontRenderer())); } } } else if (o instanceof TextChunk) { textChunks.add((TextChunk) o); } } List<TextLine> lines = new ArrayList<>(); TextLine line = new TextLine(); lines.add(line); for (int i = 0; i < textChunks.size(); i++) { int w = calculateWidth(null, textChunks.get(i), null); if (i > 0 && i < textChunks.size() - 1) { w = calculateWidth(textChunks.get(i - 1), textChunks.get(i), textChunks.get(i + 1)); } if (line.getWidth() + w > width) { line = new TextLine(); lines.add(line); } line.addChunk(textChunks.get(i)); } return lines; }
protected EditorCell_Brace(EditorContext editorContext, SNode node, boolean isOpening) { super(editorContext, node, ""); myIsOpening = isOpening; String text = getBraceText(); Style style = new StyleImpl(); // COLORS: Remove hardcoded color & font style.set(StyleAttributes.TEXT_COLOR, Color.BLUE); style.set(StyleAttributes.FONT_STYLE, Font.BOLD); style.set(StyleAttributes.PADDING_LEFT, new Padding(0.0)); style.set(StyleAttributes.PADDING_RIGHT, new Padding(0.0)); myBraceTextLine = new TextLine(text, style, false); myBraceTextLine.setCaretEnabled(false); setEditable(false); setEnabled(false); }
private TextLine findLine(final int absIdx) { TextLine selected = null; if (currentLine != null) { if (currentLine.contains(absIdx)) { selected = currentLine; } else if (absIdx > currentLine.index() && currentLine.index() + 1 < lines.size()) { selected = scanLines(absIdx, currentLine.index()); } } if (selected == null) { selected = scanLines(absIdx, 0); } assert selected == null || selected.contains(absIdx); currentLine = selected; return selected; }
/** * Try to infer the role of this textual item. For the time being, this is a simple algorithm * based on sentence location within the page, augmented by valid chord name, etc. * * @param line the sentence * @param systemInfo the containing system * @return the role information inferred for the provided sentence glyph */ public static TextRoleInfo guessRole(TextLine line, SystemInfo systemInfo) { if (line == null) { return null; } if (line.isVip()) { logger.info("TextRoleInfo. guessRole for {}", line.getValue()); } int chordCount = 0; for (TextWord word : line.getWords()) { // At least one word/glyph with a role manually assigned Glyph glyph = word.getGlyph(); if (glyph != null) { if (glyph.getManualRole() != null) { return glyph.getManualRole(); } } // Word that could be a chord symbol? if (word.guessChordInfo() != null) { chordCount++; } } // Is line made entirely of potential chord symbols? boolean isAllChord = chordCount == line.getWords().size(); Rectangle box = line.getBounds(); if (box == null) { return null; } // Is line mainly in italic? boolean isMainlyItalic = systemInfo.getTextBuilder().isMainlyItalic(line); Sheet sheet = systemInfo.getSheet(); ScoreSystem system = systemInfo.getScoreSystem(); Scale scale = system.getScale(); Point left = new Point(box.x, box.y + (box.height / 2)); Point right = new Point(box.x + box.width, box.y + (box.height / 2)); // First system in page? boolean firstSystem = system.getId() == 1; // Last system in page? boolean lastSystem = sheet.getSystems().size() == system.getId(); // Vertical position wrt (system) staves StaffPosition systemPosition = system.getStaffPosition(left); // Vertical position wrt (part) staves SystemPart part = system.getPartAbove(left); StaffPosition partPosition = part.getStaffPosition(left); // Vertical distance from staff? Staff staff = system.getStaffAt(left); int staffDy = Math.abs(staff.getTopLeft().y - box.y); boolean closeToStaff = staffDy <= scale.toPixels(constants.maxStaffDy); // Begins on left side of the part? boolean leftOfStaves = system.isLeftOfStaves(left); // At the center of page width? int maxCenterDx = scale.toPixels(constants.maxCenterDx); int pageCenter = sheet.getWidth() / 2; boolean pageCentered = Math.abs((box.x + (box.width / 2)) - pageCenter) <= maxCenterDx; // Right aligned with staves? int maxRightDx = scale.toPixels(constants.maxRightDx); boolean rightAligned = Math.abs(right.x - system.getTopLeft().x - system.getDimension().width) <= maxRightDx; // Short Sentence? int maxShortLength = scale.toPixels(constants.maxShortLength); boolean shortSentence = box.width <= maxShortLength; // Tiny Sentence? int maxTinyLength = scale.toPixels(constants.maxTinyLength); boolean tinySentence = box.width <= maxTinyLength; // High text? int minTitleHeight = scale.toPixels(constants.minTitleHeight); boolean highText = box.height >= minTitleHeight; logger.debug( "{} firstSystem={} lastSystem={} systemPosition={}" + " partPosition={} closeToStaff={} leftOfStaves={}" + " pageCentered={} rightAligned={} shortSentence={}" + " highText={10}", box, firstSystem, lastSystem, systemPosition, partPosition, closeToStaff, leftOfStaves, pageCentered, rightAligned, shortSentence, highText); // Decisions ... switch (systemPosition) { case ABOVE_STAVES: // Title, Number, Creator, Direction, Chord if (tinySentence) { if (isAllChord) { return new TextRoleInfo(TextRole.Chord); } else { return new TextRoleInfo(TextRole.UnknownRole); } } if (firstSystem) { if (leftOfStaves) { return new TextRoleInfo(TextRole.Creator, Text.CreatorText.CreatorType.lyricist); } else if (rightAligned) { return new TextRoleInfo(TextRole.Creator, Text.CreatorText.CreatorType.composer); } else if (closeToStaff) { if (isAllChord) { return new TextRoleInfo(TextRole.Chord); } else { return new TextRoleInfo(TextRole.Direction); } } else if (pageCentered) { // Title, Number if (highText) { return new TextRoleInfo(TextRole.Title); } else { return new TextRoleInfo(TextRole.Number); } } } else { if (isAllChord) { return new TextRoleInfo(TextRole.Chord); } else { return new TextRoleInfo(TextRole.Direction); } } break; case WITHIN_STAVES: // Name, Lyrics, Direction if (leftOfStaves) { return new TextRoleInfo(TextRole.Name); } else if ((partPosition == StaffPosition.BELOW_STAVES) && !isMainlyItalic) { return new TextRoleInfo(TextRole.Lyrics); } else { return new TextRoleInfo(TextRole.Direction); } case BELOW_STAVES: // Copyright, Lyrics for single-staff part if (tinySentence) { return new TextRoleInfo(TextRole.UnknownRole); } if (pageCentered && shortSentence && lastSystem) { return new TextRoleInfo(TextRole.Rights); } if (part.getStaves().size() == 1) { if ((partPosition == StaffPosition.BELOW_STAVES) && !isMainlyItalic) { return new TextRoleInfo(TextRole.Lyrics); } } } // Default return new TextRoleInfo(TextRole.UnknownRole); }
private void pushNewLine() { endLine = new TextLine(endLine.end(), endLine.index() + 1); lines.add(endLine); }
@Override public void relayoutImpl() { super.relayoutImpl(); myBraceTextLine.relayout(); myWidth += myBraceTextLine.getWidth() - getOverlapping(); }
@Override public void paintContent(Graphics g, ParentSettings parentSettings) { if (!myIsEnabled) return; TextLine textLine = getRenderedTextLine(); boolean toShowCaret = toShowCaret(); int overlapping = getOverlapping(); myBraceTextLine.setSelected(false); myBraceTextLine.setShowCaret(false); textLine.setSelected(isSelected()); textLine.setShowCaret(toShowCaret); if (myIsOpening) { myBraceTextLine.paint(g, myX + textLine.getWidth() - overlapping, myY); textLine.paint(g, myX, myY); } else { myBraceTextLine.paint(g, myX, myY); textLine.paint(g, myX + myBraceTextLine.getWidth() - overlapping, myY); } }
/** Initialize state, including fChars array, direction, and fBidi. */ private void initAll(AttributedCharacterIterator text) { fStart = text.getBeginIndex(); // extract chars fChars = new char[text.getEndIndex() - fStart]; int n = 0; for (char c = text.first(); c != CharacterIterator.DONE; c = text.next()) { fChars[n++] = c; } text.first(); fBidi = new Bidi(text); if (fBidi.isLeftToRight()) { fBidi = null; } text.first(); Map<? extends Attribute, ?> paragraphAttrs = text.getAttributes(); NumericShaper shaper = AttributeValues.getNumericShaping(paragraphAttrs); if (shaper != null) { shaper.shape(fChars, 0, fChars.length); } fParagraph = new StyledParagraph(text, fChars); // set paragraph attributes { // If there's an embedded graphic at the start of the // paragraph, look for the first non-graphic character // and use it and its font to initialize the paragraph. // If not, use the first graphic to initialize. fJustifyRatio = AttributeValues.getJustification(paragraphAttrs); boolean haveFont = TextLine.advanceToFirstFont(text); if (haveFont) { Font defaultFont = TextLine.getFontAtCurrentPos(text); int charsStart = text.getIndex() - text.getBeginIndex(); LineMetrics lm = defaultFont.getLineMetrics(fChars, charsStart, charsStart + 1, fFrc); fBaseline = (byte) lm.getBaselineIndex(); fBaselineOffsets = lm.getBaselineOffsets(); } else { // hmmm what to do here? Just try to supply reasonable // values I guess. GraphicAttribute graphic = (GraphicAttribute) paragraphAttrs.get(TextAttribute.CHAR_REPLACEMENT); fBaseline = TextLayout.getBaselineFromGraphic(graphic); Hashtable<Attribute, ?> fmap = new Hashtable<>(5, (float) 0.9); Font dummyFont = new Font(fmap); LineMetrics lm = dummyFont.getLineMetrics(" ", 0, 1, fFrc); fBaselineOffsets = lm.getBaselineOffsets(); } fBaselineOffsets = TextLine.getNormalizedOffsets(fBaselineOffsets, fBaseline); } invalidateComponents(); }
/** * Set the font to be used in the legend * * @param f font */ public void legendFont(Font f) { if (f == null) return; if (legend_text == null) legend_text = new TextLine(); legend_text.setFont(f); }
/** * Set the color for the legend text * * @param c color */ public void legendColor(Color c) { if (c == null) return; if (legend_text == null) legend_text = new TextLine(); legend_text.setColor(c); }
@Override public Boolean caseLiteral(Literal object) { if (announced == null || announced != object.getLiteral()) { acceptor.announceNextLiteral(object.getLiteral()); announced = object.getLiteral(); } Line line = object.getLine(); TextLine textLine = new TextLine( Strings.emptyIfNull(object.getLiteral().getValue()), object.getOffset(), object.getLength(), 0); CharSequence ws = textLine.getLeadingWhiteSpace(); ProcessedRichString string = line.getRichString(); boolean firstOrLast = string.getLines().get(0) == line || string.getLines().get(string.getLines().size() - 1) == line; if (isTemplateLine(line)) { if (line.getParts().get(0) == object) { if (!firstOrLast) { boolean followedByOpening = false; if (line.getParts().size() >= 2) { LinePart next = line.getParts().get(1); if (next instanceof ForLoopStart || next instanceof IfConditionStart) { followedByOpening = true; } } if (!followedByOpening) { pushSemanticIndentation(indentationHandler.getTotalIndentation()); } else { pushSemanticIndentation(ws); } } } announceTemplateText(textLine, object.getLiteral()); } else { if (skipCount <= 1) { firstOrLast = false; if (skipCount == 0 && line.getParts().get(0) == object) { if (textLine.length() == ws.length()) { for (int i = 1; i < line.getParts().size(); i++) { if (line.getParts().get(i) instanceof Literal && !(line.getParts().get(i) instanceof LineBreak)) { Literal nextLiteralInSameLine = (Literal) line.getParts().get(i); TextLine nextLiteralLine = new TextLine( nextLiteralInSameLine.getLiteral().getValue(), nextLiteralInSameLine.getOffset(), nextLiteralInSameLine.getLength(), 0); CharSequence nextLeading = nextLiteralLine.getLeadingWhiteSpace(); if (nextLeading.length() > 0) { ws = ws.toString() + nextLeading; } skipCount++; if (nextLeading.length() != nextLiteralLine.length()) { break; } } else { break; } } if (skipCount != 0) { pushSemanticIndentation(ws); } else { pushSemanticIndentation(ws); announceIndentation(); announceSemanticText( textLine.subSequence(ws.length(), textLine.length()), object.getLiteral()); } } else { pushSemanticIndentation(ws); announceIndentation(); announceSemanticText( textLine.subSequence(ws.length(), textLine.length()), object.getLiteral()); } } else { if (skipCount == 1) { skipCount--; announceIndentation(); announceSemanticText( textLine.subSequence(ws.length(), textLine.length()), object.getLiteral()); } else { announceSemanticText(textLine, object.getLiteral()); } } } else { skipCount--; } } if (!firstOrLast && line.getParts().get(line.getParts().size() - 1) == object) { popIndentation(); } computeNextPart(object); return Boolean.TRUE; }
public int length() { return endLine.end(); }