Example #1
0
  /**
   * Creates a new ClefPattern object.
   *
   * @param system the containing system
   */
  public ClefPattern(SystemInfo system) {
    super("Clef", system);

    nest = system.getSheet().getNest();

    clefWidth = scale.toPixels(constants.clefWidth);
    xOffset = scale.toPixels(constants.xOffset);
    yOffset = scale.toPixels(constants.yOffset);
    xMargin = scale.toPixels(constants.xMargin);
    yMargin = scale.toPixels(constants.yMargin);
  }
Example #2
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);
  }
  /**
   * In a specified system, look for all stems that should not be kept, rebuild surrounding glyphs
   * and try to recognize them. If this action does not lead to some recognized symbol, then we
   * restore the stems.
   *
   * @return the number of symbols recognized
   */
  public int runStemPattern() {
    int nb = 0;

    // Collect all undue stems
    List<Glyph> SuspectedStems = new ArrayList<Glyph>();

    for (Glyph glyph : system.getGlyphs()) {
      if (glyph.isStem() && glyph.isActive()) {
        Set<Glyph> goods = new HashSet<Glyph>();
        Set<Glyph> bads = new HashSet<Glyph>();
        glyph.getSymbolsBefore(reliableStemSymbols, goods, bads);
        glyph.getSymbolsAfter(reliableStemSymbols, goods, bads);

        if (goods.isEmpty()) {
          if (logger.isFineEnabled()) {
            logger.finest("Suspected Stem " + glyph);
          }

          SuspectedStems.add(glyph);

          // Discard "bad" ones
          for (Glyph g : bads) {
            if (logger.isFineEnabled()) {
              logger.finest("Deassigning bad glyph " + g);
            }

            g.setShape((Shape) null);
          }
        }
      }
    }

    // Remove these stem glyphs since nearby stems are used for recognition
    for (Glyph glyph : SuspectedStems) {
      system.removeGlyph(glyph);
    }

    // Extract brand new glyphs (removeInactiveGlyphs + retrieveGlyphs)
    system.extractNewGlyphs();

    // Try to recognize each glyph in turn
    List<Glyph> symbols = new ArrayList<Glyph>();
    final GlyphEvaluator evaluator = GlyphNetwork.getInstance();
    final double maxDoubt = GlyphInspector.getPatternsMaxDoubt();

    for (Glyph glyph : system.getGlyphs()) {
      if (glyph.getShape() == null) {
        Evaluation vote = evaluator.vote(glyph, maxDoubt);

        if (vote != null) {
          glyph.setShape(vote.shape, vote.doubt);

          if (glyph.isWellKnown()) {
            if (logger.isFineEnabled()) {
              logger.finest("New symbol " + glyph);
            }

            symbols.add(glyph);
            nb++;
          }
        }
      }
    }

    // Keep stems that have not been replaced by symbols, definitively
    // remove the others
    for (Glyph stem : SuspectedStems) {
      // Check if one of its section is now part of a symbol
      boolean known = false;
      Glyph glyph = null;

      for (GlyphSection section : stem.getMembers()) {
        glyph = section.getGlyph();

        if ((glyph != null) && glyph.isWellKnown()) {
          known = true;

          break;
        }
      }

      if (!known) {
        // Remove the newly created glyph
        if (glyph != null) {
          system.removeGlyph(glyph);
        }

        // Restore the stem
        system.addGlyph(stem);
      }
    }

    return nb;
  }