MuseScore/libmscore/symbol.cpp

313 lines
9.4 KiB
C++
Raw Normal View History

//=============================================================================
2012-05-26 14:26:10 +02:00
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2002-2011 Werner Schweer
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2
// as published by the Free Software Foundation and appearing in
// the file LICENCE.GPL
//=============================================================================
#include "symbol.h"
#include "sym.h"
#include "xml.h"
#include "system.h"
#include "staff.h"
#include "measure.h"
#include "page.h"
#include "score.h"
#include "image.h"
2013-05-13 18:49:17 +02:00
namespace Ms {
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
// Symbol
//---------------------------------------------------------
Symbol::Symbol(Score* s)
: BSymbol(s)
{
2013-11-06 15:58:05 +01:00
_sym = SymId::accidentalSharp; // arbitrary valid default
setZ(int(Element::Type::SYMBOL) * 100);
2012-05-26 14:26:10 +02:00
}
Symbol::Symbol(const Symbol& s)
: BSymbol(s)
{
2014-06-27 13:41:49 +02:00
_sym = s._sym;
_scoreFont = s._scoreFont;
setZ(int(Element::Type::SYMBOL) * 100);
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// setAbove
//---------------------------------------------------------
void Symbol::setAbove(bool val)
{
setYoff(val ? -2.0 : 7.0);
}
//---------------------------------------------------------
// layout
// height() and width() should return sensible
// values when calling this method
//---------------------------------------------------------
void Symbol::layout()
{
2014-07-15 15:05:36 +02:00
// foreach(Element* e, leafs()) done in BSymbol::layout() ?
// e->layout();
2012-05-26 14:26:10 +02:00
ElementLayout::layout(this);
BSymbol::layout();
setbbox(_scoreFont ? _scoreFont->bbox(_sym, magS()) : symBbox(_sym));
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// Symbol::draw
//---------------------------------------------------------
void Symbol::draw(QPainter* p) const
{
if (type() != Element::Type::NOTEDOT || !staff()->isTabStaff()) {
2012-05-26 14:26:10 +02:00
p->setPen(curColor());
if (_scoreFont)
_scoreFont->draw(_sym, p, magS(), QPointF());
else
drawSymbol(_sym, p);
2012-05-26 14:26:10 +02:00
}
}
//---------------------------------------------------------
// Symbol::write
//---------------------------------------------------------
void Symbol::write(Xml& xml) const
{
xml.stag(name());
xml.tag("name", Sym::id2name(_sym));
if (_scoreFont)
xml.tag("font", _scoreFont->name());
2013-01-23 14:14:09 +01:00
BSymbol::writeProperties(xml);
2012-05-26 14:26:10 +02:00
xml.etag();
}
//---------------------------------------------------------
// Symbol::read
//---------------------------------------------------------
2013-01-11 18:10:18 +01:00
void Symbol::read(XmlReader& e)
2012-05-26 14:26:10 +02:00
{
QPointF pos;
2013-01-11 18:10:18 +01:00
while (e.readNextStartElement()) {
const QStringRef& tag(e.name());
2012-05-26 14:26:10 +02:00
if (tag == "name") {
2013-01-11 18:10:18 +01:00
QString val(e.readElementText());
SymId symId = Sym::name2id(val);
2013-11-19 12:12:07 +01:00
if (val != "noSym") {
if (symId == SymId::noSym) {
2013-11-19 12:12:07 +01:00
// if symbol name not found, fall back to user names
// TODO : does it make sense? user names are probably localized
symId = Sym::userName2id(val);
// if not found, look into old names
if (symId == SymId::noSym)
symId = Sym::oldName2id(val);
if (symId == SymId::noSym) {
qDebug("unknown symbol <%s>, falling back to no symbol", qPrintable(val));
2013-11-19 12:12:07 +01:00
// set a default symbol, or layout() will crash
symId = SymId::noSym;
2013-11-19 12:12:07 +01:00
}
}
2012-05-26 14:26:10 +02:00
}
setSym(symId);
2012-05-26 14:26:10 +02:00
}
else if (tag == "font")
_scoreFont = ScoreFont::fontFactory(e.readElementText());
2012-05-26 14:26:10 +02:00
else if (tag == "Symbol") {
Symbol* s = new Symbol(score());
s->read(e);
s->adjustReadPos();
add(s);
}
else if (tag == "Image") {
if (MScore::noImages)
e.skipCurrentElement();
else {
Image* image = new Image(score());
image->read(e);
add(image);
}
2012-05-26 14:26:10 +02:00
}
2013-06-04 18:29:14 +02:00
else if (tag == "small" || tag == "subtype") // obsolete
e.skipCurrentElement();
2013-01-23 14:14:09 +01:00
else if (!BSymbol::readProperties(e))
2013-01-11 18:10:18 +01:00
e.unknown();
2012-05-26 14:26:10 +02:00
}
setPos(pos);
}
//---------------------------------------------------------
// dragAnchor
//---------------------------------------------------------
QLineF BSymbol::dragAnchor() const
{
if (parent() && parent()->type() == Element::Type::SEGMENT) {
2012-05-26 14:26:10 +02:00
System* system = segment()->measure()->system();
qreal y = system->staff(staffIdx())->y() + system->y();
2013-07-04 10:56:31 +02:00
// QPointF anchor(segment()->pageX(), y);
QPointF anchor(segment()->canvasPos().x(), y);
2012-05-26 14:26:10 +02:00
return QLineF(canvasPos(), anchor);
}
else {
return QLineF(canvasPos(), parent()->canvasPos());
}
}
//---------------------------------------------------------
// pagePos
//---------------------------------------------------------
QPointF BSymbol::pagePos() const
{
if (parent() && (parent()->type() == Element::Type::SEGMENT)) {
2012-05-26 14:26:10 +02:00
QPointF p(pos());
System* system = segment()->measure()->system();
if (system) {
p.ry() += system->staff(staffIdx())->y() + system->y();
}
p.rx() = pageX();
return p;
}
else
return Element::pagePos();
}
//---------------------------------------------------------
// canvasPos
//---------------------------------------------------------
QPointF BSymbol::canvasPos() const
{
if (parent() && (parent()->type() == Element::Type::SEGMENT)) {
2012-05-26 14:26:10 +02:00
QPointF p(pos());
Segment* s = static_cast<Segment*>(parent());
System* system = s->measure()->system();
if (system) {
int si = staffIdx();
p.ry() += system->staff(si)->y() + system->y();
Page* page = system->page();
if (page)
p.ry() += page->y();
}
p.rx() = canvasX();
return p;
}
else
return Element::canvasPos();
}
//---------------------------------------------------------
// FSymbol
//---------------------------------------------------------
FSymbol::FSymbol(Score* s)
2013-01-23 14:14:09 +01:00
: BSymbol(s)
2012-05-26 14:26:10 +02:00
{
_code = 0;
2012-05-26 14:26:10 +02:00
_font.setStyleStrategy(QFont::NoFontMerging);
}
FSymbol::FSymbol(const FSymbol& s)
2013-01-23 14:14:09 +01:00
: BSymbol(s)
2012-05-26 14:26:10 +02:00
{
_font = s._font;
_code = s._code;
}
//---------------------------------------------------------
// draw
//---------------------------------------------------------
void FSymbol::draw(QPainter* painter) const
{
QString s;
painter->setFont(_font);
if (_code & 0xffff0000) {
s = QChar(QChar::highSurrogate(_code));
s += QChar(QChar::lowSurrogate(_code));
}
else
s = QChar(_code);
2013-06-28 21:07:28 +02:00
painter->setPen(curColor());
2012-05-26 14:26:10 +02:00
painter->drawText(QPointF(0, 0), s);
}
//---------------------------------------------------------
// write
//---------------------------------------------------------
void FSymbol::write(Xml& xml) const
{
xml.stag(name());
xml.tag("font", _font.family());
xml.tag("fontsize", _font.pixelSize());
xml.tag("code", _code);
2013-01-23 14:14:09 +01:00
BSymbol::writeProperties(xml);
2012-05-26 14:26:10 +02:00
xml.etag();
}
//---------------------------------------------------------
// read
//---------------------------------------------------------
2013-01-11 18:10:18 +01:00
void FSymbol::read(XmlReader& e)
2012-05-26 14:26:10 +02:00
{
2013-01-11 18:10:18 +01:00
while (e.readNextStartElement()) {
const QStringRef& tag(e.name());
2012-05-26 14:26:10 +02:00
if (tag == "font")
2013-01-11 18:10:18 +01:00
_font.setFamily(e.readElementText());
2012-05-26 14:26:10 +02:00
else if (tag == "fontsize")
2013-01-11 18:10:18 +01:00
_font.setPixelSize(e.readInt());
2012-05-26 14:26:10 +02:00
else if (tag == "code")
2013-01-11 18:10:18 +01:00
_code = e.readInt();
2013-01-23 14:14:09 +01:00
else if (!BSymbol::readProperties(e))
2013-01-11 18:10:18 +01:00
e.unknown();
2012-05-26 14:26:10 +02:00
}
setPos(QPointF());
}
//---------------------------------------------------------
// layout
//---------------------------------------------------------
void FSymbol::layout()
{
QString s;
if (_code & 0xffff0000) {
s = QChar(QChar::highSurrogate(_code));
s += QChar(QChar::lowSurrogate(_code));
}
else
s = QChar(_code);
QFontMetricsF fm(_font);
setbbox(fm.boundingRect(s));
adjustReadPos();
}
//---------------------------------------------------------
// setFont
//---------------------------------------------------------
void FSymbol::setFont(const QFont& f)
{
_font = f;
_font.setStyleStrategy(QFont::NoFontMerging);
}
2013-05-13 18:49:17 +02:00
}