use of com.xenoage.zong.core.text.FormattedText in project Zong by Xenoage.
the class ChordNotator method compute.
public ChordNotation compute(Chord chord, Context context, @MaybeNull Notations notations) {
Score score = context.score;
float interlineSpace = score.getInterlineSpace(context.mp);
FontInfo lyricsFont = score.getFormat().getLyricFont();
MusicContext mc = score.getMusicContext(context.mp, BeforeOrAt, Before);
// grace or normal chord?
boolean grace = chord.isGrace();
ChordWidths chordWidths = (grace ? context.settings.graceChordWidths : context.settings.chordWidths);
ChordSpacings spacings = (grace ? context.settings.spacings.graceChordSpacings : context.settings.spacings.normalChordSpacings);
// use or compute stem direction
StemDirection stemDirection = chord.getStem().getDirection();
if (stemDirection == StemDirection.Default) {
// if stem direction was not computed yet, compute it now
if (notations != null)
stemDirection = notations.getChord(chord).stemDirection;
if (stemDirection == StemDirection.Default) {
Map<Chord, StemDirection> computedStems = stemDirector.compute(chord);
stemDirection = computedStems.get(chord);
// also remember the other computed stems
if (notations != null)
for (Chord computedChord : computedStems.keySet()) notations.getChord(computedChord).stemDirection = computedStems.get(computedChord);
}
}
// notes displacement
NotesNotation notes = notesNotator.compute(chord, stemDirection, chordWidths, mc);
float leftSuspendedWidth = (notes.leftSuspended ? notes.noteheadWidthIs : 0);
// accidentals
AccidentalsNotation accs = accidentalsNotator.compute(chord, notes, chordWidths, mc);
// symbol's width: width of the noteheads and dots
float symbolWidth = notes.widthIs - leftSuspendedWidth;
float frontGap = accs.widthIs + leftSuspendedWidth;
// rear gap: empty duration-dependent space behind the chord minus the symbol's width
float rearGap = spacings.getWidth(chord.getDisplayedDuration()) - symbolWidth;
// lyric width
float lyricWidth = 0;
TextMeasurer textMeasurer = platformUtils().getTextMeasurer();
for (Lyric lyric : chord.getLyrics()) {
if (lyric != null && lyric.getText() != null) {
// width of lyric in interline spaces
FormattedText lyricText = styleText(lyric.getText(), new FormattedTextStyle(lyricsFont));
float l = lyricText.getWidth() / interlineSpace;
// for start and end syllable, request "-" more space, for middle syllables "--"
// TODO: unsymmetric - start needs space on the right, end on the left, ...
SyllableType lyricType = lyric.getSyllableType();
if (lyricType == SyllableType.Begin || lyricType == SyllableType.End) {
l += textMeasurer.measure(lyricsFont, "-").getWidth() / interlineSpace;
} else if (lyricType == SyllableType.Middle) {
l += textMeasurer.measure(lyricsFont, "--").getWidth() / interlineSpace;
}
// save width of the widest lyric
lyricWidth = Math.max(lyricWidth, l);
}
}
// compute length of the stem (if any)
float scaling = grace ? context.settings.scalingGrace : 1;
StemNotation stem = stemNotator.compute(chord.getStem(), notes.getLps(), stemDirection, context.mp.getStaff(), Companion.staffLines(mc.getLinesCount()), scaling);
// compute articulations
ArticulationsNotation arts = articulationsNotator.compute(chord, stemDirection, notes, mc.getLinesCount());
return new ChordNotation(chord, chord.getMP(), new ElementWidth(frontGap, symbolWidth, rearGap, lyricWidth), context.mp.getStaff(), notes, stemDirection, stem, accs, arts);
}
use of com.xenoage.zong.core.text.FormattedText in project Zong by Xenoage.
the class CreditsReader method createFormattedText.
/**
* Creates a {@link FormattedText} and returns it.
*/
private static FormattedText createFormattedText(MxlCreditWords mxlCreditWords, FontInfo defaultFont) {
CList<FormattedTextParagraph> paragraphs = clist();
CList<FormattedTextElement> elements = clist();
// iterate through all credit-words elements.
// currently we are only interested in credit-words elements on page 1.
Alignment alignment = FormattedTextParagraph.Companion.getDefaultAlignment();
for (MxlFormattedText mxlFormattedText : mxlCreditWords.getItems()) {
// read text. if empty, ignore this element
String textContent = mxlFormattedText.getValue();
if (textContent.length() == 0)
continue;
// apply horizontal alignment, if set, otherwise keep the old value
Alignment newAlignment = readAlignment(mxlFormattedText.getJustify());
if (newAlignment != null) {
alignment = newAlignment;
}
// since we use paragraphs but MusicXML doesn't, split
// the text where there are line breaks.
String[] textLines = textContent.split("\n");
boolean endsWithLineBreak = textContent.endsWith("\n");
// new paragraphs for the following lines
for (int iLine = 0; iLine < textLines.length; iLine++) {
if (iLine > 0) {
// not the first line: we have to create a new paragraph
paragraphs.add(new FormattedTextParagraph(elements.close(), alignment));
elements = clist();
}
// read line
String textLine = textLines[iLine];
if (textLine.length() > 0) {
// font
FontInfo fontInfo = new FontInfoReader(mxlFormattedText.getPrintStyle().getFont(), defaultFont).read();
// color
Color color = mxlFormattedText.getPrintStyle().getColor().getValue();
// create text element
FormattedTextElement textElement = new FormattedTextString(textLine, new FormattedTextStyle(fontInfo, color, null));
elements.add(textElement);
}
}
if (endsWithLineBreak) {
// create a new paragraph
paragraphs.add(new FormattedTextParagraph(elements.close(), alignment));
elements = clist();
}
}
// add non-empty paragraph at the end
if (elements.size() > 0) {
paragraphs.add(new FormattedTextParagraph(elements.close(), alignment));
}
return new FormattedText(paragraphs.close());
}
use of com.xenoage.zong.core.text.FormattedText in project Zong by Xenoage.
the class TupletRenderer method draw.
/**
* Draws the given {@link TupletStamping} on the given {@link Canvas},
* using the given {@link RendererArgs}.
*/
@Override
public void draw(Stamping stamping, Canvas canvas, RendererArgs args) {
TupletStamping tuplet = (TupletStamping) stamping;
StaffStamping parentStaff = tuplet.parentStaff;
float scaling = args.targetScaling;
// horizontal position
float x1Mm = tuplet.leftSP.xMm;
float x2Mm = tuplet.rightSP.xMm;
// height of hook is 1 IS
float hookHeightPx = Units.mmToPx(parentStaff.is, scaling);
// width and color of the line
Color color = Color.Companion.getBlack();
// a little bit thicker than staff line
float width = parentStaff.getLineWidthMm() * 1.5f;
float paintWidth;
// compute the horizontal line and color
float y1Mm, y2Mm;
Color paintColor;
if (canvas.getFormat() == CanvasFormat.Raster) {
BitmapStaff ss = parentStaff.getBitmapInfo().getBitmapStaff(scaling);
y1Mm = parentStaff.positionMm.y + ss.getYMm(tuplet.leftSP.lp);
y2Mm = parentStaff.positionMm.y + ss.getYMm(tuplet.rightSP.lp);
BitmapLine screenLine = parentStaff.getBitmapInfo().getBitmapLine(scaling, width, color);
paintColor = screenLine.color;
paintWidth = screenLine.widthMm;
} else {
y1Mm = parentStaff.computeYMm(tuplet.leftSP.lp);
y2Mm = parentStaff.computeYMm(tuplet.rightSP.lp);
paintColor = color;
paintWidth = width;
}
// compute gap for text
FormattedText text = tuplet.text;
float gapMm = 0;
float textMm = 0;
if (text != null && text.getParagraphs().size() > 0) {
textMm = text.getFirstParagraph().getMetrics().getWidth();
gapMm = textMm * 2;
}
// draw line and hooks
if (gapMm > 0) {
// two lines, when there is text in between
float xGapLMm = (x2Mm + x1Mm) / 2 - gapMm / 2;
float xGapRMm = xGapLMm + gapMm;
float gapVerticalMm = gapMm / (x2Mm - x1Mm) * (y2Mm - y1Mm);
float yGapLMm = (y2Mm + y1Mm) / 2 - gapVerticalMm / 2;
float yGapRMm = yGapLMm + gapVerticalMm;
canvas.drawLine(new Point2f(x1Mm, y1Mm), new Point2f(xGapLMm, yGapLMm), paintColor, paintWidth);
canvas.drawLine(new Point2f(xGapRMm, yGapRMm), new Point2f(x2Mm, y2Mm), paintColor, paintWidth);
} else {
// no gap
canvas.drawLine(new Point2f(x1Mm, y1Mm), new Point2f(x2Mm, y2Mm), paintColor, paintWidth);
}
// hooks
canvas.drawLine(new Point2f(x1Mm, y1Mm), new Point2f(x1Mm, y1Mm + hookHeightPx * (tuplet.leftSP.lp < 0 ? -1 : 1)), paintColor, paintWidth);
canvas.drawLine(new Point2f(x2Mm, y2Mm), new Point2f(x2Mm, y2Mm + hookHeightPx * (tuplet.rightSP.lp < 0 ? -1 : 1)), paintColor, paintWidth);
// draw text
if (text != null && text.getParagraphs().size() > 0) {
float textAscent = text.getFirstParagraph().getMetrics().getAscent();
float textX = (x1Mm + x2Mm) / 2 - textMm / 2;
float textY = (y1Mm + y2Mm) / 2 + textAscent / 2;
canvas.drawText(tuplet.text, null, new Point2f(textX, textY), true, 0);
}
}
use of com.xenoage.zong.core.text.FormattedText in project Zong by Xenoage.
the class VoltaRenderer method draw.
/**
* Draws the given {@link VoltaStamping} on the given {@link Canvas},
* using the given {@link RendererArgs}.
*/
@Override
public void draw(Stamping stamping, Canvas canvas, RendererArgs args) {
VoltaStamping volta = (VoltaStamping) stamping;
StaffStamping parentStaff = volta.parentStaff;
float scaling = args.scaling;
// horizontal position
float x1 = volta.leftXMm + parentStaff.positionMm.x;
float x2 = volta.rightXMm + parentStaff.positionMm.x;
// compute hooks
boolean hook = volta.leftHook || volta.rightHook;
float hookHeight = 0;
if (hook) {
// height of hook is 2 interline spaces
hookHeight = parentStaff.is * 2;
}
// width and color of the line
Color color = Color.Companion.getBlack();
// a little bit thicker than staff line
float width = parentStaff.getLineWidthMm() * 1.5f;
float paintWidth;
// compute the horizontal line and color
float y;
Color paintColor;
if (canvas.getFormat() == CanvasFormat.Raster) {
BitmapStaff ss = parentStaff.getBitmapInfo().getBitmapStaff(scaling);
y = parentStaff.positionMm.y + ss.getYMm(volta.lp);
BitmapLine screenLine = parentStaff.getBitmapInfo().getBitmapLine(scaling, width, color);
paintColor = screenLine.color;
paintWidth = screenLine.widthMm;
} else {
y = parentStaff.computeYMm(volta.lp);
paintColor = color;
paintWidth = width;
}
// draw line and hooks
canvas.drawLine(new Point2f(x1, y), new Point2f(x2, y), paintColor, paintWidth);
if (volta.leftHook) {
canvas.drawLine(new Point2f(x1, y), new Point2f(x1, y + hookHeight), paintColor, paintWidth);
}
if (volta.rightHook) {
canvas.drawLine(new Point2f(x2, y), new Point2f(x2, y + hookHeight), paintColor, paintWidth);
}
// draw text
FormattedText text = volta.text;
if (text != null && text.getParagraphs().size() > 0) {
float textAscent = text.getFirstParagraph().getMetrics().getAscent();
float textX = x1 + parentStaff.is * 1;
float textY = y + textAscent;
canvas.drawText(volta.text, null, new Point2f(textX, textY), true, 0);
}
}
use of com.xenoage.zong.core.text.FormattedText in project Zong by Xenoage.
the class Test32b method getFormattedTextElement.
private FormattedTextElement getFormattedTextElement(Words words, MP mp) {
assertTrue("" + mp, words.getText() instanceof FormattedText);
FormattedText wordsText = (FormattedText) words.getText();
assertEquals("" + mp, 1, wordsText.getParagraphs().size());
FormattedTextParagraph wordsPara = wordsText.getFirstParagraph();
assertEquals("" + mp, 1, wordsPara.getElements().size());
FormattedTextElement wordsElem = wordsPara.getElements().getFirst();
return wordsElem;
}
Aggregations