コード例 #1
0
    // ~ Methods ------------------------------------------------------------
    // Retrieve the distance with proper staff border
    @Override
    protected double getValue(GlyphContext context) {
      Glyph stick = context.stick;
      Point2D stop = stick.getStopPoint(VERTICAL);

      // Which staff area contains the bottom of the stick?
      StaffInfo staff = staffManager.getStaffAt(stop);

      // How far are we from the stop of the staff?
      double staffBottom = staff.getLastLine().yAt(stop.getX());
      double dy = sheet.getScale().pixelsToFrac(Math.abs(staffBottom - stop.getY()));

      // Change limits according to rough & partDefining
      if (rough && context.isPartDefining) {
        setLowHigh(constants.maxStaffShiftDyLowRough, constants.maxStaffShiftDyHighRough);
      } else {
        setLowHigh(constants.maxStaffShiftDyLow, constants.maxStaffShiftDyHigh);
      }

      // Side-effect
      if (dy <= getLow()) {
        context.botStaff = context.bottomArea;
      }

      return dy;
    }
コード例 #2
0
    // ~ Methods ------------------------------------------------------------
    @Override
    public void onEvent(UserEvent event) {
      try {
        // Ignore RELEASING
        if (event.movement == MouseMovement.RELEASING) {
          return;
        }

        if (event instanceof GlyphEvent) {
          BarsChecker.GlyphContext context = null;
          GlyphEvent glyphEvent = (GlyphEvent) event;
          Glyph glyph = glyphEvent.getData();

          if (glyph != null) {
            // Make sure this is a rather vertical stick
            if (Math.abs(glyph.getInvertedSlope()) <= constants.maxCoTangentForCheck.getValue()) {
              // Apply a fresh suite
              context = new BarsChecker.GlyphContext(glyph);
              applySuite(new BarCheckSuite(), context);

              return;
            }
          }

          tellObject(null);
        }
      } catch (Exception ex) {
        logger.warn(getClass().getName() + " onEvent error", ex);
      }
    }
コード例 #3
0
        public boolean check(Glyph glyph) {
          Shape shape = glyph.getShape();

          boolean res =
              glyph.isWellKnown()
                  && ShapeRange.StemSymbols.contains(shape)
                  && (shape != Shape.BEAM_HOOK);

          return res;
        }
コード例 #4
0
    // ~ Methods ------------------------------------------------------------
    // Retrieve the difference between stick slope and global slope
    @Override
    protected double getValue(GlyphContext context) {
      Glyph stick = context.stick;
      Point2D start = stick.getStartPoint(VERTICAL);
      Point2D stop = stick.getStopPoint(VERTICAL);

      // Beware of sign of stickSlope (it is opposite of globalSlope)
      double stickSlope = -(stop.getX() - start.getX()) / (stop.getY() - start.getY());

      return Math.abs(stickSlope - sheet.getSkew().getSlope());
    }
コード例 #5
0
  /**
   * Check if the stick/bar is a thick one
   *
   * @param stick the bar stick to check
   * @return true if thick
   */
  private boolean isThickBar(Glyph stick) {
    // Max width of a thin bar line, otherwise this must be a thick bar
    final int maxThinWidth = scale.toPixels(constants.maxThinWidth);

    // Average width of the stick
    final int meanWidth =
        (int)
            Math.rint((double) stick.getWeight() / (double) stick.getLength(Orientation.VERTICAL));

    return meanWidth > maxThinWidth;
  }
コード例 #6
0
    // ~ Methods ------------------------------------------------------------
    @Override
    protected Rectangle getBox(Glyph stick) {
      Point2D bottom = stick.getStopPoint(VERTICAL);
      Rectangle box =
          new Rectangle(
              (int) Math.rint(bottom.getX()),
              (int) Math.rint(bottom.getY() - (1.5 * nHeight)),
              nWidth,
              2 * nHeight);
      stick.addAttachment("br", box);

      return box;
    }
コード例 #7
0
    // ~ Methods ------------------------------------------------------------
    // Retrieve the length data
    @Override
    protected double getValue(GlyphContext context) {
      Glyph stick = context.stick;
      int height = Integer.MAX_VALUE;

      // Check wrt every staff in the stick getRange
      for (int i = context.topArea; i <= context.bottomArea; i++) {
        StaffInfo area = staffManager.getStaff(i);
        height = Math.min(height, area.getHeight());
      }

      return sheet.getScale().pixelsToFrac(height - stick.getLength(Orientation.VERTICAL));
    }
コード例 #8
0
    // ~ Methods ------------------------------------------------------------
    @Override
    protected Rectangle getBox(Glyph stick) {
      Point2D top = stick.getStartPoint(VERTICAL);
      Rectangle box =
          new Rectangle(
              (int) Math.rint(top.getX()),
              (int) Math.rint(top.getY() - (nHeight / 2)),
              nWidth,
              2 * nHeight);
      stick.addAttachment("tr", box);

      return box;
    }
コード例 #9
0
    // ~ Methods ------------------------------------------------------------
    // Retrieve the distance with proper staff border
    @Override
    protected double getValue(GlyphContext context) {
      Glyph stick = context.stick;
      Point2D stop = stick.getStopPoint(VERTICAL);

      // Which staff area contains the bottom of the stick?
      StaffInfo staff = staffManager.getStaffAt(stop);

      // How far are we from the stop of the staff?
      double staffBottom = staff.getLastLine().yAt(stop.getX());
      double dy = sheet.getScale().pixelsToFrac(Math.abs(staffBottom - stop.getY()));

      return dy;
    }
コード例 #10
0
  // -------------------//
  // initializeContext //
  // -------------------//
  private void initializeContext(GlyphContext context) {
    Glyph stick = context.stick;
    StaffInfo startStaff = staffManager.getStaffAt(stick.getStartPoint(VERTICAL));
    StaffInfo stopStaff = staffManager.getStaffAt(stick.getStopPoint(VERTICAL));

    // Remember top & bottom areas
    context.topArea = staffManager.getIndexOf(startStaff);
    context.bottomArea = staffManager.getIndexOf(stopStaff);

    // Check whether this stick embraces more than one staff
    context.isPartDefining = context.topArea != context.bottomArea;

    // Remember if this is a thick stick
    context.isThick = isThickBar(stick);
  }
コード例 #11
0
  // ------------------//
  // getAlienPixelsIn //
  // ------------------//
  private int getAlienPixelsIn(Glyph glyph, Rectangle absRoi) {
    Predicate<Section> predicate =
        new Predicate<Section>() {
          @Override
          public boolean check(Section section) {
            return (section.getGlyph() == null)
                || (section.getGlyph().getShape() != Shape.STAFF_LINE);
          }
        };

    int total = 0;
    total += glyph.getAlienPixelsFrom(sheet.getVerticalLag(), absRoi, predicate);
    total += glyph.getAlienPixelsFrom(sheet.getHorizontalLag(), absRoi, predicate);

    return total;
  }
コード例 #12
0
  // --------------//
  // computeShape //
  // --------------//
  @Override
  protected Shape computeShape() {
    StringBuilder sig = new StringBuilder();

    for (Glyph glyph : getGlyphs()) {
      sig.append(sigs.get(glyph.getShape()));
    }

    Shape shape = shapes.get(sig.toString());

    if (shape == null) {
      addError("Invalid dynamics signature:" + sig);
    }

    return shape;
  }
コード例 #13
0
  /**
   * Used by SystemTranslator to allocate the dynamics marks
   *
   * @param glyph underlying glyph
   * @param measure measure where the mark is located
   * @param point location for the mark
   */
  public static void populate(Glyph glyph, Measure measure, SystemPoint point) {
    // Can we gather with another dynamics letter? (e.g. m + p -> mp)
    for (TreeNode node : measure.getChildren()) {
      if (node instanceof Dynamics) {
        Dynamics d = (Dynamics) node;

        if (d.isCompatibleWith(point)) {
          d.addGlyph(glyph);
          glyph.setTranslation(d);

          return;
        }
      }
    }

    // Otherwise, create a brand new instance
    glyph.setTranslation(new Dynamics(measure, point, findChord(measure, point), glyph));
  }
コード例 #14
0
    // ~ Methods ------------------------------------------------------------
    // Retrieve the stick abscissa
    @Override
    protected double getValue(GlyphContext context) {
      Glyph stick = context.stick;
      double dist = Double.MAX_VALUE;

      // Check wrt every staff in the stick range
      for (int i = context.topArea; i <= context.bottomArea; i++) {
        StaffInfo staff = staffManager.getStaff(i);
        Point2D top = staff.getFirstLine().getEndPoint(LEFT);
        Point2D bot = staff.getLastLine().getEndPoint(LEFT);
        double y = (top.getY() + bot.getY()) / 2;
        double x = stick.getPositionAt(y, Orientation.VERTICAL);
        double dx = x - staff.getAbscissa(LEFT);
        dist = Math.min(dist, dx);
      }

      return sheet.getScale().pixelsToFrac(dist);
    }
コード例 #15
0
    @Override
    protected double getValue(GlyphContext context) {
      Glyph stick = context.stick;
      Rectangle box = getBox(stick);

      int aliens = getAlienPixelsIn(stick, box);
      int area = box.width * box.height;

      // Normalize the ratio with stick length
      double ratio = (1000 * aliens) / ((double) area * stick.getLength(Orientation.VERTICAL));

      logger.debug(
          "{} {} aliens:{} area:{} ratio:{}",
          stick.idString(),
          getName(),
          aliens,
          area,
          (float) ratio);

      return ratio;
    }
コード例 #16
0
ファイル: ClefPattern.java プロジェクト: sbunciak/symphonia
  /**
   * Check that each staff begins with a clef.
   *
   * @return the number of clefs rebuilt
   */
  @Override
  public int runPattern() {
    int successNb = 0;
    int staffId = 0;

    for (StaffInfo staff : system.getStaves()) {
      staffId++;

      // Define the inner box to intersect clef glyph(s)
      int left = (int) Math.rint(staff.getAbscissa(HorizontalSide.LEFT));
      Rectangle inner =
          new Rectangle(
              left + (2 * xOffset) + (clefWidth / 2),
              staff.getFirstLine().yAt(left) + (staff.getHeight() / 2),
              0,
              0);
      inner.grow((clefWidth / 2) - xOffset, (staff.getHeight() / 2) - yOffset);

      // Remember the box, for visual debug
      staff.addAttachment("  ci", inner);

      // We must find a clef out of these glyphs
      Collection<Glyph> glyphs = system.lookupIntersectedGlyphs(inner);
      logger.debug("{}{}", staffId, Glyphs.toString(" int", glyphs));

      // We assume than there can't be any alien among them, so we should
      // rebuild the larger glyph which the alien had wrongly segmented
      Set<Glyph> impacted = new HashSet<>();

      for (Glyph glyph : glyphs) {
        if (glyph.getShape() == Shape.STEM) {
          logger.debug("Clef: Removed stem#{}", glyph.getId());

          impacted.addAll(glyph.getConnectedNeighbors());
          impacted.add(glyph);
        }
      }

      if (!impacted.isEmpty()) {
        // Rebuild the larger glyph
        Glyph larger = system.buildCompound(impacted);
        if (larger != null) {
          logger.debug("Rebuilt stem-segmented {}", larger.idString());
        }

        // Recompute the set of intersected glyphs
        glyphs = system.lookupIntersectedGlyphs(inner);
      }

      if (checkClef(glyphs, staff)) {
        successNb++;
      }
    }

    return successNb;
  }
コード例 #17
0
ファイル: BassPattern.java プロジェクト: sbunciak/symphonia
 @Override
 public boolean isCandidateSuitable(Glyph glyph) {
   return !glyph.isManualShape() || ShapeSet.BassClefs.contains(glyph.getShape());
 }
コード例 #18
0
ファイル: BassPattern.java プロジェクト: sbunciak/symphonia
  // ~ Methods ----------------------------------------------------------------
  // ------------//
  // runPattern //
  // ------------//
  @Override
  public int runPattern() {
    int successNb = 0;

    // Constants for clef verification
    final double maxBassDotPitchDy = constants.maxBassDotPitchDy.getValue();
    final double maxBassDotDx = scale.toPixels(constants.maxBassDotDx);

    // Specific adapter definition for bass clefs
    CompoundAdapter bassAdapter = new BassAdapter(system, Grades.clefMinGrade);

    for (Glyph top : system.getGlyphs()) {
      // Look for top dot
      if ((top.getShape() != Shape.DOT_set)
          || (Math.abs(top.getPitchPosition() - -3) > maxBassDotPitchDy)) {
        continue;
      }

      int topX = top.getCentroid().x;
      StaffInfo topStaff = system.getStaffAt(top.getCentroid());

      // Look for bottom dot right underneath, and in the same staff
      for (Glyph bot : system.getGlyphs()) {
        if ((bot.getShape() != Shape.DOT_set)
            || (Math.abs(bot.getPitchPosition() - -1) > maxBassDotPitchDy)) {
          continue;
        }

        if (Math.abs(bot.getCentroid().x - topX) > maxBassDotDx) {
          continue;
        }

        if (system.getStaffAt(bot.getCentroid()) != topStaff) {
          continue;
        }

        // Here we have a couple
        logger.debug("Got bass dots #{} & #{}", top.getId(), bot.getId());

        Glyph compound = system.buildCompound(top, true, system.getGlyphs(), bassAdapter);

        if (compound != null) {
          successNb++;
        }
      }
    }

    return successNb;
  }
コード例 #19
0
ファイル: ClefPattern.java プロジェクト: sbunciak/symphonia
  /**
   * Try to recognize a clef in the compound of the provided glyphs.
   *
   * @param glyphs the parts of a clef candidate
   * @param staff the containing staff
   * @return true if successful
   */
  private boolean checkClef(Collection<Glyph> glyphs, StaffInfo staff) {
    if (glyphs.isEmpty()) {
      return false;
    }

    // Check if we already have a clef among the intersected glyphs
    Set<Glyph> clefs = Glyphs.lookupGlyphs(glyphs, clefGlyphPredicate);
    Glyph orgClef = null;

    if (!clefs.isEmpty()) {
      if (Glyphs.containsManual(clefs)) {
        return false; // Respect user decision
      } else {
        // Remember grade of the best existing clef
        for (Glyph glyph : clefs) {
          if ((orgClef == null) || (glyph.getGrade() > orgClef.getGrade())) {
            orgClef = glyph;
          }
        }
      }
    }

    // Remove potential aliens
    Glyphs.purgeManuals(glyphs);

    Glyph compound = system.buildTransientCompound(glyphs);

    // Check if a clef appears in the top evaluations
    Evaluation vote =
        GlyphNetwork.getInstance().vote(compound, system, Grades.clefMinGrade, clefShapePredicate);

    if ((vote != null) && ((orgClef == null) || (vote.grade > orgClef.getGrade()))) {
      // We now have a clef!
      // Look around for an even better result...
      logger.debug("{} built from {}", vote.shape, Glyphs.toString(glyphs));

      // Look for larger stuff
      Rectangle outer = compound.getBounds();
      outer.grow(xMargin, yMargin);

      // Remember the box, for visual debug
      staff.addAttachment("co", outer);

      List<Glyph> outerGlyphs = system.lookupIntersectedGlyphs(outer);
      outerGlyphs.removeAll(glyphs);
      Collections.sort(outerGlyphs, Glyph.byReverseWeight);

      final double minWeight = constants.minWeight.getValue();

      for (Glyph g : outerGlyphs) {
        // Consider only glyphs with a minimum weight
        if (g.getNormalizedWeight() < minWeight) {
          break;
        }

        logger.debug("Considering {}", g);

        Glyph newCompound = system.buildTransientCompound(Arrays.asList(compound, g));
        final Evaluation newVote =
            GlyphNetwork.getInstance()
                .vote(newCompound, system, Grades.clefMinGrade, clefShapePredicate);

        if ((newVote != null) && (newVote.grade > vote.grade)) {
          logger.debug("{} better built with {}", vote, g.idString());

          compound = newCompound;
          vote = newVote;
        }
      }

      // Register the last definition of the clef
      compound = system.addGlyph(compound);
      compound.setShape(vote.shape, Evaluation.ALGORITHM);

      logger.debug("{} rebuilt as {}", vote.shape, compound.idString());

      return true;
    } else {
      return false;
    }
  }
コード例 #20
0
ファイル: ClefPattern.java プロジェクト: sbunciak/symphonia
 @Override
 public boolean check(Glyph glyph) {
   return glyph.isClef();
 }
コード例 #21
0
  /**
   * From the list of vertical sticks, this method uses several tests to provide the initial
   * collection of good barlines candidates.
   *
   * @param sticks the collection of candidate sticks
   */
  public void checkCandidates(Collection<? extends Glyph> sticks) {
    //        // Sort candidates according to their abscissa
    //        List<Glyph> sortedSticks = new ArrayList<Glyph>(sticks);
    //        Collections.sort(sortedSticks, Glyph.midPosComparator);
    double minResult = constants.minCheckResult.getValue();

    // Check each candidate stick in turn
    for (Glyph stick : sticks) {
      // Allocate the candidate context, and pass the whole check suite
      GlyphContext context = new GlyphContext(stick);

      double res = suite.pass(context);

      if (logger.isDebugEnabled() || stick.isVip()) {
        logger.info(
            "suite => {}{} for {}",
            (float) res,
            (stick.getResult() != null) ? (" " + stick.getResult()) : "",
            stick);
      }

      if ((stick.isBar() && stick.isManualShape()) || res >= minResult) {
        // OK, we flag this candidate with proper barline shape
        contexts.put(stick, context);
        if ((!stick.isBar() || !stick.isManualShape())) {
          stick.setShape(isThickBar(stick) ? Shape.THICK_BARLINE : Shape.THIN_BARLINE);
        }

        // Additional processing for Bars that define a system or a part
        // (they start AND end with precise staves horizontal limits)
        if ((context.topStaff != -1) && (context.botStaff != -1)) {
          // Here, we have both part & system defining bars
          // System bars occur first
          // (since glyphs are sorted by increasing abscissa)
          stick.setResult(BAR_PART_DEFINING);

          logger.debug(
              "Part-defining Barline from staff {} to staff {} {}",
              context.topStaff,
              context.botStaff,
              stick);
        } else {
          if (logger.isDebugEnabled()) {
            logger.debug(
                "Non-Part-defining Bar line {}{}",
                (context.topStaff != -1) ? (" topIdx=" + context.topStaff) : "",
                (context.botStaff != -1) ? (" botIdx=" + context.botStaff) : "");
          }

          stick.setResult(BAR_NOT_PART_DEFINING);
        }
      } else {
        if (stick.isBar()) {
          if (logger.isDebugEnabled() || stick.isVip()) {
            logger.info("Purged {} {}", stick.idString(), stick.getShape());
          }

          stick.setShape(null);
        }
      }
    }
  }
コード例 #22
0
 @Override
 public void setVip() {
   stick.setVip();
 }
コード例 #23
0
 @Override
 public void setResult(Result result) {
   stick.setResult(result);
 }
コード例 #24
0
 // ~ Methods ------------------------------------------------------------
 @Override
 public boolean isVip() {
   return stick.isVip();
 }
コード例 #25
0
  /**
   * 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;
  }
コード例 #26
0
ファイル: TextRole.java プロジェクト: sbunciak/symphonia
  /**
   * 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);
  }
コード例 #27
0
 @Override
 public String toString() {
   return "stick#" + stick.getId();
 }