MuseScore/libmscore/elementlayout.cpp
2017-12-20 16:49:58 +01:00

248 lines
8.1 KiB
C++

//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2010-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 "elementlayout.h"
#include "xml.h"
#include "element.h"
#include "text.h"
#include "mscore.h"
namespace Ms {
//---------------------------------------------------------
// ElementLayout
//---------------------------------------------------------
ElementLayout::ElementLayout()
{
_align = Align::LEFT | Align::BASELINE;
_offsetType = OffsetType::SPATIUM;
}
//---------------------------------------------------------
// offset
//---------------------------------------------------------
QPointF ElementLayout::offset(qreal spatium) const
{
QPointF o(_offset);
if (_offsetType == OffsetType::SPATIUM)
o *= spatium;
else
o *= DPI;
return o;
}
//---------------------------------------------------------
// layout
// height() and width() should return sensible
// values when calling this method
//---------------------------------------------------------
void ElementLayout::layout(Element* e) const
{
QPointF o(offset(e->spatium()));
qreal w = 0.0;
qreal h = 0.0;
bool frameText = e->isText() && toText(e)->layoutToParentWidth() && e->parent();
QPointF p;
if (frameText)
h = e->parent()->height();
else
w = e->width();
if (_align & Align::BOTTOM)
p.setY(h - e->height());
else if (_align & Align::VCENTER)
p.setY((h - e->height()) * .5);
else if (_align & Align::BASELINE)
p.setY(-e->baseLine());
if (!frameText) {
if (_align & Align::RIGHT)
p.setX(-w);
else if (_align & Align::HCENTER)
p.setX(-(w * .5));
}
e->setPos(p + o);
}
//---------------------------------------------------------
// writeProperties
// writout only differences to l
//---------------------------------------------------------
void ElementLayout::writeProperties(XmlWriter& xml, const ElementLayout& l) const
{
if ((l._align & Align::HMASK) != (_align & Align::HMASK)) {
const char* p;
if (_align & Align::HCENTER)
p = "center";
else if (_align & Align::RIGHT)
p = "right";
else
p = "left";
xml.tag("halign", p);
}
if ((l._align & Align::VMASK) != (_align & Align::VMASK)) {
const char* p;
if (_align & Align::BOTTOM)
p = "bottom";
else if (_align & Align::VCENTER)
p = "center";
else if (_align & Align::BASELINE)
p = "baseline";
else
p = "top";
xml.tag("valign", p);
}
if (l._offset != _offset) {
QPointF pt(_offset);
if (offsetType() == OffsetType::ABS)
pt *= INCH;
xml.tag("xoffset", pt.x()); // save in spatium or metric mm
xml.tag("yoffset", pt.y());
}
if (_offsetType != l._offsetType) {
const char* p = 0;
switch(_offsetType) {
case OffsetType::SPATIUM: p = "spatium"; break;
case OffsetType::ABS: p = "absolute"; break;
}
xml.tag("offsetType", p);
}
}
//---------------------------------------------------------
// writeProperties
//---------------------------------------------------------
void ElementLayout::writeProperties(XmlWriter& xml) const
{
if (_align & Align::HCENTER)
xml.tag("halign", "center");
else if (_align & Align::RIGHT)
xml.tag("halign", "right");
else
xml.tag("halign", "left");
if (_align & Align::BOTTOM)
xml.tag("valign", "bottom");
else if (_align & Align::VCENTER)
xml.tag("valign", "center");
else if (_align & Align::BASELINE)
xml.tag("valign", "baseline");
else
xml.tag("valign", "top");
if (!_offset.isNull()) {
QPointF pt(_offset);
if (offsetType() == OffsetType::ABS)
pt *= INCH;
xml.tag("xoffset", pt.x()); // save in spatium or metric mm
xml.tag("yoffset", pt.y());
}
const char* p = 0;
switch(_offsetType) {
case OffsetType::SPATIUM: p = "spatium"; break;
case OffsetType::ABS: p = "absolute"; break;
}
xml.tag("offsetType", p);
}
//---------------------------------------------------------
// readProperties
//---------------------------------------------------------
bool ElementLayout::readProperties(XmlReader& e)
{
const QStringRef& tag(e.name());
if (tag == "halign") {
const QString& val(e.readElementText());
_align = Align(int(_align) & int(~(Align::HCENTER | Align::RIGHT)));
if (val == "center")
_align = _align | Align::HCENTER;
else if (val == "right")
_align = _align | Align::RIGHT;
else if (val == "left")
;
else
qDebug("Text::readProperties: unknown alignment: <%s>", qPrintable(val));
}
else if (tag == "valign") {
const QString& val(e.readElementText());
_align = Align(int(_align) & int(~(Align::VCENTER | Align::BOTTOM | Align::BASELINE)));
if (val == "center")
_align = _align | Align::VCENTER;
else if (val == "bottom")
_align = _align | Align::BOTTOM;
else if (val == "baseline")
_align = _align | Align::BASELINE;
else if (val == "top")
;
else
qDebug("Text::readProperties: unknown alignment: <%s>", qPrintable(val));
}
else if (tag == "xoffset") {
qreal xo = e.readDouble();
if (offsetType() == OffsetType::ABS)
xo /= INCH;
setXoff(xo);
}
else if (tag == "yoffset") {
qreal yo = e.readDouble();
if (offsetType() == OffsetType::ABS)
yo /= INCH;
setYoff(yo);
}
else if (tag == "rxoffset") // obsolete
e.readDouble();
else if (tag == "ryoffset") // obsolete
e.readDouble();
else if (tag == "offsetType") {
const QString& val(e.readElementText());
OffsetType ot = OffsetType::ABS;
if (val == "spatium" || val == "1")
ot = OffsetType::SPATIUM;
if (ot != offsetType()) {
setOffsetType(ot);
if (ot == OffsetType::ABS)
_offset /= INCH; // convert spatium -> inch
else
_offset *= INCH; // convert inch -> spatium
}
}
else
return false;
return true;
}
//---------------------------------------------------------
// restyle
//---------------------------------------------------------
void ElementLayout::restyle(const ElementLayout& ol, const ElementLayout& nl)
{
if ((ol._align & Align::HMASK) == (_align & Align::HMASK))
_align = Align(_align | Align(int(nl._align) & int(Align::HMASK)));
if ((ol._align & Align::VMASK) == (_align & Align::VMASK))
_align = _align | Align((int(nl._align) & int(Align::VMASK)));
if (ol._offset == _offset)
_offset = nl._offset;
if (_offsetType == ol._offsetType)
_offsetType = nl._offsetType;
}
}