Skip to content

Commit

Permalink
fix #285434 : Certain 2.x frame texts imported with no style
Browse files Browse the repository at this point in the history
  • Loading branch information
AntonioBL committed Apr 13, 2020
1 parent a36499a commit 78d9a29
Show file tree
Hide file tree
Showing 7 changed files with 839 additions and 78 deletions.
101 changes: 53 additions & 48 deletions libmscore/read206.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1524,39 +1524,62 @@ bool readNoteProperties206(Note* note, XmlReader& e)
}

//---------------------------------------------------------
// readTextPropertyStyle206
// This reads only the 'style' tag, so that it can be read
// before setting anything else.
// ReadStyleName206
// For 2.x files, the style tag could be in a different
// position with respect to 3.x files. Since seek
// position is not reliable for readline in QIODevices (for
// example because of non-single-byte characters in at least
// one of the fields; some two-byte characters are counted as
// two single-byte characters and thus the reading could
// start at the wrong position)
//---------------------------------------------------------

static bool readTextPropertyStyle206(XmlReader& e, TextBase* t, Element* be, QStringRef elementName)
static QString ReadStyleName206(XmlReader& e)
{
QString s;
if (e.readAheadAvailable()) {
e.performReadAhead([&s, &elementName](QIODevice& dev) {
const QString closeTag = QString("</").append(elementName.toString()).append(">");
QByteArray arrLine = dev.readLine();
while (!arrLine.isEmpty()) {
QString line(arrLine);
if (line.contains("<style>")) {
QRegExp re("<style>([^<]+)</style>");
if (re.indexIn(line) > -1)
s = re.cap(1);
return;
}
else if (line.contains(closeTag)) {
return;
}

arrLine = dev.readLine();
QIODevice* device = e.getDevice();
if (!device || device->isSequential())
return s;
if (!device->isOpen())
device->open(QIODevice::ReadOnly);
const auto pos = device->pos();
const auto pos1 = e.characterOffset();
const QString tagName = e.name().toString();
device->seek(0);
XmlReader streamReader(device);
QString xmltag;
QString name;
for (;;) {
streamReader.readNextStartElement();
name = streamReader.name().toString();
if ((name == tagName) && (streamReader.characterOffset() == pos1)) {
xmltag = streamReader.readXml();
if (xmltag.contains("<style>")) {
QRegExp re("<style>([^<]+)</style>");
if (re.indexIn(xmltag) > -1)
s = re.cap(1);
}
});
break;
}
if (streamReader.atEnd())
break;
}
else
return false;
device->seek(pos);
return s;
}

//---------------------------------------------------------
// readTextPropertyStyle206
// This reads only the 'style' tag, so that it can be read
// before setting anything else.
//---------------------------------------------------------

static bool readTextPropertyStyle206(XmlReader& e, TextBase* t, Element* be)
{
QString s = ReadStyleName206(e);

if (s.isEmpty())
return true;
return false;

if (!be->isTuplet()) { // Hack
if (excessTextStyles206.find(s) != excessTextStyles206.end()) {
Expand Down Expand Up @@ -1665,7 +1688,7 @@ static bool readTextProperties206(XmlReader& e, TextBase* t)

static void readText206(XmlReader& e, TextBase* t, Element* be)
{
readTextPropertyStyle206(e, t, be, e.name());
readTextPropertyStyle206(e, t, be);
while (e.readNextStartElement()) {
if (!readTextProperties206(e, t))
e.unknown();
Expand All @@ -1678,7 +1701,7 @@ static void readText206(XmlReader& e, TextBase* t, Element* be)

static void readTempoText(TempoText* t, XmlReader& e)
{
readTextPropertyStyle206(e, t, t, e.name());
readTextPropertyStyle206(e, t, t);
while (e.readNextStartElement()) {
const QStringRef& tag(e.name());
if (tag == "tempo")
Expand All @@ -1703,7 +1726,7 @@ static void readTempoText(TempoText* t, XmlReader& e)

static void readMarker(Marker* m, XmlReader& e)
{
readTextPropertyStyle206(e, m, m, e.name());
readTextPropertyStyle206(e, m, m);
Marker::Type mt = Marker::Type::SEGNO;

while (e.readNextStartElement()) {
Expand All @@ -1725,7 +1748,7 @@ static void readMarker(Marker* m, XmlReader& e)

static void readDynamic(Dynamic* d, XmlReader& e)
{
readTextPropertyStyle206(e, d, d, e.name());
readTextPropertyStyle206(e, d, d);
while (e.readNextStartElement()) {
const QStringRef& tag = e.name();
if (tag == "subtype")
Expand Down Expand Up @@ -3130,25 +3153,7 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e)
// MuseScore 3 has different types for system text and
// staff text while MuseScore 2 didn't.
// We need to decide first which one we should create.
QString styleName;
if (e.readAheadAvailable()) {
e.performReadAhead([&styleName, tag](QIODevice& dev) {
const QString closeTag = QString("</").append(tag).append(">");
QByteArray arrLine = dev.readLine();
while (!arrLine.isEmpty()) {
QString line(arrLine);
if (line.contains("<style>")) {
QRegExp re("<style>([A-z0-9]+)</style>");
if (re.indexIn(line) > -1)
styleName = re.cap(1);
return;
}
if (line.contains(closeTag))
return;
arrLine = dev.readLine();
}
});
}
QString styleName = ReadStyleName206(e);
StaffTextBase* t;
if (styleName == "System" || styleName == "Tempo"
|| styleName == "Marker" || styleName == "Jump"
Expand Down
6 changes: 3 additions & 3 deletions libmscore/scorefile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -848,8 +848,8 @@ Score::FileError MasterScore::loadCompressedMsc(QIODevice* io, bool ignoreVersio
}
}
XmlReader e(dbuf);
QBuffer readAheadBuf(&dbuf);
e.setReadAheadDevice(&readAheadBuf);
QBuffer readBuf(&dbuf);
e.setDevice(&readBuf);
e.setDocName(masterScore()->fileInfo()->completeBaseName());

FileError retval = read1(e, ignoreVersionError);
Expand Down Expand Up @@ -907,7 +907,7 @@ Score::FileError MasterScore::loadMsc(QString name, QIODevice* io, bool ignoreVe
return loadCompressedMsc(io, ignoreVersionError);
else {
XmlReader r(io);
r.setReadAheadDevice(io);
r.setDevice(io);
return read1(r, ignoreVersionError);
}
}
Expand Down
11 changes: 5 additions & 6 deletions libmscore/xml.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ class XmlReader : public QXmlStreamReader {
QString docName; // used for error reporting

// For readahead possibility.
// If needed, must be explicitly set by setReadAheadDevice.
QIODevice* _readAheadDevice = nullptr;
// If needed, must be explicitly set by setDevice.
QIODevice* _readDevice = nullptr;

// Score read context (for read optimizations):
Fraction _tick { Fraction(0, 1) };
Expand Down Expand Up @@ -205,10 +205,9 @@ class XmlReader : public QXmlStreamReader {
Tid addUserTextStyle(const QString& name);
Tid lookupUserTextStyle(const QString& name);

// Ownership on read ahead device is NOT transferred to XmlReader.
void setReadAheadDevice(QIODevice* dev) { if (!dev->isSequential()) _readAheadDevice = dev; }
bool readAheadAvailable() const { return bool(_readAheadDevice); }
void performReadAhead(std::function<void(QIODevice&)> readAheadRoutine);
// Ownership on read device is NOT transferred to XmlReader.
void setDevice(QIODevice* dev) { if (!dev->isSequential()) _readDevice = dev; }
QIODevice* getDevice() { return _readDevice; }

QList<std::pair<Element*, QPointF>>& fixOffsets() { return _fixOffsets; }
};
Expand Down
21 changes: 0 additions & 21 deletions libmscore/xmlreader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -547,27 +547,6 @@ Tid XmlReader::lookupUserTextStyle(const QString& name)
return Tid::TEXT_STYLES; // not found
}

//---------------------------------------------------------
// performReadAhead
// If f is called, the device will be non-sequential and
// open. Reading position equals to the current value of
// characterOffset(), but it is possible to seek for any
// other position inside f.
//---------------------------------------------------------

void XmlReader::performReadAhead(std::function<void(QIODevice&)> f)
{
if (!_readAheadDevice || _readAheadDevice->isSequential())
return;
if (!_readAheadDevice->isOpen())
_readAheadDevice->open(QIODevice::ReadOnly);

const auto pos = _readAheadDevice->pos();
_readAheadDevice->seek(characterOffset());
f(*_readAheadDevice);
_readAheadDevice->seek(pos);
}

//---------------------------------------------------------
// addConnectorInfo
//---------------------------------------------------------
Expand Down
Loading

0 comments on commit 78d9a29

Please sign in to comment.