예제 #1
0
  /**
   * 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);
  }
예제 #2
0
 private int getOverlapping() {
   if (myIsOpening) {
     return myBraceTextLine.getPaddingLeft() + myTextLine.getPaddingRight();
   } else {
     return myBraceTextLine.getPaddingRight() + myTextLine.getPaddingLeft();
   }
 }
예제 #3
0
  /**
   * 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));
  }
예제 #5
0
  /**
   * 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
  }
예제 #6
0
 /**
  * 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);
 }
예제 #7
0
 /**
  * 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;
 }
예제 #8
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);
  }
예제 #9
0
 @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;
  }
예제 #11
0
    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;
  }
예제 #13
0
  /**
   * 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);
 }
예제 #15
0
 @Override
 public void relayoutImpl() {
   super.relayoutImpl();
   myBraceTextLine.relayout();
   myWidth += myBraceTextLine.getWidth() - getOverlapping();
 }
예제 #16
0
    @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);
      }
    }
예제 #17
0
  /** 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();
  }
예제 #18
0
  /**
   * 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);
  }
예제 #19
0
  /**
   * 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);
  }
예제 #20
0
 @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();
 }