removed OMR, OCR, AVSOMR

This commit is contained in:
Igor Korsukov 2020-12-02 16:21:50 +02:00
parent 36d6beca3f
commit ec18e98ae7
385 changed files with 2 additions and 184263 deletions

View file

@ -175,21 +175,13 @@ endif (NOT APPLE AND NOT MINGW AND NOT MSVC)
option(ZERBERUS "Enable experimental SFZ sampler" ON)
option(USE_ZITA_REVERB "Enable Zita Reverb audio effect" ON)
option(OSC "Enable OSC remote control protocol" ON)
option(AVSOMR "Enable AVSOMR import" OFF) # AVSOMR - optical music recognition by audirevis
option(OMR "Enable PDF import" OFF) # OMR - optical music recognition
# For installation see: http://ubuntuforums.org/showthread.php?t=1647350
option(OCR "Enable OCR, requires OMR" OFF) # Requires tesseract 3.0, needs work on mac/win
option(SOUNDFONT3 "Ogg Vorbis compressed fonts" ON) # Enable Ogg Vorbis compressed fonts, requires Ogg & Vorbis
option(HAS_AUDIOFILE "Enable audio export" ON) # Requires libsndfile
option(USE_SYSTEM_QTSINGLEAPPLICATION "Use system QtSingleApplication" OFF)
option(USE_SYSTEM_FREETYPE "Use system FreeType" OFF) # requires freetype >= 2.5.2, does not work on win
option(USE_SYSTEM_POPPLER "Use system Poppler for OMR" OFF)
option(BUILD_LAME "Enable MP3 export" ON) # Requires libmp3lame, call CMake with -DBUILD_LAME="OFF" to disable
option(DOWNLOAD_SOUNDFONT "Download the latest soundfont version as part of the build process" ON)
# licence incompatibility, must never be distributed
set(OCR OFF)
SET(JACK_LONGNAME "JACK (Jack Audio Connection Kit)")
SET(JACK_MIN_VERSION "0.98.0")
option(BUILD_JACK "Build with support for ${JACK_LONGNAME} audio backend. JACK >= ${JACK_MIN_VERSION} will be needed." ON)
@ -840,16 +832,6 @@ else (USE_SYSTEM_FREETYPE)
include_directories(${PROJECT_SOURCE_DIR}/thirdparty/freetype/include)
endif (USE_SYSTEM_FREETYPE)
if (OMR)
if (NOT USE_SYSTEM_POPPLER)
include_directories(${PROJECT_SOURCE_DIR}/thirdparty/poppler)
include_directories(${PROJECT_SOURCE_DIR}/thirdparty/poppler/poppler)
else (NOT USE_SYSTEM_POPPLER)
include_directories(/usr/include/poppler)
include_directories(/usr/include/poppler/qt5)
endif (NOT USE_SYSTEM_POPPLER)
endif (OMR)
set (BUILD_MU3 OFF)
if (BUILD_UI_MU4)
if (BUILD_UI_MU4_WITH_MU3)
@ -899,17 +881,6 @@ if (BUILD_MU3)
add_subdirectory(thirdparty/portmidi)
endif (USE_PORTMIDI AND (MINGW OR APPLE OR MSVC))
if (AVSOMR)
add_subdirectory(avsomr)
endif (AVSOMR)
if (OMR)
add_subdirectory(omr)
if (NOT USE_SYSTEM_POPPLER)
add_subdirectory(thirdparty/poppler)
endif (NOT USE_SYSTEM_POPPLER)
endif (OMR)
if (OSC)
add_subdirectory(thirdparty/ofqf)
endif (OSC)

View file

@ -1,96 +0,0 @@
#=============================================================================
# MuseScore
# Music Composition & Notation
#
# Copyright (C) 2020 MuseScore BVBA and others
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#=============================================================================
include (${PROJECT_SOURCE_DIR}/build/gch.cmake)
include_directories(
${PROJECT_SOURCE_DIR}
${PROJECT_SOURCE_DIR}/framework/global
)
if (NOT MSVC)
set(_all_h_file "${PROJECT_BINARY_DIR}/all.h")
else (NOT MSVC)
set(_all_h_file "${PROJECT_SOURCE_DIR}/all.h")
endif (NOT MSVC)
add_library (
avsomr STATIC
${_all_h_file}
${PCH}
avsimport.cpp
avslog.h
ret.cpp
ret.h
avsomr.cpp
avsomr.h
avsomrreader.cpp
avsomrreader.h
msmrfile.cpp
msmrfile.h
msmrwriter.cpp
msmrwriter.h
avsomrdrawer.cpp
avsomrdrawer.h
iavsomrrecognizer.h
avsomrnetrecognizer.cpp
avsomrnetrecognizer.h
avsomrlocal.cpp
avsomrlocal.h
avsomrlocalrecognizer.cpp
avsomrlocalrecognizer.h
avsomrlocalinstaller.cpp
avsomrlocalinstaller.h
avsomrsetup.cpp
avsomrsetup.h
ui/recognitionproccessdialog.cpp
ui/recognitionproccessdialog.h
ui/taskbarprogress.cpp
ui/taskbarprogress.h
ui/infopopup.cpp
ui/infopopup.h
ui/setupavsomrview.cpp
ui/setupavsomrview.h
)
if (NOT MSVC)
set_target_properties (
avsomr
PROPERTIES
COMPILE_FLAGS "${PCH_INCLUDE} -g -Wall -Wextra -Winvalid-pch"
)
else (NOT MSVC)
set_target_properties (
avsomr
PROPERTIES
COMPILE_FLAGS "${PCH_INCLUDE}"
)
endif (NOT MSVC)
xcode_pch(avsomr all)
# Use MSVC pre-compiled headers
vstudio_pch( avsomr )
# MSVC does not depend on mops1 & mops2 for PCH
if (NOT MSVC)
ADD_DEPENDENCIES(avsomr mops1)
ADD_DEPENDENCIES(avsomr mops2)
endif (NOT MSVC)

View file

@ -1,191 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include <memory>
#include <QFileInfo>
#include <QByteArray>
#include <QIODevice>
#include "libmscore/score.h"
#include "libmscore/text.h"
#include "avslog.h"
#include "msmrfile.h"
#include "avsomr.h"
#include "avsomrreader.h"
#include "avsomrnetrecognizer.h"
#include "avsomrlocalrecognizer.h"
#include "avsomrlocal.h"
#include "ui/recognitionproccessdialog.h"
#include "ui/infopopup.h"
namespace Ms {
extern Score::FileError importMusicXml(MasterScore* score, QIODevice* dev, const QString& name);
//---------------------------------------------------------
// doImportMSMR
// return Score::FileError::FILE_* errors
//---------------------------------------------------------
static Score::FileError doImportMSMR(MasterScore* score,
QIODevice* data,
const QString& filePath,
bool created)
{
IF_ASSERT(score) {
return Score::FileError::FILE_ERROR;
}
IF_ASSERT(data) {
return Score::FileError::FILE_ERROR;
}
QString baseName = QFileInfo(filePath).baseName();
auto msmr = std::make_shared<Avs::MsmrFile>(data->readAll(), baseName);
// import score
QByteArray msczData = msmr->readMscz();
if (!msczData.isEmpty()) {
// read mscz
QBuffer msczBuf(&msczData);
msczBuf.open(QIODevice::ReadOnly);
Score::FileError err = score->loadMsc("score.mscz", &msczBuf, true);
if (err != Score::FileError::FILE_NO_ERROR) {
return err;
}
} else {
// import MusicXml
QByteArray muzicXmlData = msmr->readMuzicXml();
if (muzicXmlData.isEmpty()) {
return Score::FileError::FILE_BAD_FORMAT;
}
QBuffer muzicXmlBuf(&muzicXmlData);
muzicXmlBuf.open(QIODevice::ReadOnly);
Score::FileError err = importMusicXml(score, &muzicXmlBuf, baseName);
if (err != Score::FileError::FILE_NO_ERROR) {
return err;
}
// corrections after import
//! NOTE Audiveris sets the title "[Audiveris detected movement]",
//! I decided it was not convenient for the user,
//! the file base name as title is more convenient.
QString titleText = baseName;
Text* title = score->getText(Tid::TITLE);
if (title) {
title->setPlainText(titleText);
}
score->setMetaTag("movementNumber", "");
score->setMetaTag("movementTitle", "");
score->setMetaTag("source", QFileInfo(filePath).fileName());
score->setMetaTag("workTitle", title ? title->plainText() : titleText);
}
// import omr
QByteArray ormData = msmr->readOmr();
if (ormData.isEmpty()) {
return Score::FileError::FILE_BAD_FORMAT;
}
QBuffer ormBuf(&ormData);
Avs::AvsOmrReader reader;
std::shared_ptr<Avs::AvsOmr> omr = reader.read(&ormBuf);
if (!omr) {
return Score::FileError::FILE_BAD_FORMAT;
}
omr->setMsmrFile(msmr);
score->setAvsOmr(omr);
// set format
score->setCreated(created);
//! NOTE format of file determined by .ext,
//! therefore setting .msmr for correctly saving
score->fileInfo()->setFile(QFileInfo(filePath).path() + "/" + baseName + ".msmr");
return Score::FileError::FILE_NO_ERROR;
}
//---------------------------------------------------------
// importMSMR
// return Score::FileError::FILE_* errors
//---------------------------------------------------------
Score::FileError importMSMR(MasterScore* score, const QString& filePath)
{
QFile file(filePath);
if (!file.exists()) {
LOGE() << "not exists file: " << filePath;
return Score::FileError::FILE_NOT_FOUND;
}
if (!file.open(QIODevice::ReadOnly)) {
LOGE() << "failed open file: " << filePath;
return Score::FileError::FILE_OPEN_ERROR;
}
return doImportMSMR(score, &file, filePath, false);
}
//---------------------------------------------------------
// loadAndImportMSMR
// return Score::FileError::FILE_* errors
//---------------------------------------------------------
Score::FileError loadAndImportMSMR(MasterScore* score, const QString& filePath)
{
Avs::RecognitionProccessDialog progDialog;
auto onStep = [&progDialog](const Avs::AvsOmrNetRecognizer::Step& step) {
progDialog.onStep(step);
};
std::shared_ptr<Avs::IAvsOmrRecognizer> recognizer;
bool useLocal = Avs::AvsOmrLocal::instance()->isUseLocal();
if (useLocal) {
recognizer = std::make_shared<Avs::AvsOmrLocalRecognizer>();
} else {
recognizer = std::make_shared<Avs::AvsOmrNetRecognizer>();
}
LOGI() << "try use avs omr recognizer: " << recognizer->type();
progDialog.setType(recognizer->type());
progDialog.show();
QByteArray data;
bool ok = recognizer->recognize(filePath, &data, onStep);
progDialog.onFinished(ok);
if (!ok) {
//! NOTE A message has already been shown to the user
return Score::FileError::FILE_IGNORE_ERROR;
}
QBuffer buf(&data);
buf.open(QIODevice::ReadOnly);
return doImportMSMR(score, &buf, filePath, true);
}
}

View file

@ -1,42 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef AVS_LOG_H
#define AVS_LOG_H
#include <QDebug>
#define LOGD() qDebug()
#define LOGI() qInfo()
#define LOGW() qWarning()
#define LOGE() qCritical()
#define IF_ASSERT(cond) if (!(cond)) { \
LOGE() << "\"ASSERT FAILED!\":" << #cond << __FILE__ << __LINE__; \
Q_ASSERT(cond); \
} \
if (!(cond)) \
#define IF_FAILED(cond) if (!(cond)) { \
LOGE() << "\"FAILED!\":" << #cond << __FILE__ << __LINE__; \
} \
if (!(cond)) \
#endif // AVS_LOG_H

View file

@ -1,398 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "avsomr.h"
#include "avslog.h"
namespace {
static int TRASH_GLYPH_SIZE{ 10 };
static int DEFAULT_SYSTEM_GAP{ 200 };
static float SYSTEM_GAP_PERCENT{ 0.55f };
}
using namespace Ms::Avs;
AvsOmr::AvsOmr()
{
}
//---------------------------------------------------------
// resolve - calculates some elements and attributes
//---------------------------------------------------------
void AvsOmr::resolve()
{
auto firstMS = [](Sheet* sh) -> const MStack* {
if (sh->page.systems.empty()) {
return nullptr;
}
for (int si = 0; si < sh->page.systems.count(); ++si) {
if (sh->page.systems.at(si).mstacks.empty()) {
continue;
}
return &sh->page.systems.at(si).mstacks.first();
}
return nullptr;
};
auto lastMS = [](Sheet* sh) -> const MStack* {
if (sh->page.systems.empty()) {
return nullptr;
}
for (int si = (sh->page.systems.count() - 1); si != 0; --si) {
if (sh->page.systems.at(si).mstacks.empty()) {
continue;
}
return &sh->page.systems.at(si).mstacks.last();
}
return nullptr;
};
auto staffBarlineBBox = [](const Sheet* sh, const System& sys, const Staff& staff) {
IF_FAILED(!staff.barlines.empty()) {
return QRect();
}
ID barID = staff.barlines.first();
Barline bar = sys.inters.barlines.value(barID);
const Glyph* gly = sh->glyphs.value(bar.glyphID, nullptr);
IF_FAILED(gly) {
return QRect();
}
return gly->bbox;
};
auto isTrashGlyph = [](const AvsOmr::Glyph* g) {
if (g->bbox.width() <= TRASH_GLYPH_SIZE && g->bbox.height() <= TRASH_GLYPH_SIZE) {
return true;
}
return false;
};
Idx midx{ 0 };
for (int shi = 0; shi < _sheets.count(); ++shi) {
Sheet* sh = _sheets[shi];
if (sh->page.systems.empty()) {
continue;
}
for (System& sys : sh->page.systems) {
// meausure idx
for (MStack& ms : sys.mstacks) {
ms.idx = midx;
++midx;
}
// system top and bottom
IF_FAILED(!sys.part.staffs.empty()) {
continue;
}
QRect topBarBBox = staffBarlineBBox(sh, sys, sys.part.staffs.first());
QRect bottomBarBBox = staffBarlineBBox(sh, sys, sys.part.staffs.last());
sys.top = topBarBBox.top();
sys.bottom = bottomBarBBox.bottom() + 40;
}
// meausure ranges
const MStack* fms = firstMS(sh);
const MStack* lms = lastMS(sh);
sh->mbeginIdx = fms ? fms->idx : 0;
sh->mendIdx = lms ? lms->idx : 0;
// glyph used
QList<QRect> usedBBoxs;
int gap = 5;
for (const Glyph* g : sh->glyphs) {
if (GlyphUsed::Used == g->used) {
usedBBoxs.append(g->bbox.adjusted(-gap, -gap, gap, gap));
}
}
auto isUsedContains = [](const QList<QRect>& usedBBoxs, const QRect& bbox) {
for (const QRect& r : usedBBoxs) {
if (r.contains(bbox)) {
return true;
}
}
return false;
};
//! TODO optimization may be needed because complexity O^2
for (Glyph* g : sh->glyphs) {
if (isTrashGlyph(g)) {
g->used = GlyphUsed::Trash;
} else if (GlyphUsed::Free == g->used) {
if (isUsedContains(usedBBoxs, g->bbox)) {
g->used = GlyphUsed::Free_Covered;
}
}
}
}
}
//---------------------------------------------------------
// sheetNumByMeausereIdx
//---------------------------------------------------------
AvsOmr::Num AvsOmr::sheetNumByMeausereIdx(const Idx& meausureIdx) const
{
for (const Sheet* sh : _sheets) {
if (meausureIdx >= sh->mbeginIdx && meausureIdx <= sh->mendIdx) {
return sh->num;
}
}
return 0;
}
//---------------------------------------------------------
// sheet
//---------------------------------------------------------
const AvsOmr::Sheet* AvsOmr::sheet(const Num& sheetNum) const
{
for (const Sheet* sh : _sheets) {
if (sheetNum == sh->num) {
return sh;
}
}
return nullptr;
}
//---------------------------------------------------------
// isGlyphUsed
//---------------------------------------------------------
bool AvsOmr::Sheet::isGlyphUsed(const ID& glypthID) const
{
for (const System& sys : page.systems) {
if (sys.inters.usedglyphs.contains(glypthID)) {
return true;
}
}
return false;
}
//---------------------------------------------------------
// isGlyphFree
//---------------------------------------------------------
bool AvsOmr::Sheet::isGlyphFree(const ID& glypthID) const
{
for (const System& sys : page.systems) {
if (sys.freeglyphs.contains(glypthID)) {
return true;
}
}
return false;
}
//---------------------------------------------------------
// stackByIdx
//---------------------------------------------------------
const AvsOmr::MStack& AvsOmr::System::stackByIdx(Idx idx, Idx* idxInSys) const
{
for (int i = 0; i < mstacks.count(); ++i) {
const MStack& m = mstacks.at(i);
if (m.idx == idx) {
if (idxInSys) {
*idxInSys = i;
}
return m;
}
}
static MStack dummy;
return dummy;
}
//---------------------------------------------------------
// mmetrics
//---------------------------------------------------------
AvsOmr::MMetrics AvsOmr::mmetrics(const Num& sheetNum, const Idx& meausureIdx) const
{
const Sheet* sh = sheet(sheetNum);
IF_ASSERT(sh) {
return MMetrics();
}
MMetrics mm;
int sysCount = sh->page.systems.count();
for (int si = 0; si < sysCount; ++si) {
const System& sys = sh->page.systems.at(si);
Idx idxInSys{ 0 };
const AvsOmr::MStack& m = sys.stackByIdx(meausureIdx, &idxInSys);
if (!m.isValid()) {
continue;
}
// bbox
mm.bbox.setLeft(m.left);
mm.bbox.setRight(m.right);
mm.bbox.setTop(sys.top);
mm.bbox.setBottom(sys.bottom);
// bbox header
if (0 == idxInSys) {
if (!sys.part.staffs.empty()) {
const Staff& topStaff = sys.part.staffs.first();
mm.hbbox.setLeft(topStaff.header.start);
mm.hbbox.setRight(topStaff.header.stop);
mm.hbbox.setTop(mm.bbox.top());
mm.hbbox.setBottom(mm.bbox.bottom());
}
}
// bbox elements
mm.ebbox = mm.bbox;
bool isFirstSys = (0 == si);
bool isLastSys = ((sysCount - 1) == si);
int halfH = mm.bbox.height() / 2;
if (1 == sysCount) {
mm.ebbox.setTop(mm.ebbox.top() - halfH);
mm.ebbox.setBottom(mm.ebbox.bottom() + halfH);
} else {
auto gapToNextSys = [sh](const System& sys, size_t si) {
const System& nextSys = sh->page.systems.at(si + 1);
int gapSys = nextSys.top - sys.bottom;
IF_ASSERT(gapSys > 0) {
gapSys = DEFAULT_SYSTEM_GAP;
}
return gapSys;
};
auto gapToPrevSys = [sh](const System& sys, size_t si) {
const System& prevSys = sh->page.systems.at(si - 1);
int gapSys = sys.top - prevSys.bottom;
IF_ASSERT(gapSys > 0) {
gapSys = DEFAULT_SYSTEM_GAP;
}
return gapSys;
};
if (isFirstSys) {
mm.ebbox.setTop(mm.ebbox.top() - halfH);
int gapSys = gapToNextSys(sys, si);
mm.ebbox.setBottom(mm.ebbox.bottom() + (gapSys * SYSTEM_GAP_PERCENT));
} else if (isLastSys) {
int gapSys = gapToPrevSys(sys, si);
mm.ebbox.setTop(mm.ebbox.top() - (gapSys * SYSTEM_GAP_PERCENT));
mm.ebbox.setBottom(mm.ebbox.bottom() + halfH);
} else {
int gapPrevSys = gapToPrevSys(sys, si);
mm.ebbox.setTop(mm.ebbox.top() - (gapPrevSys * SYSTEM_GAP_PERCENT));
int gapNextSys = gapToNextSys(sys, si);
mm.ebbox.setBottom(mm.ebbox.bottom() + (gapNextSys * SYSTEM_GAP_PERCENT));
}
}
//! RETURN
return mm;
}
return mm;
}
//---------------------------------------------------------
// glyphsByBBox
//---------------------------------------------------------
QList<const AvsOmr::Glyph*> AvsOmr::glyphsByBBox(const Num& sheetNum, const QRect& bbox,
QList<GlyphUsed>& accepted) const
{
const Sheet* sh = sheet(sheetNum);
IF_ASSERT(sh) {
return QList<const AvsOmr::Glyph*>();
}
QList<const Glyph*> list;
for (auto g : sh->glyphs) {
if (!accepted.contains(g->used)) {
continue;
}
if (bbox.contains(g->bbox)) {
list.append(g);
}
}
return list;
}
//---------------------------------------------------------
// config
//---------------------------------------------------------
AvsOmr::Config& AvsOmr::config()
{
return _config;
}
//---------------------------------------------------------
// config const
//---------------------------------------------------------
const AvsOmr::Config& AvsOmr::config() const
{
return _config;
}
//---------------------------------------------------------
// setMsmrFile
//---------------------------------------------------------
void AvsOmr::setMsmrFile(std::shared_ptr<MsmrFile> file)
{
_msmrFile = file;
}
//---------------------------------------------------------
// msmrFile
//---------------------------------------------------------
std::shared_ptr<MsmrFile> AvsOmr::msmrFile() const
{
return _msmrFile;
}
//---------------------------------------------------------
// info
//---------------------------------------------------------
const AvsOmr::Info& AvsOmr::info() const
{
return _info;
}

View file

@ -1,196 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef AVS_AVSOMR_H
#define AVS_AVSOMR_H
#include <memory>
#include <QList>
#include <QHash>
#include <QSet>
#include <QRect>
#include <QImage>
#include <QByteArray>
namespace Ms {
namespace Avs {
class MsmrFile;
class AvsOmr
{
public:
AvsOmr();
using ID = uint32_t;
using Num = uint16_t;
using Idx = uint16_t;
// Model
struct Barline {
ID id{ 0 };
ID glyphID{ 0 };
};
struct Staff {
ID id{ 0 };
QList<ID> barlines;
struct {
int32_t start{ 0 };
int32_t stop{ 0 };
ID clefID{ 0 };
ID keyID{ 0 };
ID timeID{ 0 };
} header;
bool isValid() const { return id > 0; }
};
struct MStack {
ID id{ 0 };
Idx idx{ 0 }; // resolved
int32_t left{ 0 };
int32_t right{ 0 };
bool isValid() const { return right > 0; }
};
struct Part {
QList<Staff> staffs;
};
struct Inters {
QHash<ID, Barline> barlines;
QSet<ID> usedglyphs;
};
struct System {
QList<MStack> mstacks;
Part part;
Inters inters;
QSet<ID> freeglyphs;
// resolved
int32_t top{ 0 };
int32_t bottom{ 0 };
const MStack& stackByIdx(Idx idx, Idx* idxInSys = nullptr) const;
};
struct Page {
QList<System> systems;
};
enum class GlyphUsed {
Undefined = 0,
Used,
Free,
Free_Covered, // Avs marked as free, but fully covered used
Trash // Detected as trash (too small)
};
struct Glyph {
ID id{ 0 };
QRect bbox;
GlyphUsed used{ GlyphUsed::Undefined };
QImage img;
};
struct Sheet {
Num num{ 0 };
Page page;
Idx mbeginIdx{ 0 };
Idx mendIdx{ 0 };
QHash<ID, Glyph*> glyphs;
bool isGlyphUsed(const ID& glypthID) const;
bool isGlyphFree(const ID& glypthID) const;
};
struct Book {
uint16_t sheets{ 0 };
};
void resolve();
// Configure
struct Config {
bool isHiddenAll() const { return !_isShowRecognized && !_isShowNotRecognized; }
void setIsShowRecognized(bool arg) { _isShowRecognized = arg; }
bool isShowRecognized() const { return _isShowRecognized; }
void setIsShowNotRecognized(bool arg) { _isShowNotRecognized = arg; }
bool isShowNotRecognized() const { return _isShowNotRecognized; }
private:
bool _isShowRecognized{ true };
bool _isShowNotRecognized{ true };
};
Config& config();
const Config& config() const;
// Access
struct MMetrics {
QRect bbox; //! NOTE bbox of measure
QRect ebbox; //! NOTE bbox in which there may be elements belonging to measure
QRect hbbox; //! NOTE bbox of measure header (clef, key, time)
QRect headerBBox() const
{
return hbbox;
}
QRect chordBBox() const
{
QRect c = bbox;
c.setLeft(c.left() + hbbox.width());
return c;
}
};
Num sheetNumByMeausereIdx(const Idx& meausureIdx) const;
MMetrics mmetrics(const Num& sheetNum, const Idx& meausureIdx) const;
QList<const Glyph*> glyphsByBBox(const Num& sheetNum, const QRect& bbox, QList<AvsOmr::GlyphUsed>& accepted) const;
// Data
void setMsmrFile(std::shared_ptr<MsmrFile> file); // keep data for saving
std::shared_ptr<MsmrFile> msmrFile() const;
// Info
struct Info {
QColor usedColor;
uint32_t usedCount{ 0 };
QColor freeColor;
uint32_t freeCount{ 0 };
};
const Info& info() const;
private:
friend class AvsOmrReader;
const Sheet* sheet(const Num& sheetNum) const;
Book _book;
QList<Sheet*> _sheets;
Config _config;
std::shared_ptr<MsmrFile> _msmrFile;
Info _info;
};
} // Avs
} // Ms
#endif // AVS_AVSOMR_H

View file

@ -1,229 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "avsomrdrawer.h"
#include <QPainter>
#include "libmscore/score.h"
#include "libmscore/measure.h"
#include "avslog.h"
using namespace Ms::Avs;
AvsOmrDrawer::AvsOmrDrawer()
{
}
//---------------------------------------------------------
// makeContext
//---------------------------------------------------------
std::shared_ptr<AvsOmrDrawer::Context> AvsOmrDrawer::makeContext(QPainter* p, const Ms::Score* score) const
{
IF_ASSERT(p) {
return nullptr;
}
const Ms::MasterScore* ms = score->masterScore();
IF_ASSERT(ms) {
return nullptr;
}
std::shared_ptr<AvsOmr> omr = ms->avsOmr();
if (!omr) {
return nullptr;
}
std::shared_ptr<Context> ctx = std::make_shared<Context>();
ctx->omr = omr;
ctx->p = p;
//! TODO Think about how to do it better.
Avs::AvsOmr::Idx idx{ 0 };
for (Ms::Measure* m = score->firstMeasure(); m; m = m->nextMeasure()) {
ctx->measureIdxs.insert(m, idx);
++idx;
}
return ctx;
}
//---------------------------------------------------------
// draw
//---------------------------------------------------------
void AvsOmrDrawer::draw(std::shared_ptr<Context> ctx, const QList<const Ms::Measure*>& ml)
{
IF_ASSERT(ctx) {
return;
}
if (ctx->omr->config().isHiddenAll()) {
return;
}
ctx->p->save();
for (const Ms::Measure* m : ml) {
ctx->ormMeasureIdx = ctx->measureIdxs.value(m);
ctx->ormSheetNum = ctx->omr->sheetNumByMeausereIdx(ctx->ormMeasureIdx);
MMetrics mm;
mm.bbox = m->bbox();
auto setMSegment = [](MSegment& ms, const Ms::Segment* s) {
ms.pos = s->pos();
ms.w = s->width();
};
for (Ms::Segment* s = m->first(); s; s = s->next()) {
if (Ms::SegmentType::Clef == s->segmentType() || Ms::SegmentType::HeaderClef == s->segmentType()) {
setMSegment(mm.clef, s);
} else if (Ms::SegmentType::KeySig == s->segmentType()) {
setMSegment(mm.key, s);
} else if (Ms::SegmentType::TimeSig == s->segmentType()) {
setMSegment(mm.time, s);
} else if (Ms::SegmentType::ChordRest == s->segmentType()) {
setMSegment(mm.fchord, s);
break; //! NOTE The first chord and we dont need anything else
}
}
QPointF ppos = m->pagePos();
ctx->p->translate(ppos);
drawMeasure(ctx, mm);
ctx->p->translate(-ppos);
}
ctx->p->restore();
}
//---------------------------------------------------------
// drawMeasure
//---------------------------------------------------------
void AvsOmrDrawer::drawMeasure(std::shared_ptr<Context> ctx, const MMetrics& scoreMM) const
{
AvsOmr::MMetrics omm = ctx->omr->mmetrics(ctx->ormSheetNum, ctx->ormMeasureIdx);
QRectF scoreMH = scoreMM.headerBBox();
QRectF scoreMCH = scoreMM.chordBBox();
QRect ormMH = omm.headerBBox();
ormMH.setRight(ormMH.right() + 30);
QRect ormMCH = omm.chordBBox();
int topGap = omm.ebbox.top() - omm.bbox.top();
int bottomGap = omm.ebbox.bottom() - omm.bbox.bottom();
drawGlyphs(ctx, ormMH, topGap, bottomGap, scoreMH);
ctx->p->translate(scoreMCH.left(), 0);
drawGlyphs(ctx, ormMCH, topGap, bottomGap, scoreMCH);
ctx->p->translate(-scoreMCH.left(), 0);
}
//---------------------------------------------------------
// drawGlyphs
//---------------------------------------------------------
void AvsOmrDrawer::drawGlyphs(std::shared_ptr<Context> ctx,
const QRect omrBB,
int topGap, int bottomGap,
const QRectF scoreBB) const
{
QTransform originTransform = ctx->p->transform();
// Scale
qreal sx = scoreBB.width() / static_cast<qreal>(omrBB.width());
qreal sy = scoreBB.height() / static_cast<qreal>(omrBB.height());
QTransform transform = originTransform;
transform.scale(sx, sy);
ctx->p->setTransform(transform);
QRect abb = omrBB.adjusted(0, topGap, 0, bottomGap);
QList<AvsOmr::GlyphUsed> accepted;
if (ctx->omr->config().isShowRecognized()) {
accepted << AvsOmr::GlyphUsed::Used;
}
if (ctx->omr->config().isShowNotRecognized()) {
accepted << AvsOmr::GlyphUsed::Free;
}
QList<const AvsOmr::Glyph*> glys = ctx->omr->glyphsByBBox(ctx->ormSheetNum, abb, accepted);
for (const auto& g : glys) {
QRect gb = g->bbox.translated(-omrBB.left(), -omrBB.top());
ctx->p->drawImage(gb.topLeft(), g->img);
}
ctx->p->setTransform(originTransform);
}
//---------------------------------------------------------
// nextColor (for debug)
//---------------------------------------------------------
QColor AvsOmrDrawer::nextColor() const
{
static int cf = static_cast<int>(Qt::darkGray);
static int cl = static_cast<int>(Qt::darkYellow);
static int ci = cf;
++ci;
if (ci > cl) {
ci = cf;
}
return QColor(static_cast<Qt::GlobalColor>(ci));
}
//---------------------------------------------------------
// drawBBox (for debug)
//---------------------------------------------------------
void AvsOmrDrawer::drawBBox(QPainter* p, const QRect& r, Qt::GlobalColor colr) const
{
QPen pen;
pen.setColor(QColor(colr));
pen.setWidth(8);
p->setPen(pen);
p->drawRect(r);
}
//---------------------------------------------------------
// drawMSegment (for debug)
//---------------------------------------------------------
void AvsOmrDrawer::drawMSegment(QPainter* p, const MSegment& s, Qt::GlobalColor colr) const
{
if (s.isNull()) {
return;
}
QPen pen;
pen.setColor(QColor(colr));
pen.setWidth(20);
p->setPen(pen);
p->drawLine(s.pos, QPoint(s.pos.x() + s.w, s.pos.y()));
}

View file

@ -1,93 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef AVS_AVSOMRDRAWER_H
#define AVS_AVSOMRDRAWER_H
#include "avsomr.h"
namespace Ms {
class Score;
class Measure;
namespace Avs {
class AvsOmrDrawer
{
public:
AvsOmrDrawer();
struct Context {
QPainter* p{ nullptr };
std::shared_ptr<AvsOmr> omr;
QHash<const Ms::Measure*, AvsOmr::Idx> measureIdxs;
AvsOmr::Num ormSheetNum{ 0 };
AvsOmr::Idx ormMeasureIdx{ 0 };
};
std::shared_ptr<Context> makeContext(QPainter* p, const Ms::Score* score) const;
void draw(std::shared_ptr<Context> ctx, const QList<const Ms::Measure*>& ml);
private:
struct MSegment {
QPointF pos;
qreal w{ 0 };
bool isNull() const { return qFuzzyIsNull(w); }
};
struct MMetrics {
QRectF bbox;
MSegment clef;
MSegment key;
MSegment time;
MSegment fchord;
qreal headerW() const
{
return clef.w + key.w + time.w;
}
QRectF headerBBox() const
{
QRectF h = bbox;
h.setRight(headerW());
return h;
}
QRectF chordBBox() const
{
QRectF c = bbox;
c.setLeft(headerW());
return c;
}
};
void drawMeasure(std::shared_ptr<Context> ctx, const MMetrics& scoreMM) const;
void drawGlyphs(std::shared_ptr<Context> ctx,const QRect omrBB,int topGap, int bottomGap,const QRectF scoreBB) const;
// debug
QColor nextColor() const;
void drawBBox(QPainter* p, const QRect& r, Qt::GlobalColor colr) const;
void drawMSegment(QPainter* p, const MSegment& s, Qt::GlobalColor colr) const;
};
} // Avs
} // Ms
#endif // AVS_AVSOMRDRAWER_H

View file

@ -1,357 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "avsomrlocal.h"
#include <QFileInfo>
#include <QEventLoop>
#include <QProcess>
#include <QtConcurrent>
#include <QFutureWatcher>
#include "mscore/preferences.h"
#include "avslog.h"
#include "avsomrlocalinstaller.h"
namespace {
static const QString AVS_EXT_NAME("avsomr_local");
#ifdef Q_OS_WIN
static const QString SHELL("cmd");
static const QStringList SHELL_ARGS("/c");
static const QString AVS_MAKE_SCRIPT("make_avs_win.bat");
#elif defined(Q_OS_MAC)
static const QString SHELL("sh");
static const QStringList SHELL_ARGS;
static const QString AVS_MAKE_SCRIPT("make_avs_mac.sh");
#else
static const QString SHELL("sh");
static const QStringList SHELL_ARGS;
static const QString AVS_MAKE_SCRIPT("make_avs_lin.sh");
#endif
}
using namespace Ms::Avs;
AvsOmrLocal::AvsOmrLocal()
{
}
AvsOmrLocal::~AvsOmrLocal()
{
delete _installer;
}
//---------------------------------------------------------
// installer
//---------------------------------------------------------
AvsOmrLocalInstaller* AvsOmrLocal::installer() const
{
if (!_installer) {
_installer = new AvsOmrLocalInstaller(avsHomePath());
}
return _installer;
}
//---------------------------------------------------------
// avsHomePath
//---------------------------------------------------------
QString AvsOmrLocal::avsHomePath() const
{
QString path = preferences.getString(PREF_APP_PATHS_MYEXTENSIONS) + "/" + AVS_EXT_NAME;
return path;
}
//---------------------------------------------------------
// makeAvsFilePath
//---------------------------------------------------------
QString AvsOmrLocal::makeAvsFilePath(const QString& buildDir, const QString& baseName) const
{
return buildDir + "/" + baseName + "/" + baseName + ".msmr";
}
//---------------------------------------------------------
// version
//---------------------------------------------------------
QString AvsOmrLocal::version() const
{
QString versionPath = avsHomePath() + "/VERSION";
QFile versionFile(versionPath);
bool ok = versionFile.open(QIODevice::ReadOnly);
if (!ok) {
return QString();
}
QString ver = versionFile.readAll();
return ver.trimmed();
}
//---------------------------------------------------------
// state
//---------------------------------------------------------
const AvsOmrLocal::State& AvsOmrLocal::state() const
{
if (State::Undefined == _state) {
bool ok = execAvs("check", QString(), QString());
_state = ok ? State::Ready : State::NotInstalled;
}
return _state;
}
//---------------------------------------------------------
// stateString
//---------------------------------------------------------
QString AvsOmrLocal::stateString() const
{
switch (state()) {
case State::Undefined: return QStringLiteral("Undefined");
case State::NotInstalled: return QStringLiteral("NotInstalled");
case State::Instaling: return QStringLiteral("Instaling");
case State::Ready: return QStringLiteral("Ready");
case State::Building: return QStringLiteral("Building");
}
Q_UNREACHABLE();
return QString();
}
//---------------------------------------------------------
// setState
//---------------------------------------------------------
Ret AvsOmrLocal::stateToRet(const State& st) const
{
switch (st) {
case State::Undefined: return Ret::UnknownError;
case State::NotInstalled: return Ret::LocalNotInstalled;
case State::Instaling: return Ret::LocalInstaling;
case State::Ready: return Ret::Ok;
case State::Building: return Ret::LocalAlreadyBuilding;
}
Q_UNREACHABLE();
return Ret::Undefined;
}
//---------------------------------------------------------
// setState
//---------------------------------------------------------
void AvsOmrLocal::setState(State st)
{
_state = st;
}
//---------------------------------------------------------
// isUseLocal
//---------------------------------------------------------
bool AvsOmrLocal::isUseLocal() const
{
bool useLocal = preferences.getBool(PREF_IMPORT_AVSOMR_USELOCAL);
return useLocal;
}
//---------------------------------------------------------
// isInstalled
//---------------------------------------------------------
bool AvsOmrLocal::isInstalled() const
{
return state() != State::NotInstalled;
}
//---------------------------------------------------------
// isInstalledAsync
//---------------------------------------------------------
void AvsOmrLocal::isInstalledAsync(const std::function<void(bool)>& callback) const
{
if (_state != State::Undefined) {
callback(_state != State::NotInstalled);
return;
}
QFutureWatcher<bool>* watcher = new QFutureWatcher<bool>();
QObject::connect(watcher, &QFutureWatcher<bool>::finished, [watcher, callback]() {
bool isInstl = watcher->result();
callback(isInstl);
watcher->deleteLater();
});
QFuture<bool> future = QtConcurrent::run([this]() { return isInstalled(); });
watcher->setFuture(future);
}
//---------------------------------------------------------
// checkInstallOrUpdate
//---------------------------------------------------------
Ret AvsOmrLocal::checkInstallOrUpdate(bool isWait)
{
const State& st = state();
if (State::NotInstalled == st) {
installBackground();
} else if (State::Instaling == st) {
// noop, only waiting
} else {
if (isNeedUpdate()) {
installBackground();
}
}
if (isWait) {
waitInstallOrUpdate();
}
if (State::Ready != state()) {
return stateToRet(state());
}
return Ret::Ok;
}
//---------------------------------------------------------
// isNeedUpdate
//---------------------------------------------------------
bool AvsOmrLocal::isNeedUpdate() const
{
const AvsOmrLocalInstaller::ReleaseInfo& info = installer()->loadReleaseInfo();
if (!info.isValid()) {
LOGW() << "failed load release info";
return false;
}
QString localVer = version();
if (localVer.isEmpty()) {
LOGW() << "failed read version";
return true;
}
if (localVer != info.tag) {
LOGI() << "avs need update, installed version: " << localVer << ", latest: " << info.tag;
return true;
}
return false;
}
//---------------------------------------------------------
// installBackground
//---------------------------------------------------------
void AvsOmrLocal::installBackground()
{
setState(State::Instaling);
installer()->installBackground();
}
//---------------------------------------------------------
// waitInstallOrUpdate
//---------------------------------------------------------
void AvsOmrLocal::waitInstallOrUpdate()
{
installer()->waitForFinished();
setState(State::Undefined);
}
//---------------------------------------------------------
// build
//---------------------------------------------------------
Ret AvsOmrLocal::build(const QString& filePath, const QString& buildDir)
{
if (State::Ready != state()) {
LOGE() << "unable start build, state: " << stateString();
return stateToRet(state());
}
setState(State::Building);
Ret ret = execAvs("build", filePath, buildDir);
setState(State::Instaling);
return ret;
}
//---------------------------------------------------------
// execAvs
//---------------------------------------------------------
Ret AvsOmrLocal::execAvs(const QString& cmd, const QString& filePath, const QString& buildDir) const
{
QString home = avsHomePath();
if (home.isEmpty()) {
LOGE() << "not found avs plugin";
return Ret::LocalNotInstalled;
}
QString make_avs = avsHomePath() + "/" + AVS_MAKE_SCRIPT;
if (!QFileInfo(make_avs).exists()) {
LOGE() << "not found make script: " << make_avs;
return Ret::LocalNotInstalled;
}
QStringList arguments;
if (!SHELL_ARGS.isEmpty()) {
arguments << SHELL_ARGS;
}
arguments << make_avs << cmd << filePath << buildDir;
QEventLoop loop;
QProcess proc;
int exitCode = -1;
auto onFinished = [&loop, &exitCode](int code, QProcess::ExitStatus exitStatus) {
LOGI() << "onFinished exitCode: " << code << ", exitStatus: " << exitStatus;
exitCode = code;
loop.quit();
};
QObject::connect(&proc, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
onFinished);
LOGI() << "try start: " << SHELL << arguments;
proc.start(SHELL, arguments);
loop.exec();
LOGD() << QString::fromLatin1(proc.readAll());
if (exitCode != 0) {
return Ret::LocalFailedExec;
}
return Ret::Ok;
}

View file

@ -1,83 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef AVS_AVSOMRLOCAL_H
#define AVS_AVSOMRLOCAL_H
#include <functional>
#include <QString>
#include "ret.h"
namespace Ms {
namespace Avs {
class AvsOmrLocalInstaller;
class AvsOmrLocal
{
public:
static AvsOmrLocal* instance()
{
static AvsOmrLocal l;
return &l;
}
enum class State {
Undefined = 0,
NotInstalled,
Instaling,
Ready,
Building
};
QString version() const;
const State& state() const;
QString stateString() const;
Ret stateToRet(const State& st) const;
bool isUseLocal() const;
bool isInstalled() const;
void isInstalledAsync(const std::function<void(bool)>& callback) const;
Ret checkInstallOrUpdate(bool isWait);
QString avsHomePath() const;
QString makeAvsFilePath(const QString& buildDir, const QString& baseName) const;
Ret build(const QString& filePath, const QString& buildDir);
private:
AvsOmrLocal();
~AvsOmrLocal();
AvsOmrLocalInstaller* installer() const;
bool isNeedUpdate() const;
void installBackground();
void waitInstallOrUpdate();
void setState(State st);
Ret execAvs(const QString& cmd, const QString& filePath, const QString& buildDir) const;
mutable State _state{ State::Undefined };
mutable AvsOmrLocalInstaller* _installer{ nullptr };
};
} // Avs
} // Ms
#endif // AVS_AVSOMRLOCAL_H

View file

@ -1,272 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "avsomrlocalinstaller.h"
#include <QtConcurrent>
#include <QFutureWatcher>
#include <QEventLoop>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QBuffer>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include "thirdparty/qzip/qzipreader_p.h"
#include "avslog.h"
namespace {
static const QString AVS_RELEASE_LATEST_API("https://api.github.com/repos/musescore/omr-local/releases/latest");
#ifdef Q_OS_WIN
static const QString RELEASE_PREFIX("_windows_");
#elif defined(Q_OS_MAC)
static const QString RELEASE_PREFIX("_macos_");
#else
static const QString RELEASE_PREFIX("_linux_");
#endif
}
using namespace Ms::Avs;
AvsOmrLocalInstaller::AvsOmrLocalInstaller(const QString& avsHomePath)
: _avsHomePath(avsHomePath)
{
_loop = new QEventLoop();
}
//---------------------------------------------------------
// installBackground
//---------------------------------------------------------
void AvsOmrLocalInstaller::installBackground()
{
IF_ASSERT(!_watcher) {
LOGE() << "already run installing";
return;
}
const ReleaseInfo& info = loadReleaseInfo();
if (!info.isValid()) {
LOGW() << "failed load release info";
return;
}
_watcher = new QFutureWatcher<bool>();
QObject::connect(_watcher, &QFutureWatcher<bool>::finished, [this]() {
if (_loop->isRunning()) {
_loop->quit();
}
_watcher->deleteLater();
_watcher = nullptr;
});
QFuture<bool> future = QtConcurrent::run(this, &AvsOmrLocalInstaller::doInstallAvs, info.url);
_watcher->setFuture(future);
}
//---------------------------------------------------------
// waitForFinished
//---------------------------------------------------------
void AvsOmrLocalInstaller::waitForFinished()
{
if (!_watcher) {
return;
}
_loop->exec();
}
//---------------------------------------------------------
// doInstallAvs
//---------------------------------------------------------
bool AvsOmrLocalInstaller::doInstallAvs(const QString& url)
{
LOGI() << "try load avs, url: " << url;
QByteArray avsZipPack;
bool ok = getData(&avsZipPack, url, "application/zip");
if (!ok) {
LOGE() << "failed load avs, url: " << url;
return false;
}
LOGI() << "success loaded avs, url: " << url;
ok = unpackAvs(&avsZipPack, _avsHomePath);
if (!ok) {
LOGE() << "failed unpack avs, path: " << _avsHomePath;
return false;
}
LOGI() << "success unpack avs, path: " << _avsHomePath;
return true;
}
//---------------------------------------------------------
// loadReleaseInfo
//---------------------------------------------------------
const AvsOmrLocalInstaller::ReleaseInfo& AvsOmrLocalInstaller::loadReleaseInfo() const
{
if (_info.isValid()) {
return _info;
}
doLoadReleaseInfo(&_info, AVS_RELEASE_LATEST_API);
return _info;
}
//---------------------------------------------------------
// doLoadReleaseInfo
//---------------------------------------------------------
bool AvsOmrLocalInstaller::doLoadReleaseInfo(ReleaseInfo* info, const QString& url) const
{
IF_ASSERT(info) {
return false;
}
QByteArray json_data;
bool ok = getData(&json_data, url, "application/json");
if (!ok) {
LOGE() << "failed get data, url: " << url;
return false;
}
QJsonParseError err;
QJsonDocument doc = QJsonDocument::fromJson(json_data, &err);
if (err.error != QJsonParseError::NoError) {
LOGE() << "failed parse json, err: " << err.errorString() << ", json: " << json_data;
return false;
}
QJsonObject infoObj = doc.object();
info->tag = infoObj.value("tag_name").toString();
QJsonArray assetsArr = infoObj.value("assets").toArray();
for (const auto& av : assetsArr) {
QJsonObject ao = av.toObject();
QString name = ao.value("name").toString();
if (!name.contains(RELEASE_PREFIX)) {
continue;
}
info->url = ao.value("browser_download_url").toString();
break;
}
if (info->tag.isEmpty() || info->url.isEmpty()) {
return false;
}
return true;
}
namespace {
//---------------------------------------------------------
// execReq
//---------------------------------------------------------
static QNetworkReply* execReq(QNetworkAccessManager& net, QNetworkRequest req)
{
QNetworkReply* reply = net.get(req);
QEventLoop loop;
QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
loop.exec();
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (status >= 300 && status < 399) { // redirect
QString newurl = reply->rawHeader("Location");
req.setUrl(newurl);
return execReq(net, req); // recursion
}
return reply;
}
}
//---------------------------------------------------------
// getData
//---------------------------------------------------------
bool AvsOmrLocalInstaller::getData(QByteArray* data, const QString& url, const QByteArray& mime) const
{
QNetworkRequest req;
req.setUrl(QUrl(url));
req.setRawHeader("accept", mime);
QNetworkAccessManager net;
QNetworkReply* reply = execReq(net, req);
if (reply->error() != QNetworkReply::NoError) {
LOGE() << "reply error: " << reply->errorString();
reply->close();
return false;
}
if (data) {
*data = reply->readAll();
}
reply->close();
return true;
}
//---------------------------------------------------------
// unpackAvs
//---------------------------------------------------------
bool AvsOmrLocalInstaller::unpackAvs(QByteArray* avsZipPack, const QString& path)
{
bool ok = cleanDir(path);
if (!ok) {
LOGE() << "failed clean avs dir: " << path;
return false;
}
QBuffer buf(avsZipPack);
MQZipReader zip(&buf);
ok = zip.extractAll(path);
if (!ok) {
LOGE() << "failed unpack avs, path: " << path;
return false;
}
return true;
}
//---------------------------------------------------------
// cleanDir
//---------------------------------------------------------
bool AvsOmrLocalInstaller::cleanDir(const QString& dirPath)
{
return QDir(dirPath).removeRecursively();
}

View file

@ -1,69 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef AVS_AVSOMRLOCALINSTALLER_H
#define AVS_AVSOMRLOCALINSTALLER_H
#include <functional>
#include <QString>
#include <QByteArray>
template<typename T>
class QFutureWatcher;
class QEventLoop;
namespace Ms {
namespace Avs {
class AvsOmrLocalInstaller
{
private:
friend class AvsOmrLocal;
AvsOmrLocalInstaller(const QString& avsHomePath);
struct ReleaseInfo {
QString tag;
QString url;
bool isValid() const { return !tag.isEmpty() && !url.isEmpty(); }
};
const ReleaseInfo& loadReleaseInfo() const;
void installBackground();
void waitForFinished();
private:
bool doLoadReleaseInfo(ReleaseInfo* info, const QString& url) const;
bool doInstallAvs(const QString& url);
bool getData(QByteArray* data, const QString& url, const QByteArray& mime) const;
bool unpackAvs(QByteArray* avsZipPack, const QString& path);
bool cleanDir(const QString& dirPath);
QString _avsHomePath;
mutable ReleaseInfo _info;
QFutureWatcher<bool>* _watcher{ nullptr };
QEventLoop* _loop{ nullptr };
};
} // Avs
} // Ms
#endif // AVS_AVSOMRLOCALINSTALLER_H

View file

@ -1,174 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "avsomrlocalrecognizer.h"
#include <QCoreApplication>
#include <QStandardPaths>
#include <QProcess>
#include <QEventLoop>
#include <QFileInfo>
#include <QFile>
#include <QDir>
#include "avslog.h"
#include "avsomrlocal.h"
using namespace Ms::Avs;
AvsOmrLocalRecognizer::AvsOmrLocalRecognizer()
{
}
AvsOmrLocalRecognizer::~AvsOmrLocalRecognizer()
{
}
//---------------------------------------------------------
// type
//---------------------------------------------------------
QString AvsOmrLocalRecognizer::type() const
{
return "local";
}
//---------------------------------------------------------
// avsOmrLocal
//---------------------------------------------------------
AvsOmrLocal* AvsOmrLocalRecognizer::avsOmrLocal() const
{
return AvsOmrLocal::instance();
}
//---------------------------------------------------------
// makeBuildPath
//---------------------------------------------------------
QString AvsOmrLocalRecognizer::makeBuildPath() const
{
QString tempPath = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
QString path = tempPath
+ "/" + QCoreApplication::applicationName()
+ "/avsomr/build";
return path;
}
//---------------------------------------------------------
// isAvailable
//---------------------------------------------------------
bool AvsOmrLocalRecognizer::isAvailable() const
{
return avsOmrLocal()->isInstalled();
}
//---------------------------------------------------------
// recognize
//---------------------------------------------------------
bool AvsOmrLocalRecognizer::recognize(const QString& filePath, QByteArray* avsFileData, const OnStep& onStep)
{
auto step = [&onStep](Step::Type t, uint perc, uint16_t percMax, Ret ret = Ret::Ok) {
if (!ret) {
LOGE() << "failed step: " << t << ", ret: " << ret.formatedText();
} else {
LOGI() << "success step: " << t << ", ret: " << ret.formatedText();
}
if (onStep) {
onStep(Step(t, perc, percMax, ret));
}
};
step(Step::PrepareStart, 1, 10);
Ret ret = avsOmrLocal()->checkInstallOrUpdate(true);
const QString buildDir = makeBuildPath();
if (ret) {
ret = cleanDir(buildDir);
}
step(Step::PrepareFinish, 10, 10, ret);
if (!ret) {
return false;
}
step(Step::ProcessingStart, 11, 90);
ret = avsOmrLocal()->build(filePath, buildDir);
step(Step::ProcessingFinish, 90, 90, ret);
if (!ret) {
return false;
}
step(Step::LoadStart, 91, 100);
QString avsPath = avsOmrLocal()->makeAvsFilePath(buildDir, QFileInfo(filePath).baseName());
ret = readFile(avsFileData, avsPath);
if (!ret) {
//! NOTE If we cannot read the resulting file,
//! then this means failed to execute
ret = Ret::LocalFailedExec;
}
step(Step::LoadFinish, 100, 100, ret);
if (!ret) {
return false;
}
cleanDir(buildDir);
return true;
}
//---------------------------------------------------------
// cleanDir
//---------------------------------------------------------
Ret AvsOmrLocalRecognizer::cleanDir(const QString& dirPath)
{
return QDir(dirPath).removeRecursively() ? Ret::Ok : Ret::FailedClearDir;
}
//---------------------------------------------------------
// readFile
//---------------------------------------------------------
Ret AvsOmrLocalRecognizer::readFile(QByteArray* avsData, const QString& avsPath)
{
IF_ASSERT(avsData) {
return Ret::FailedReadFile;
}
QFile avsFile(avsPath);
if (!avsFile.exists()) {
LOGE() << "not found avs file: " << avsPath;
return Ret::FailedReadFile;
}
if (!avsFile.open(QIODevice::ReadOnly)) {
LOGE() << "failed open avs file: " << avsPath;
return Ret::FailedReadFile;
}
*avsData = avsFile.readAll();
return Ret::Ok;
}

View file

@ -1,49 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef AVS_AVSOMRLOCALRECOGNIZER_H
#define AVS_AVSOMRLOCALRECOGNIZER_H
#include "iavsomrrecognizer.h"
namespace Ms {
namespace Avs {
class AvsOmrLocal;
class AvsOmrLocalRecognizer : public IAvsOmrRecognizer
{
public:
AvsOmrLocalRecognizer();
~AvsOmrLocalRecognizer() override;
QString type() const override;
bool isAvailable() const override;
bool recognize(const QString& filePath, QByteArray* avsFileData, const OnStep& onStep) override;
private:
AvsOmrLocal* avsOmrLocal() const;
QString makeBuildPath() const;
Ret cleanDir(const QString& dirPath);
Ret readFile(QByteArray* avsData, const QString& avsPath);
};
} // Avs
} // Ms
#endif // AVS_AVSOMRLOCALRECOGNIZER_H

View file

@ -1,297 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "avsomrnetrecognizer.h"
#include <QFile>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QHttpPart>
#include <QEventLoop>
#include <QTimer>
#include <QJsonDocument>
#include <QJsonParseError>
#include "avslog.h"
namespace {
static const QString HOST_API_OMR("https://musescore.com/api/omr");
static const int STATUS_OK{ 200 };
static const int STATUS_NOT_FOUND{ 404 };
static const int STATUS_PROCESSING{ 411 };
static const int STATUS_NOT_SUPPORTED{ 422 };
static const int CHECK_COUNT{ 1000 };
static const int CHECK_INTERVAL_MS{ 300 };
}
using namespace Ms::Avs;
AvsOmrNetRecognizer::AvsOmrNetRecognizer()
{
_net = new QNetworkAccessManager();
}
AvsOmrNetRecognizer::~AvsOmrNetRecognizer()
{
delete _net;
}
//---------------------------------------------------------
// type
//---------------------------------------------------------
QString AvsOmrNetRecognizer::type() const
{
return "cloud";
}
//---------------------------------------------------------
// isAvailable
//---------------------------------------------------------
bool AvsOmrNetRecognizer::isAvailable() const
{
//! TODO add allow check
return true;
}
//---------------------------------------------------------
// recognize
//---------------------------------------------------------
bool AvsOmrNetRecognizer::recognize(const QString& filePath, QByteArray* avsFileData, const OnStep& onStep)
{
QString getUrl;
LOGI() << "begin send file: " << filePath;
auto step = [&onStep](Step::Type t, uint16_t perc, uint16_t percMax, Ret ret = Ret::Ok) {
if (!ret) {
LOGE() << "failed step: " << t << ", err: " << ret.formatedText();
} else {
LOGI() << "success step: " << t << ", err: " << ret.formatedText();
}
if (onStep) {
onStep(Step(t, perc, percMax, ret));
}
};
step(Step::PrepareStart, 1, 10);
Ret ret = send(filePath, &getUrl);
step(Step::PrepareFinish, 10, 10, ret);
if (!ret) {
return false;
}
step(Step::ProcessingStart, 11, 90);
QString fileUrl;
ret = check(getUrl, &fileUrl);
step(Step::ProcessingFinish, 90, 90, ret);
if (!ret) {
return false;
}
step(Step::LoadStart, 91, 100);
ret = load(fileUrl, avsFileData);
step(Step::LoadFinish, 100, 100, ret);
if (!ret) {
return false;
}
return true;
}
//---------------------------------------------------------
// send
//---------------------------------------------------------
Ret AvsOmrNetRecognizer::netRetToRet(const NetRet& nr) const
{
if (nr.httpStatus < 100) {
return Ret::NetworkError;
}
if (nr.httpStatus >= 200 && nr.httpStatus < 300) {
return Ret::Ok;
} else if (nr.httpStatus == STATUS_NOT_SUPPORTED) {
return Ret::FileNotSupported;
}
return Ret::ServerError;
}
//---------------------------------------------------------
// send
//---------------------------------------------------------
Ret AvsOmrNetRecognizer::send(const QString& filePath, QString* getUrl)
{
QFile* file = new QFile(filePath);
if (!file->open(QIODevice::ReadOnly)) {
LOGE() << "failed open file: " << filePath;
delete file;
return Ret::FailedReadFile;
}
//request
QHttpMultiPart* multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QHttpPart part;
part.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/octet-stream"));
part.setHeader(QNetworkRequest::ContentDispositionHeader,
QString("form-data; name=\"file\"; filename=\"%1\"").arg(QFileInfo(filePath).fileName()));
part.setBodyDevice(file);
file->setParent(multiPart); // we cannot delete the file now, so delete it with the multiPart
multiPart->append(part);
QNetworkRequest req;
req.setUrl(QUrl(HOST_API_OMR));
req.setRawHeader("accept", "application/json");
QNetworkReply* rep = _net->post(req, multiPart);
multiPart->setParent(rep);
QByteArray ba;
NetRet netRet = doExecReply(rep, &ba);
LOGI() << "send status: " << netRet.httpStatus << ", data: " << ba;
if (netRet.httpStatus != STATUS_OK) {
LOGE() << "failed send status: " << netRet.httpStatus << ", file: " << filePath;
return netRetToRet(netRet);
}
QVariantMap info = parseInfo(ba);
if (getUrl) {
*getUrl = info.value("url").toString();
}
return Ret::Ok;
}
//---------------------------------------------------------
// doExecReply
//---------------------------------------------------------
AvsOmrNetRecognizer::NetRet AvsOmrNetRecognizer::doExecReply(QNetworkReply* reply, QByteArray* ba)
{
NetRet ret;
QEventLoop loop;
QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
loop.exec();
ret.replyError = static_cast<int>(reply->error());
ret.httpStatus = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (ba) {
*ba = reply->readAll();
}
reply->close();
delete reply;
return ret;
}
//---------------------------------------------------------
// parseInfo
//---------------------------------------------------------
QVariantMap AvsOmrNetRecognizer::parseInfo(const QByteArray& ba) const
{
QVariantMap info;
QJsonParseError err;
QJsonDocument doc = QJsonDocument::fromJson(ba, &err);
if (err.error != QJsonParseError::NoError) {
LOGE() << "failed parse reply, err: " << err.errorString();
return QVariantMap();
}
QJsonObject replyObj = doc.object();
QJsonObject infoObj = replyObj.value("info").toObject();
info["url"] = infoObj.value("url").toString();
return info;
}
//---------------------------------------------------------
// check
//---------------------------------------------------------
Ret AvsOmrNetRecognizer::check(const QString& url, QString* fileUrl)
{
NetRet netRet;
QByteArray data;
for (size_t t = 0; t < CHECK_COUNT; ++t) {
netRet = doCheck(url, &data);
LOGI() << "[" << t << "] status: " << netRet.httpStatus;
if (netRet.httpStatus != STATUS_PROCESSING) {
break;
}
// sleep
QEventLoop loop;
QTimer timer;
timer.setSingleShot(true);
QObject::connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
timer.start(CHECK_INTERVAL_MS);
loop.exec();
}
if (netRet.httpStatus != STATUS_OK) {
return netRetToRet(netRet);
}
QVariantMap info = parseInfo(data);
if (fileUrl) {
*fileUrl = info.value("url").toString();
}
return Ret::Ok;
}
//---------------------------------------------------------
// doCheck
//---------------------------------------------------------
AvsOmrNetRecognizer::NetRet AvsOmrNetRecognizer::doCheck(const QString& url, QByteArray* ba)
{
QNetworkRequest req;
req.setUrl(QUrl(url));
QNetworkReply* reply = _net->get(req);
return doExecReply(reply, ba);
}
//---------------------------------------------------------
// load
//---------------------------------------------------------
Ret AvsOmrNetRecognizer::load(const QString& url, QByteArray* ba)
{
QNetworkRequest req;
req.setUrl(QUrl(url));
QNetworkReply* reply = _net->get(req);
NetRet netRet = doExecReply(reply, ba);
return netRetToRet(netRet);
}

View file

@ -1,68 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef AVS_AVSOMRNETRECOGNIZER_H
#define AVS_AVSOMRNETRECOGNIZER_H
#include <QString>
#include <QByteArray>
#include <QVariantMap>
#include "iavsomrrecognizer.h"
class QNetworkAccessManager;
class QNetworkReply;
namespace Ms {
namespace Avs {
class AvsOmrNetRecognizer : public IAvsOmrRecognizer
{
public:
AvsOmrNetRecognizer();
~AvsOmrNetRecognizer() override;
QString type() const override;
bool isAvailable() const override;
bool recognize(const QString& filePath, QByteArray* avsFileData, const OnStep& onStep) override;
private:
Ret send(const QString& filePath, QString* getUrl);
Ret check(const QString& url, QString* fileUrl);
Ret load(const QString& url, QByteArray* ba);
struct NetRet
{
int httpStatus{ 0 };
int replyError{ 0 };
};
Ret netRetToRet(const NetRet& nr) const;
NetRet doExecReply(QNetworkReply* reply, QByteArray* ba);
NetRet doCheck(const QString& url, QByteArray* ba);
QVariantMap parseInfo(const QByteArray& ba) const;
QNetworkAccessManager* _net{ nullptr };
};
} // Avs
} // Ms
#endif // AVS_AVSOMRNETRECOGNIZER_H

View file

@ -1,534 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "avsomrreader.h"
#include <QFile>
#include <QBuffer>
#include <QXmlStreamReader>
#include <QPainter>
#include "thirdparty/qzip/qzipreader_p.h"
#include "mscore/preferences.h"
#include "avslog.h"
using namespace Ms::Avs;
AvsOmrReader::AvsOmrReader()
{
}
//---------------------------------------------------------
// glyphColor
//---------------------------------------------------------
QColor AvsOmrReader::glyphColor(AvsOmr::GlyphUsed used) const
{
if (_glyphColors.isEmpty()) {
_glyphColors[AvsOmr::GlyphUsed::Used] = preferences.getColor(PREF_UI_AVSOMR_RECOGNITION_COLOR);
_glyphColors[AvsOmr::GlyphUsed::Free] = preferences.getColor(PREF_UI_AVSOMR_NOT_RECOGNITION_COLOR);
_glyphColors[AvsOmr::GlyphUsed::Free_Covered] = preferences.getColor(PREF_UI_AVSOMR_NOT_RECOGNITION_COLOR);
}
return _glyphColors.value(used);
}
//---------------------------------------------------------
// read
//---------------------------------------------------------
std::shared_ptr<AvsOmr> AvsOmrReader::read(const QString& ormFilePath) const
{
QFile zipFile(ormFilePath);
if (!zipFile.exists()) {
LOGE() << "not exists orm file: " << zipFile.fileName();
return nullptr;
}
if (!zipFile.open(QIODevice::ReadOnly)) {
LOGE() << "failed open orm file: " << zipFile.fileName();
return nullptr;
}
return read(&zipFile);
}
//---------------------------------------------------------
// read
//---------------------------------------------------------
std::shared_ptr<AvsOmr> AvsOmrReader::read(QIODevice* ormFile) const
{
MQZipReader zip(ormFile);
QByteArray book = zip.fileData("book.xml");
if (book.isEmpty()) {
LOGE() << "not exists book.xml";
return nullptr;
}
QBuffer bookBuf(&book);
bookBuf.open(QIODevice::ReadOnly);
std::shared_ptr<AvsOmr> omr = std::make_shared<AvsOmr>();
bool ok = readBook(omr->_book, &bookBuf);
if (!ok) {
LOGE() << "failed read book.xml";
return nullptr;
}
for (uint16_t n = 1; n <= omr->_book.sheets; ++n) {
QString path = makeSheetPath(n);
QByteArray sheet = zip.fileData(path);
if (sheet.isEmpty()) {
LOGE() << "not exists sheet: " << path;
continue;
}
QBuffer sheetBuf(&sheet);
sheetBuf.open(QIODevice::ReadOnly);
AvsOmr::Sheet* sh = new AvsOmr::Sheet();
ok = readSheet(*sh, &sheetBuf);
if (!ok) {
LOGE() << "failed read sheet: " << path;
continue;
}
omr->_sheets.insert(sh->num, sh);
}
omr->resolve();
AvsOmr::Info& info = omr->_info;
info.usedColor = glyphColor(AvsOmr::GlyphUsed::Used);
info.freeColor = glyphColor(AvsOmr::GlyphUsed::Free);
for (const AvsOmr::Sheet* sh : omr->_sheets) {
for (AvsOmr::Glyph* g : sh->glyphs) {
if (AvsOmr::GlyphUsed::Used == g->used) {
++info.usedCount;
} else if (AvsOmr::GlyphUsed::Free == g->used) {
++info.freeCount;
}
}
}
return omr;
}
//---------------------------------------------------------
// makeSheetPath
//---------------------------------------------------------
QString AvsOmrReader::makeSheetPath(uint16_t n) const
{
QString name = "sheet#" + QString::number(n);
return name + "/" + name + ".xml";
}
//---------------------------------------------------------
// readBook
//---------------------------------------------------------
bool AvsOmrReader::readBook(AvsOmr::Book& b, QIODevice* xmlData) const
{
QXmlStreamReader xml(xmlData);
if (xml.readNextStartElement()) {
if (!(xml.name() == "book")) {
return false;
}
while (xml.readNextStartElement()) {
QStringRef tag = xml.name();
if ("sheet" == tag) {
++b.sheets;
xml.skipCurrentElement();
} else {
xml.skipCurrentElement();
}
}
}
bool ok = !xml.hasError();
if (!ok) {
LOGE() << "failed read xml, err: " << xml.errorString();
}
return ok;
}
//---------------------------------------------------------
// readSheet
//---------------------------------------------------------
bool AvsOmrReader::readSheet(AvsOmr::Sheet& sh, QIODevice* xmlData) const
{
QXmlStreamReader xml(xmlData);
if (xml.readNextStartElement()) {
if (xml.name() == "sheet") {
sh.num = xml.attributes().value("number").toInt();
while (xml.readNextStartElement()) {
QStringRef tag = xml.name();
if (tag == "page") {
readPage(sh.page, xml);
} else if (tag == "glyph-index") {
readGlyphs(sh, xml);
} else {
xml.skipCurrentElement();
}
}
}
}
bool ok = !xml.hasError();
if (!ok) {
LOGE() << "failed read xml, err: " << xml.errorString();
}
return ok;
}
//---------------------------------------------------------
// readPage
//---------------------------------------------------------
void AvsOmrReader::readPage(AvsOmr::Page& p, QXmlStreamReader& xml) const
{
while (xml.readNextStartElement()) {
if (xml.name() == "system") {
AvsOmr::System sys;
readSystem(sys, xml);
p.systems.append(sys);
} else {
xml.skipCurrentElement();
}
}
}
//---------------------------------------------------------
// readSystem
//---------------------------------------------------------
void AvsOmrReader::readSystem(AvsOmr::System& sys, QXmlStreamReader& xml) const
{
while (xml.readNextStartElement()) {
auto tag = xml.name();
if (tag == "stack") {
AvsOmr::MStack st;
readStack(st, xml);
sys.mstacks.append(st);
} else if (tag == "part") {
readPart(sys.part, xml);
} else if (tag == "free-glyphs") {
QString str = xml.readElementText();
sys.freeglyphs = toIDSet(str);
} else if (tag == "sig") {
while (xml.readNextStartElement()) {
if (xml.name() == "inters") {
readInters(sys.inters, xml);
} else {
xml.skipCurrentElement();
}
}
} else {
xml.skipCurrentElement();
}
}
}
//---------------------------------------------------------
// readStack
//---------------------------------------------------------
void AvsOmrReader::readStack(AvsOmr::MStack& st, QXmlStreamReader& xml) const
{
auto attrs = xml.attributes();
st.id = attrs.value("id").toInt();
st.left = attrs.value("left").toInt();
st.right = attrs.value("right").toInt();
xml.skipCurrentElement();
}
//---------------------------------------------------------
// readPart
//---------------------------------------------------------
void AvsOmrReader::readPart(AvsOmr::Part& pt, QXmlStreamReader& xml) const
{
while (xml.readNextStartElement()) {
auto tag = xml.name();
if (tag == "staff") {
AvsOmr::Staff sf;
readStaff(sf, xml);
pt.staffs.append(sf);
} else {
xml.skipCurrentElement();
}
}
}
//---------------------------------------------------------
// readStaff
//---------------------------------------------------------
void AvsOmrReader::readStaff(AvsOmr::Staff& sf, QXmlStreamReader& xml) const
{
auto attrs = xml.attributes();
sf.id = attrs.value("id").toInt();
while (xml.readNextStartElement()) {
auto tag = xml.name();
if (tag == "header") {
sf.header.start = xml.attributes().value("start").toInt();
sf.header.stop = xml.attributes().value("stop").toInt();
while (xml.readNextStartElement()) {
if (xml.name() == "clef") {
sf.header.clefID = xml.readElementText().toInt();
} else if (xml.name() == "key") {
sf.header.keyID = xml.readElementText().toInt();
} else if (xml.name() == "time") {
sf.header.timeID = xml.readElementText().toInt();
} else {
xml.skipCurrentElement();
}
}
} else if (tag == "barlines") {
QString str = xml.readElementText();
sf.barlines = toIDList(str);
} else {
xml.skipCurrentElement();
}
}
}
//---------------------------------------------------------
// readInters
//---------------------------------------------------------
void AvsOmrReader::readInters(AvsOmr::Inters& its, QXmlStreamReader& xml) const
{
while (xml.readNextStartElement()) {
auto tag = xml.name();
if ("barline" == tag) {
AvsOmr::Barline bl;
readBarline(bl, xml);
its.barlines.insert(bl.id, bl);
} else if ("brace" == tag) {
readInterGlyphID(its.usedglyphs, xml);
} else if ("clef" == tag) {
readInterGlyphID(its.usedglyphs, xml);
} else if ("time-whole" == tag) {
readInterGlyphID(its.usedglyphs, xml);
} else if ("beam" == tag) {
readInterGlyphID(its.usedglyphs, xml);
} else if ("ledger" == tag) {
readInterGlyphID(its.usedglyphs, xml);
} else if ("head" == tag) {
readInterGlyphID(its.usedglyphs, xml);
} else if ("stem" == tag) {
readInterGlyphID(its.usedglyphs, xml);
} else if ("dynamics" == tag) {
readInterGlyphID(its.usedglyphs, xml);
} else if ("alter" == tag) {
readInterGlyphID(its.usedglyphs, xml);
} else {
xml.skipCurrentElement();
}
}
}
//---------------------------------------------------------
// readBarline
//---------------------------------------------------------
void AvsOmrReader::readBarline(AvsOmr::Barline& bl, QXmlStreamReader& xml) const
{
auto attrs = xml.attributes();
bl.id = attrs.value("id").toInt();
bl.glyphID = attrs.value("glyph").toInt();
xml.skipCurrentElement();
}
//---------------------------------------------------------
// readInterGlyphID
//---------------------------------------------------------
void AvsOmrReader::readInterGlyphID(QSet<AvsOmr::ID>& gls, QXmlStreamReader& xml) const
{
auto attrs = xml.attributes();
AvsOmr::ID glyphID = attrs.value("glyph").toInt();
gls.insert(glyphID);
xml.skipCurrentElement();
}
//---------------------------------------------------------
// toIDList
//---------------------------------------------------------
QList<AvsOmr::ID> AvsOmrReader::toIDList(const QString& str) const
{
if (str.isEmpty()) {
return QList<AvsOmr::ID>();
}
QList<AvsOmr::ID> ids;
QStringList strList = str.split(' ');
for (const QString& s : strList) {
ids.append(s.toInt());
}
return ids;
}
//---------------------------------------------------------
// toIDSet
//---------------------------------------------------------
QSet<AvsOmr::ID> AvsOmrReader::toIDSet(const QString& str) const
{
if (str.isEmpty()) {
return QSet<AvsOmr::ID>();
}
QSet<AvsOmr::ID> ids;
QStringList strList = str.split(' ');
for (const QString& s : strList) {
ids.insert(s.toInt());
}
return ids;
}
//---------------------------------------------------------
// readGlyphs
//---------------------------------------------------------
void AvsOmrReader::readGlyphs(AvsOmr::Sheet& sh, QXmlStreamReader& xml) const
{
while (xml.readNextStartElement()) {
if (xml.name() == "glyph") {
auto attrs = xml.attributes();
AvsOmr::Glyph* g = new AvsOmr::Glyph();
g->bbox.setLeft(attrs.value("left").toInt());
g->bbox.setTop(attrs.value("top").toInt());
g->id = attrs.value("id").toInt();
if (sh.isGlyphUsed(g->id)) {
g->used = AvsOmr::GlyphUsed::Used;
} else if (sh.isGlyphFree(g->id)) {
g->used = AvsOmr::GlyphUsed::Free;
}
while (xml.readNextStartElement()) {
if (xml.name() == "run-table") {
readImage(g->img, xml, glyphColor(g->used));
} else {
xml.skipCurrentElement();
}
}
g->bbox.setRight(g->bbox.left() + g->img.width());
g->bbox.setBottom(g->bbox.top() + g->img.height());
sh.glyphs.insert(g->id, g);
} else {
xml.skipCurrentElement();
}
}
}
//---------------------------------------------------------
// readImage
//---------------------------------------------------------
void AvsOmrReader::readImage(QImage& img, QXmlStreamReader& xml, const QColor& color) const
{
IF_ASSERT(xml.isStartElement() && xml.name() == "run-table") {
return;
}
auto attrs = xml.attributes();
int width = attrs.value("width").toInt();
int height = attrs.value("height").toInt();
bool isVertical = attrs.value("orientation") == "VERTICAL";
img = QImage(width, height, QImage::Format_ARGB32);
img.fill(Qt::transparent);
QPainter p(&img);
p.setPen(color);
auto drawLine = [&p, isVertical](int i, const QString& line) {
if (line.isEmpty()) {
return;
}
QStringList segs = line.split(' ');
bool isFill{ true };
int j{ 0 };
for (const QString& seg : segs) {
int length = seg.toInt();
if (length > 0 && isFill) {
if (isVertical) {
p.drawLine(i, j, i, j + length);
} else {
p.drawLine(j, i, j + length, i);
}
}
j += length;
isFill = !isFill;
}
};
int i = 0;
while (xml.readNextStartElement()) {
if (xml.name() == "runs") {
QString line = xml.readElementText();
drawLine(i, line);
++i;
} else {
xml.skipCurrentElement();
}
}
}
//---------------------------------------------------------
// readPicture
//---------------------------------------------------------
bool AvsOmrReader::readPicture(QImage& img, QIODevice* xmlData) const
{
QXmlStreamReader xml(xmlData);
while (xml.readNextStartElement()) {
if (xml.name() == "run-table") {
readImage(img, xml, QColor(Qt::darkBlue));
} else {
xml.skipCurrentElement();
}
}
return true;
}

View file

@ -1,71 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef AVS_AVSOMRREADER_H
#define AVS_AVSOMRREADER_H
#include <QString>
#include <QMap>
#include <QList>
#include <QSet>
#include <QColor>
#include "avsomr.h"
class QXmlStreamReader;
namespace Ms {
namespace Avs {
class AvsOmrReader
{
public:
AvsOmrReader();
std::shared_ptr<AvsOmr> read(const QString& ormFilePath) const;
std::shared_ptr<AvsOmr> read(QIODevice* ormFile) const;
private:
QString makeSheetPath(uint16_t n) const;
bool readBook(AvsOmr::Book& b, QIODevice* xmlData) const;
bool readSheet(AvsOmr::Sheet& sh, QIODevice* xmlData) const;
bool readPicture(QImage& img, QIODevice* xmlData) const;
void readPage(AvsOmr::Page& p, QXmlStreamReader& xml) const;
void readSystem(AvsOmr::System& sys, QXmlStreamReader& xml) const;
void readStack(AvsOmr::MStack& st, QXmlStreamReader& xml) const;
void readPart(AvsOmr::Part& pt, QXmlStreamReader& xml) const;
void readStaff(AvsOmr::Staff& sf, QXmlStreamReader& xml) const;
void readInters(AvsOmr::Inters& its, QXmlStreamReader& xml) const;
void readBarline(AvsOmr::Barline& bl, QXmlStreamReader& xml) const;
void readInterGlyphID(QSet<AvsOmr::ID>& gls, QXmlStreamReader& xml) const;
void readGlyphs(AvsOmr::Sheet& sh, QXmlStreamReader& xml) const;
void readImage(QImage& img, QXmlStreamReader& xml, const QColor& color) const;
QList<AvsOmr::ID> toIDList(const QString& str) const;
QSet<AvsOmr::ID> toIDSet(const QString& str) const;
QColor glyphColor(AvsOmr::GlyphUsed used) const;
mutable QMap<AvsOmr::GlyphUsed, QColor> _glyphColors;
};
} // Avs
} // Ms
#endif // AVS_AVSOMRREADER_H

View file

@ -1,70 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "avsomrsetup.h"
#include <QTimer>
#include "mscore/preferences.h"
#include "avslog.h"
#include "avsomrlocal.h"
using namespace Ms::Avs;
//---------------------------------------------------------
// moduleName
//---------------------------------------------------------
std::string AvsOmrSetup::moduleName() const
{
return "avsomr";
}
//---------------------------------------------------------
// onStartApp
//---------------------------------------------------------
void AvsOmrSetup::onStartApp()
{
AvsOmrLocal* avsLocal = AvsOmrLocal::instance();
//! NOTE If enabled use local avs then check the installation or update
//! on application start
QTimer::singleShot(10000, [avsLocal]() {
if (avsLocal->isUseLocal()) {
avsLocal->checkInstallOrUpdate(false);
}
});
//! NOTE If enabled use local avs then immediately start the installation
//! on preference changed
preferences.addOnSetListener([avsLocal](const QString& key, const QVariant& value) {
if (key != PREF_IMPORT_AVSOMR_USELOCAL) {
return;
}
bool useLocalAvsOmr = value.toBool();
if (!useLocalAvsOmr) {
return;
}
avsLocal->checkInstallOrUpdate(false);
});
}

View file

@ -1,37 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef AVS_AVSOMRSETUP_H
#define AVS_AVSOMRSETUP_H
#include "modularity/imodulesetup.h"
namespace Ms {
namespace Avs {
class AvsOmrSetup : public mu::framework::IModuleSetup
{
private:
std::string moduleName() const override;
void onStartApp() override;
};
} // Avs
} // Ms
#endif // AVS_AVSOMRSETUP_H

View file

@ -1,17 +0,0 @@
First testing phase
===================
examples:
* allegretto.png - [OK]
* BachInvention5.jpg - [WARN] a lot of things out of sync
* batuque.png - [OK]
* carmen.png - [OK]
* chula.png - [OK]
* cucaracha.png - [OK]
* D0392410-1.256.png - [BAD]
* Dichterliebe01.pdf - [BAD]
* inaccessibl_etoile.pdf - [OK]
* SchbAvMaSample.pdf - [BAD]
* zizi.png - [OK]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 197 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

View file

@ -1,68 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef AVS_IAVSOMRRECOGNIZER_H
#define AVS_IAVSOMRRECOGNIZER_H
#include <functional>
#include <QString>
#include <QByteArray>
#include "ret.h"
namespace Ms {
namespace Avs {
class IAvsOmrRecognizer
{
public:
virtual ~IAvsOmrRecognizer() {}
struct Step {
enum Type {
Undefined = 0,
PrepareStart,
PrepareFinish,
ProcessingStart,
ProcessingFinish,
LoadStart,
LoadFinish,
};
Type type{ Undefined };
uint16_t percent{ 0 }; //! NOTE Estimated percent of completion
uint16_t percentMax{ 0 }; //! NOTE Max percent of current step
Ret error{ Ret::Ok };
Step() {}
Step(Type t, uint16_t perc, uint16_t percMax, Ret err)
: type(t), percent(perc), percentMax(percMax), error(err) {}
bool success() const { return error.success(); }
};
using OnStep = std::function<void (const Step& step)>;
virtual QString type() const = 0;
virtual bool isAvailable() const = 0;
virtual bool recognize(const QString& filePath, QByteArray* avsFileData, const OnStep& onStep) = 0;
};
} // Avs
} // Ms
#endif // AVS_IAVSOMRRECOGNIZER_H

View file

@ -1,351 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "msmrfile.h"
#include <QFileInfo>
#include <QBuffer>
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
#include "thirdparty/qzip/qzipreader_p.h"
#include "thirdparty/qzip/qzipwriter_p.h"
#include "avslog.h"
using namespace Ms::Avs;
MsmrFile::MsmrFile(const QByteArray& data, const QString& name)
: _data(data), _name(QFileInfo(name).baseName())
{
}
MsmrFile::~MsmrFile()
{
}
//---------------------------------------------------------
// readMxl
//---------------------------------------------------------
QByteArray MsmrFile::readMxl()
{
QBuffer buf(&_data);
MQZipReader zip(&buf);
MetaInf meta;
meta.read(zip);
QString scoreMxlPath = meta.fileByExt(".mxl");
QByteArray scoreMxlData = zip.fileData(scoreMxlPath);
if (scoreMxlData.isEmpty()) {
LOGE() << "failed read mxl: " << scoreMxlPath;
return QByteArray();
}
return scoreMxlData;
}
//---------------------------------------------------------
// readMuzicXml
//---------------------------------------------------------
QByteArray MsmrFile::readMuzicXml()
{
// compressed
QByteArray scoreMxlData = readMxl();
QBuffer scoreMxlBuf(&scoreMxlData);
scoreMxlBuf.open(QIODevice::ReadOnly);
// xml
MQZipReader mxlZip(&scoreMxlBuf);
MetaInf meta;
meta.read(mxlZip);
QString scoreXmlPath = meta.fileByExt(".xml");
QByteArray scoreXmlData = mxlZip.fileData(scoreXmlPath);
if (scoreXmlData.isEmpty()) {
LOGE() << "failed read xml: " << scoreXmlPath;
return QByteArray();
}
return scoreXmlData;
}
//---------------------------------------------------------
// readOmr
//---------------------------------------------------------
QByteArray MsmrFile::readOmr()
{
QBuffer buf(&_data);
MQZipReader zip(&buf);
MetaInf meta;
meta.read(zip);
QString ormPath = meta.fileByExt(".omr");
QByteArray ormData = zip.fileData(ormPath);
if (ormData.isEmpty()) {
LOGE() << "failed read omr: " << ormPath;
return QByteArray();
}
return ormData;
}
//---------------------------------------------------------
// readMscz
//---------------------------------------------------------
QByteArray MsmrFile::readMscz()
{
QBuffer buf(&_data);
MQZipReader zip(&buf);
MetaInf meta;
meta.read(zip);
QString msczPath = meta.fileByExt(".mscz");
if (msczPath.isEmpty()) { //! NOTE No error, maybe not
LOGI() << "no mscz data";
return QByteArray();
}
QByteArray msczData = zip.fileData(msczPath);
if (msczData.isEmpty()) {
LOGE() << "failed read mscz: " << msczPath;
return QByteArray();
}
return msczData;
}
//---------------------------------------------------------
// writeMscz
//---------------------------------------------------------
bool MsmrFile::writeMscz(const QByteArray& mscz)
{
QByteArray mxl = readMxl();
QByteArray omr = readOmr();
//! NOTE MQZipWriter will overwrite the data,
//! so well clear it explicitly so as not to be misleading
_data.clear();
QBuffer buf(&_data);
MQZipWriter zip(&buf);
//! NOTE all items already compressed
zip.setCompressionPolicy(MQZipWriter::NeverCompress);
MetaInf meta;
auto addFile = [&zip, &meta](const QString& path, const QByteArray& data) {
meta.addFile(path);
zip.addFile(path, data);
};
addFile(_name + ".mxl", mxl);
addFile(_name + ".omr", omr);
addFile(_name + ".mscz", mscz);
meta.write(zip);
if (zip.status() != MQZipWriter::NoError) {
LOGE() << "failed add mscz, zip status: " << zip.status();
return false;
}
return true;
}
//---------------------------------------------------------
// writeTo
//---------------------------------------------------------
bool MsmrFile::writeTo(QIODevice* d)
{
IF_ASSERT(d) {
return false;
}
if (!d->isOpen()) {
d->open(QIODevice::WriteOnly);
}
IF_ASSERT(d->isOpen()) {
return false;
}
d->seek(0);
qint64 size = d->write(_data);
if (size != _data.size()) {
LOGE() << "failed write data";
return false;
}
return true;
}
//---------------------------------------------------------
// addFile
//---------------------------------------------------------
void MsmrFile::MetaInf::addFile(const QString& path)
{
IF_ASSERT(!_containerFiles.contains(path)) {
return;
}
_containerFiles << path;
IF_ASSERT(!_storedFiles.contains(path)) {
return;
}
_storedFiles << path;
}
//---------------------------------------------------------
// fileByExt
//---------------------------------------------------------
QString MsmrFile::MetaInf::fileByExt(const QString& ext) const
{
auto findByExt = [](const QStringList& list, const QString& ext) {
for (const QString& f : list) {
if (f.endsWith(ext)) {
return f;
}
}
return QString();
};
QString file = findByExt(_containerFiles, ext);
//! NOTE If the file is not found in the container,
//! then we will look among the stored files for backward compatibility
//! and eliminating any errors
if (file.isEmpty()) {
file = findByExt(_storedFiles, ext);
} else {
if (!_storedFiles.contains(file)) {
LOGE() << "not found file: " << file;
file = findByExt(_storedFiles, ext);
}
}
return file;
}
//---------------------------------------------------------
// write
//---------------------------------------------------------
void MsmrFile::MetaInf::write(MQZipWriter& zip)
{
QByteArray data;
writeContainer(&data);
zip.addFile("META-INF/container.xml", data);
}
//---------------------------------------------------------
// read
//---------------------------------------------------------
void MsmrFile::MetaInf::read(const MQZipReader& zip)
{
// read container
QByteArray container = zip.fileData("META-INF/container.xml");
if (container.isEmpty()) {
LOGW() << "not found META-INF/container.xml";
} else {
readContainer(container);
}
// read files list
QVector<MQZipReader::FileInfo> fis = zip.fileInfoList();
for (const MQZipReader::FileInfo& fi : fis) {
_storedFiles << fi.filePath;
}
}
//---------------------------------------------------------
// readContainer
//---------------------------------------------------------
void MsmrFile::MetaInf::readContainer(const QByteArray& data)
{
_containerFiles.clear();
QXmlStreamReader xml(data);
while (xml.readNextStartElement()) {
if ("container" != xml.name()) {
xml.skipCurrentElement();
continue;
}
while (xml.readNextStartElement()) {
if ("rootfiles" != xml.name()) {
xml.skipCurrentElement();
continue;
}
while (xml.readNextStartElement()) {
if ("rootfile" != xml.name()) {
xml.skipCurrentElement();
continue;
}
QString path = xml.attributes().value("full-path").toString();
_containerFiles << path;
}
}
}
}
//---------------------------------------------------------
// writeContainer
//---------------------------------------------------------
void MsmrFile::MetaInf::writeContainer(QByteArray* data) const
{
IF_ASSERT(data) {
return;
}
QXmlStreamWriter xml(data);
xml.setAutoFormatting(true);
xml.writeStartDocument();
xml.writeStartElement("container");
xml.writeStartElement("rootfiles");
for (const QString& f : _containerFiles) {
xml.writeStartElement("rootfile");
xml.writeAttribute("full-path", f);
xml.writeEndElement();
}
xml.writeEndElement();
xml.writeEndElement();
xml.writeEndDocument();
}

View file

@ -1,71 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef AVS_MSMRFILE_H
#define AVS_MSMRFILE_H
#include <QIODevice>
#include <QByteArray>
#include <QBuffer>
class MQZipReader;
class MQZipWriter;
namespace Ms {
namespace Avs {
class MsmrFile
{
public:
MsmrFile(const QByteArray& data, const QString& name);
~MsmrFile();
QByteArray readMxl(); // compressed MuzicXml
QByteArray readMuzicXml();
QByteArray readOmr();
QByteArray readMscz();
bool writeMscz(const QByteArray& mscz); // add or replace
bool writeTo(QIODevice* d);
private:
struct MetaInf {
void addFile(const QString& path);
QString fileByExt(const QString& ext) const;
void write(MQZipWriter& zip);
void read(const MQZipReader& zip);
private:
void readContainer(const QByteArray& data);
void writeContainer(QByteArray* data) const;
QStringList _containerFiles;
QStringList _storedFiles;
};
QByteArray _data;
QString _name;
};
} // Avs
} // Ms
#endif // AVS_MSMRFILE_H

View file

@ -1,69 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "msmrwriter.h"
#include <QBuffer>
#include "libmscore/score.h"
#include "avslog.h"
#include "msmrfile.h"
using namespace Ms::Avs;
MsmrWriter::MsmrWriter() {}
//---------------------------------------------------------
// saveMsmrFile
//---------------------------------------------------------
bool MsmrWriter::saveMsmrFile(Ms::MasterScore* score, QIODevice* file, const QFileInfo& info)
{
IF_ASSERT(score->avsOmr()) {
return false;
}
std::shared_ptr<MsmrFile> msmr = score->avsOmr()->msmrFile();
IF_ASSERT(msmr) {
return false;
}
QByteArray mscz;
QBuffer b(&mscz);
bool ok = score->saveCompressedFile(&b, info, false, false);
if (!ok) {
LOGE() << "failed save mscz file";
return false;
}
ok = msmr->writeMscz(mscz);
if (!ok) {
LOGE() << "failed save mscz data";
return false;
}
ok = msmr->writeTo(file);
if (!ok) {
LOGE() << "failed write msmr file";
return false;
}
return true;
}

View file

@ -1,43 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef AVS_MSMRWRITER_H
#define AVS_MSMRWRITER_H
#include <memory>
#include <QIODevice>
#include <QFileInfo>
#include "avsomr.h"
namespace Ms {
class MasterScore;
namespace Avs {
class MsmrWriter
{
public:
MsmrWriter();
bool saveMsmrFile(Ms::MasterScore* score, QIODevice* file, const QFileInfo& info);
};
} // Avs
} // Ms
#endif // AVS_MSMRWRITER_H

View file

@ -1,163 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "ret.h"
#include <QObject>
#include "avslog.h"
using namespace Ms::Avs;
Ret::Ret()
{
}
Ret::Ret(Code c)
: _code(c)
{
}
//---------------------------------------------------------
// valid
//---------------------------------------------------------
bool Ret::valid() const
{
return _code > Undefined;
}
//---------------------------------------------------------
// success
//---------------------------------------------------------
bool Ret::success() const
{
return _code == Ok;
}
//---------------------------------------------------------
// code
//---------------------------------------------------------
Ret::Code Ret::code() const
{
return _code;
}
//---------------------------------------------------------
// formatedText
//---------------------------------------------------------
QString Ret::formatedText() const
{
return formatedText(_code);
}
//---------------------------------------------------------
// supportHint
//---------------------------------------------------------
QString Ret::supportHint() const
{
return supportHint(_code);
}
//---------------------------------------------------------
// text
//---------------------------------------------------------
QString Ret::text() const
{
return text(_code);
}
//---------------------------------------------------------
// formatedText /static/
//---------------------------------------------------------
QString Ret::formatedText(Code c)
{
QString str;
str += "[" + QString::number(static_cast<int>(c)) + "] ";
str += text(c);
return str;
}
//---------------------------------------------------------
// text /static/
//---------------------------------------------------------
QString Ret::text(Code c)
{
switch (c) {
case Undefined: return "Undefined error";
case Ok: return QObject::tr("Ok");
// common
case UnknownError: return QObject::tr("Unknown error");
case FailedReadFile: return QObject::tr("Failed reading file");
case FailedClearDir: return QObject::tr("Failed clearing directory");
case FileNotSupported: return QObject::tr("File not supported");
// network
case NetworkError: return QObject::tr("Network error");
case ServerError: return QObject::tr("Server error");
// local
case LocalNotInstalled: return QObject::tr("Local OMR engine not installed");
case LocalInstaling: return QObject::tr("Local OMR engine installing…");
case LocalFailedExec: return QObject::tr("Failed executing local OMR engine");
case LocalAlreadyBuilding: return QObject::tr("Local OMR engine already building…");
case AvsOmrFirst:
case AvsOmrLast: break;
}
return QString();
}
//---------------------------------------------------------
// supportHint /static/
//---------------------------------------------------------
QString Ret::supportHint(Code c)
{
//! TODO Make information better
static QString PleaseTryAgain = QObject::tr("Please try again");
switch (c) {
case Undefined: return QString();
case Ok: return QString();
// common
case UnknownError: return PleaseTryAgain;
case FailedReadFile: return PleaseTryAgain;
case FailedClearDir: return PleaseTryAgain;
case FileNotSupported: return QObject::tr("Choose another file");
// network
case NetworkError: return QObject::tr("Check your internet connection");
case ServerError: return PleaseTryAgain;
// local
case LocalNotInstalled: return QObject::tr("Try to uncheck and check again to use the local OMR engine");
case LocalInstaling: return PleaseTryAgain;
case LocalFailedExec: return PleaseTryAgain;
case LocalAlreadyBuilding: return PleaseTryAgain;
case AvsOmrFirst:
case AvsOmrLast: break;
}
return QString();
}

View file

@ -1,77 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef AVS_ERR_H
#define AVS_ERR_H
#include <QString>
namespace Ms {
namespace Avs {
class Ret
{
public:
enum Code {
Undefined = -1,
Ok = 0,
AvsOmrFirst = 9000, // reserved codes less than 9000, avs codes will be 90xx
// common
UnknownError,
FailedReadFile,
FailedClearDir,
FileNotSupported,
// network
NetworkError = 9020,
ServerError,
// local
LocalNotInstalled = 9040,
LocalInstaling,
LocalFailedExec,
LocalAlreadyBuilding,
AvsOmrLast
};
Ret();
Ret(Code c);
bool valid() const;
bool success() const;
Code code() const;
inline Ret& operator=(Code c) { _code = c; return *this; }
inline operator bool() const { return success(); }
inline bool operator!() const { return !success(); }
QString text() const;
QString formatedText() const;
QString supportHint() const;
static QString text(Code c);
static QString formatedText(Code c);
static QString supportHint(Code c);
private:
Code _code{ Undefined };
};
} // Avs
} // Ms
#endif // AVS_ERR_H

View file

@ -1,178 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "infopopup.h"
#include <QLabel>
#include <QCheckBox>
#include <QVBoxLayout>
#include <QBitmap>
#include <QMouseEvent>
#include "mscore/scoreview.h"
#include "avslog.h"
namespace {
static int POPUP_MARGIN{ 10 };
}
using namespace Ms;
using namespace Ms::Avs;
InfoPopup::InfoPopup()
{
setFixedSize(220, 80);
setWindowFlags(Qt::Popup);
setFrameStyle(QFrame::Panel | QFrame::Raised);
setAutoFillBackground(true);
setBackgroundRole(QPalette::ToolTipBase);
_recognizedCheck = new QCheckBox(this);
QObject::connect(_recognizedCheck, &QCheckBox::stateChanged, [this](int state) {
emit recognizedCheckedChanged(Qt::Checked == state);
});
_notrecognizedCheck = new QCheckBox(this);
QObject::connect(_notrecognizedCheck, &QCheckBox::stateChanged, [this](int state) {
emit notrecognizedCheckedChanged(Qt::Checked == state);
});
}
//---------------------------------------------------------
// setRecognizedChecked
//---------------------------------------------------------
void InfoPopup::setRecognizedChecked(bool arg)
{
_recognizedCheck->setChecked(arg);
}
//---------------------------------------------------------
// setNotRecognizedChecked
//---------------------------------------------------------
void InfoPopup::setNotRecognizedChecked(bool arg)
{
_notrecognizedCheck->setChecked(arg);
}
//---------------------------------------------------------
// showOnView
//---------------------------------------------------------
void InfoPopup::showOnView(ScoreView* view,
const AvsOmr::Info& info)
{
IF_ASSERT(view) {
return;
}
QVBoxLayout* layout = new QVBoxLayout(this);
auto addRow = [this, layout](QCheckBox* check, const QColor& color, const QString& text) {
QHBoxLayout* row = new QHBoxLayout(this);
row->addWidget(check, 0, Qt::AlignLeft);
QFrame* rec = new QFrame(this);
rec->setFrameStyle(QFrame::Panel);
rec->setFixedSize(40, 20);
rec->setStyleSheet(QString("background-color: %1;").arg(color.name()));
row->addWidget(rec, 0, Qt::AlignLeft);
QLabel* label = new QLabel(this);
label->setText(text);
row->addWidget(label, 1);
layout->addLayout(row);
};
addRow(_recognizedCheck, info.usedColor, QString("- recognized"));
addRow(_notrecognizedCheck, info.freeColor, QString("- not recognized"));
setLayout(layout);
setParent(view);
QObject::connect(view, &ScoreView::viewRectChanged, this, &InfoPopup::onViewChanged);
QObject::connect(view, &ScoreView::sizeChanged, this, &InfoPopup::onViewChanged);
updatePopup(view);
show();
}
//---------------------------------------------------------
// onViewChanged
//---------------------------------------------------------
void InfoPopup::onViewChanged()
{
ScoreView* view = static_cast<ScoreView*>(sender());
updatePopup(view);
}
//---------------------------------------------------------
// updatePopup
//---------------------------------------------------------
void InfoPopup::updatePopup(ScoreView* view)
{
IF_ASSERT(view) {
return;
}
move(view->width() - width() - POPUP_MARGIN, view->height() - height() - POPUP_MARGIN);
//! NOTE When scrolling the view, only a small part is redrawn,
//! therefore the previous position of the info panel remains drawn and
//! the panel is draws in a new position, so the panel is duplicated.
//! To prevent this from happening while the panel is showing,
//! we will redraw the view completely.
view->update();
}
//---------------------------------------------------------
// mouseMoveEvent
//---------------------------------------------------------
void InfoPopup::mouseMoveEvent(QMouseEvent* event)
{
event->accept();
}
//---------------------------------------------------------
// mousePressEvent
//---------------------------------------------------------
void InfoPopup::mousePressEvent(QMouseEvent* event)
{
event->accept();
}
//---------------------------------------------------------
// mouseReleaseEvent
//---------------------------------------------------------
void InfoPopup::mouseReleaseEvent(QMouseEvent* event)
{
event->accept();
}

View file

@ -1,66 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef AVS_INFOPOPUP_H
#define AVS_INFOPOPUP_H
#include <QFrame>
#include "avsomr/avsomr.h"
class QCheckBox;
namespace Ms {
class ScoreView;
namespace Avs {
class InfoPopup : public QFrame
{
Q_OBJECT
public:
InfoPopup();
void setRecognizedChecked(bool arg);
void setNotRecognizedChecked(bool arg);
void showOnView(ScoreView* view, const AvsOmr::Info& info);
signals:
void recognizedCheckedChanged(bool checked);
void notrecognizedCheckedChanged(bool checked);
private slots:
void onViewChanged();
private:
void mouseMoveEvent(QMouseEvent* event) override;
void mousePressEvent(QMouseEvent* event) override;
void mouseReleaseEvent(QMouseEvent* event) override;
void updatePopup(ScoreView* view);
QCheckBox* _recognizedCheck{ nullptr };
QCheckBox* _notrecognizedCheck{ nullptr };
};
} // Avs
} // Ms
#endif // AVS_INFOPOPUP_H

View file

@ -1,167 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "recognitionproccessdialog.h"
#include <QPushButton>
#include "taskbarprogress.h"
using namespace Ms::Avs;
RecognitionProccessDialog::RecognitionProccessDialog()
: QProgressDialog()
{
setWindowFlags(windowFlags() & ~Qt::WindowCloseButtonHint& ~Qt::WindowContextHelpButtonHint);
setFixedSize(300, 140);
setAutoReset(false);
_closeBtn = new QPushButton(QObject::tr("Close"));
setCancelButton(_closeBtn);
_taskbarProgress = new TaskbarProgress(this);
setRange(0, 100);
_taskbarProgress->setRange(0, 100);
setValue(0);
_taskbarProgress->setValue(0);
_updater.setInterval(1000);
_updater.setSingleShot(false);
QObject::connect(&_updater, &QTimer::timeout, [this]() {
update();
});
}
//---------------------------------------------------------
// formatStep
//---------------------------------------------------------
QString RecognitionProccessDialog::formatStep(const IAvsOmrRecognizer::Step& step) const
{
switch (step.type) {
case IAvsOmrRecognizer::Step::Undefined:
return QString();
case IAvsOmrRecognizer::Step::PrepareStart:
return QObject::tr("Preparing…");
case IAvsOmrRecognizer::Step::PrepareFinish:
if (step.success()) {
return QObject::tr("Successfully prepared");
}
return QObject::tr("Failed to prepare")
+ "\n" + step.error.formatedText()
+ "\n" + step.error.supportHint();
case IAvsOmrRecognizer::Step::ProcessingStart:
return QObject::tr("Processing…");
case IAvsOmrRecognizer::Step::ProcessingFinish:
if (step.success()) {
return QObject::tr("Successfully processed");
}
return QObject::tr("Failed to process")
+ "\n" + step.error.formatedText()
+ "\n" + step.error.supportHint();
case IAvsOmrRecognizer::Step::LoadStart:
return QObject::tr("Loading…");
case IAvsOmrRecognizer::Step::LoadFinish:
if (step.success()) {
return QObject::tr("Successfully loaded");
}
return QObject::tr("Failed to load")
+ "\n" + step.error.formatedText()
+ "\n" + step.error.supportHint();
}
return QString();
}
//---------------------------------------------------------
// setType
//---------------------------------------------------------
void RecognitionProccessDialog::setType(const QString& type)
{
_type = type;
}
//---------------------------------------------------------
// show
//---------------------------------------------------------
void RecognitionProccessDialog::show()
{
setWindowTitle(QString("Optical Music Recognition (%1)").arg(_type));
_closeBtn->setEnabled(false);
_updater.start();
_time.start();
QProgressDialog::show();
_taskbarProgress->show();
}
//---------------------------------------------------------
// update
//---------------------------------------------------------
void RecognitionProccessDialog::update()
{
//! NOTE Imitation of continuous progress
if (_lastStep.percent < _lastStep.percentMax) {
_lastStep.percent++;
}
setValue(_lastStep.percent);
_taskbarProgress->setValue(_lastStep.percent);
setLabelText(formatStep(_lastStep));
}
//---------------------------------------------------------
// onStep
//---------------------------------------------------------
void RecognitionProccessDialog::onStep(const IAvsOmrRecognizer::Step& step)
{
_lastStep = step;
update();
}
//---------------------------------------------------------
// onFinished
//---------------------------------------------------------
void RecognitionProccessDialog::onFinished(bool success)
{
_updater.stop();
if (success) {
QProgressDialog::hide();
_taskbarProgress->hide();
} else {
_closeBtn->setEnabled(true);
_taskbarProgress->stop();
QProgressDialog::exec();
_taskbarProgress->hide();
}
}

View file

@ -1,63 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef AVS_RECOGNITIONPROCCESSDIALOG_H
#define AVS_RECOGNITIONPROCCESSDIALOG_H
#include <QProgressDialog>
#include <QString>
#include <QTimer>
#include <QTime>
#include "iavsomrrecognizer.h"
class QPushButton;
namespace Ms {
class TaskbarProgress;
namespace Avs {
class RecognitionProccessDialog : private QProgressDialog
{
public:
RecognitionProccessDialog();
void setType(const QString& type);
void show();
void onStep(const IAvsOmrRecognizer::Step& step);
void onFinished(bool success);
private:
QString formatStep(const IAvsOmrRecognizer::Step& step) const;
void update();
QString _type;
IAvsOmrRecognizer::Step _lastStep;
QTimer _updater;
QElapsedTimer _time;
QPushButton* _closeBtn{ nullptr };
TaskbarProgress* _taskbarProgress{ nullptr };
};
} // Avs
} // Ms
#endif // AVS_RECOGNITIONPROCCESSDIALOG_H

View file

@ -1,70 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "setupavsomrview.h"
#include "mscore/scoreview.h"
#include "avslog.h"
#include "infopopup.h"
using namespace Ms::Avs;
SetupAvsOmrView::SetupAvsOmrView()
{
}
//---------------------------------------------------------
// setupView
//---------------------------------------------------------
void SetupAvsOmrView::setupView(Ms::ScoreView* view, std::shared_ptr<AvsOmr> avsOmr)
{
IF_ASSERT(view) {
return;
}
IF_ASSERT(avsOmr) {
return;
}
AvsOmr::Config& config = avsOmr->config();
InfoPopup* infoPopup = new InfoPopup();
infoPopup->setParent(view);
// recognized
config.setIsShowRecognized(true);
infoPopup->setRecognizedChecked(true);
QObject::connect(infoPopup, &InfoPopup::recognizedCheckedChanged, [view, avsOmr](bool checked) {
avsOmr->config().setIsShowRecognized(checked);
view->update();
});
// notrecognized
config.setIsShowNotRecognized(true);
infoPopup->setNotRecognizedChecked(true);
QObject::connect(infoPopup, &InfoPopup::notrecognizedCheckedChanged, [view, avsOmr](bool checked) {
avsOmr->config().setIsShowNotRecognized(checked);
view->update();
});
// show popup
infoPopup->showOnView(view, avsOmr->info());
}

View file

@ -1,40 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef AVS_SETUPAVSOMRVIEW_H
#define AVS_SETUPAVSOMRVIEW_H
#include <memory>
#include "avsomr/avsomr.h"
namespace Ms {
class ScoreView;
namespace Avs {
class SetupAvsOmrView
{
public:
SetupAvsOmrView();
void setupView(Ms::ScoreView* view, std::shared_ptr<AvsOmr> avsOmr);
};
} // Avs
} // Ms
#endif // AVS_SETUPAVSOMRVIEW_H

View file

@ -1,122 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "taskbarprogress.h"
#ifdef Q_OS_WIN
#include <QWinTaskbarProgress>
#endif
using namespace Ms;
TaskbarProgress::TaskbarProgress(QObject* parent)
: QObject(parent)
{
#ifdef Q_OS_WIN
_winTaskbarProgress = new QWinTaskbarProgress();
#endif
}
TaskbarProgress::~TaskbarProgress()
{
#ifdef Q_OS_WIN
delete _winTaskbarProgress;
#endif
}
//---------------------------------------------------------
// isAvalabled
//---------------------------------------------------------
bool TaskbarProgress::isAvalabled() const
{
#ifdef Q_OS_WIN
return true;
#else
return false;
#endif
}
//---------------------------------------------------------
// show
//---------------------------------------------------------
void TaskbarProgress::show()
{
#ifdef Q_OS_WIN
_winTaskbarProgress->show();
#else
// noop
#endif
}
//---------------------------------------------------------
// hide
//---------------------------------------------------------
void TaskbarProgress::hide()
{
#ifdef Q_OS_WIN
_winTaskbarProgress->hide();
#else
// noop
#endif
}
//---------------------------------------------------------
// stop
//---------------------------------------------------------
void TaskbarProgress::stop()
{
#ifdef Q_OS_WIN
_winTaskbarProgress->stop();
#else
// noop
#endif
}
//---------------------------------------------------------
// setRange
//---------------------------------------------------------
void TaskbarProgress::setRange(int min, int max)
{
#ifdef Q_OS_WIN
_winTaskbarProgress->setRange(min, max);
#else
Q_UNUSED(min);
Q_UNUSED(max);
// noop
#endif
}
//---------------------------------------------------------
// setValue
//---------------------------------------------------------
void TaskbarProgress::setValue(int val)
{
#ifdef Q_OS_WIN
_winTaskbarProgress->setValue(val);
#else
Q_UNUSED(val);
// noop
#endif
}

View file

@ -1,55 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef AVS_TASKBARPROGRESS_H
#define AVS_TASKBARPROGRESS_H
#include <QObject>
#ifdef Q_OS_WIN
class QWinTaskbarProgress;
#endif
namespace Ms {
//! NOTE Probably somewhere there should be a common place for common UI controls
class TaskbarProgress : public QObject
{
Q_OBJECT
public:
TaskbarProgress(QObject* parent);
~TaskbarProgress();
bool isAvalabled() const;
public slots:
void show();
void hide();
void stop();
void setRange(int min, int max);
void setValue(int val);
private:
#ifdef Q_OS_WIN
QWinTaskbarProgress* _winTaskbarProgress{ nullptr };
#endif
};
} // Ms
#endif // AVS_TASKBARPROGRESS_H

View file

@ -52,9 +52,6 @@
#cmakedefine WIN_SPARKLE_ENABLED
#cmakedefine MAC_SPARKLE_ENABLED
#cmakedefine ZERBERUS
#cmakedefine OMR
#cmakedefine OCR
#cmakedefine AVSOMR
#cmakedefine OSC
#cmakedefine OPENGL
#cmakedefine SOUNDFONT3

View file

@ -204,10 +204,5 @@
//#define PREF_PAN_WEIGHT_SMART "smoothPan/weight/smart"
//#define PREF_PAN_WEIGHT_ADVANCED "smoothPan/weight/advanced"
//#define PREF_PAN_SMART_TIMER_DURATION "smoothPan/smart/timer/duration"
#ifdef AVSOMR
#define PREF_IMPORT_AVSOMR_USELOCAL "import/avsomr/useLocalEngine"
#define PREF_UI_AVSOMR_RECOGNITION_COLOR "ui/avsomr/recognition/valid/color"
#define PREF_UI_AVSOMR_NOT_RECOGNITION_COLOR "ui/avsomr/recognition/notValid/color"
#endif
#endif // PREFERENCEKEYS_H

View file

@ -105,9 +105,6 @@ add_library (
)
set (LINK_LIBS )
if (AVSOMR)
set(LINK_LIBS ${LINK_LIBS} avsomr)
endif (AVSOMR)
set(FREETYPE_LIB )
if (USE_SYSTEM_FREETYPE)

View file

@ -67,11 +67,6 @@
#include "measurenumber.h"
#include "marker.h"
#ifdef OMR
#include "omr/omr.h"
#include "omr/omrpage.h"
#endif
namespace Ms {
static void readText206(XmlReader& e, TextBase* t, Element* be);
@ -3712,12 +3707,7 @@ static bool readScore(Score* score, XmlReader& e)
} else if (tag == "siglist") {
score->sigmap()->read(e, score->fileDivision());
} else if (tag == "Omr") {
#ifdef OMR
score->masterScore()->setOmr(new Omr(score));
score->masterScore()->omr()->read(e);
#else
e.skipCurrentElement();
#endif
} else if (tag == "Audio") {
score->setAudio(new Audio);
score->audio()->read(e);

View file

@ -24,11 +24,6 @@
#include "excerpt.h"
#include "spanner.h"
#ifdef OMR
#include "omr/omr.h"
#include "omr/omrpage.h"
#endif
namespace Ms {
//---------------------------------------------------------
// read
@ -43,12 +38,7 @@ bool Score::read(XmlReader& e)
if (tag == "Staff") {
readStaff(e);
} else if (tag == "Omr") {
#ifdef OMR
masterScore()->setOmr(new Omr(this));
masterScore()->omr()->read(e);
#else
e.skipCurrentElement();
#endif
} else if (tag == "Audio") {
_audio = new Audio;
_audio->read(e);

View file

@ -62,9 +62,6 @@
#include "layoutbreak.h"
#include "harmony.h"
#include "mscore.h"
#ifdef OMR
#include "omr/omr.h"
#endif
#include "bracket.h"
#include "audio.h"
#include "instrtemplate.h"
@ -5038,9 +5035,6 @@ void MasterScore::setTempomap(TempoMap* tm)
void MasterScore::removeOmr()
{
_showOmr = false;
#ifdef OMR
delete _omr;
#endif
_omr = 0;
}

View file

@ -38,15 +38,6 @@
#include "preferences.h"
#ifdef OMR
#include "omr/omr.h"
#include "omr/omrpage.h"
#endif
#ifdef AVSOMR
#include "avsomr/msmrwriter.h"
#endif
#include "sig.h"
#include "undo.h"
#include "imageStore.h"
@ -130,11 +121,6 @@ void Score::writeMovement(XmlWriter& xml, bool selectionOnly)
xml.tag("layoutMode", "system");
}
#ifdef OMR
if (masterScore()->omr() && xml.writeOmr()) {
masterScore()->omr()->write(xml);
}
#endif
if (isMaster() && masterScore()->showOmr() && xml.writeOmr()) {
xml.tag("showOmr", masterScore()->showOmr());
}
@ -416,14 +402,7 @@ bool MasterScore::saveFile(bool generateBackup)
bool rv = false;
if ("mscx" == suffix) {
rv = Score::saveFile(&temp, false);
}
#ifdef AVSOMR
else if ("msmr" == suffix) {
Avs::MsmrWriter msmrWriter;
rv = msmrWriter.saveMsmrFile(this, &temp, info);
}
#endif
else {
} else {
QString fileName = info.completeBaseName() + ".mscx";
rv = Score::saveCompressedFile(&temp, fileName, false);
}
@ -660,26 +639,6 @@ bool Score::saveCompressedFile(QIODevice* f, const QString& fn, bool onlySelecti
uz.addFile("Thumbnails/thumbnail.png", ba);
}
#ifdef OMR
//
// save OMR page images
//
if (masterScore()->omr()) {
int n = masterScore()->omr()->numPages();
for (int i = 0; i < n; ++i) {
QString path = QString("OmrPages/page%1.png").arg(i + 1);
QBuffer cbuf1;
OmrPage* page = masterScore()->omr()->page(i);
const QImage& image = page->image();
if (!image.save(&cbuf1, "PNG")) {
MScore::lastError = tr("Save file: cannot save image (%1x%2)").arg(image.width(), image.height());
return false;
}
uz.addFile(path, cbuf1.data());
cbuf1.close();
}
}
#endif
//
// save audio
//
@ -883,25 +842,6 @@ Score::FileError MasterScore::loadCompressedMsc(QIODevice* io, bool ignoreVersio
FileError retval = read1(e, ignoreVersionError);
#ifdef OMR
//
// load OMR page images
//
if (masterScore()->omr()) {
int n = masterScore()->omr()->numPages();
for (int i = 0; i < n; ++i) {
QString path = QString("OmrPages/page%1.png").arg(i + 1);
QByteArray dbuf1 = uz.fileData(path);
OmrPage* page = masterScore()->omr()->page(i);
QImage image;
if (image.loadFromData(dbuf1, "PNG")) {
page->setImage(image);
} else {
qDebug("load image failed");
}
}
}
#endif
//
// read audio
//

View file

@ -57,10 +57,6 @@
#include "framework/telemetry/telemetrysetup.h"
#endif
#ifdef AVSOMR
#include "avsomr/avsomrsetup.h"
#endif
//! NOTE Separately to initialize logger and profiler as early as possible
static mu::framework::GlobalModule globalModule;
@ -99,10 +95,6 @@ ModulesSetup::ModulesSetup()
#ifdef BUILD_VST
<< new mu::vst::VSTModule()
#endif
#endif
#ifdef AVSOMR
<< new Ms::Avs::AvsOmrSetup()
#endif
<< new mu::importexport::ImportExportModule()
<< new mu::inspector::InspectorModule()

View file

@ -34,10 +34,6 @@ else (USE_SYSTEM_FREETYPE)
include_directories(${PROJECT_SOURCE_DIR}/thirdparty/freetype/include)
endif (USE_SYSTEM_FREETYPE)
if (OMR)
set(OMR_SRC ${PROJECT_SOURCE_DIR}/omr/importpdf.cpp)
endif (OMR)
if (MSVC)
set(_all_h_file "${PROJECT_SOURCE_DIR}/all.h")
endif (MSVC)
@ -95,7 +91,6 @@ set (SOURCE_LIB
${PROJECT_SOURCE_DIR}/thirdparty/beatroot/BeatTracker.cpp # Required by importmidi.cpp
${PROJECT_SOURCE_DIR}/thirdparty/beatroot/Induction.cpp # Required by importmidi.cpp
${PROJECT_SOURCE_DIR}/mscore/extension.cpp # required by zerberus tests
${OMR_SRC}
omr
)
@ -257,6 +252,3 @@ install(FILES
)
endif (NOT MSVC)
if (OMR)
subdirs(omr)
endif (OMR)

View file

@ -50,13 +50,6 @@ else (MSVC)
)
endif (MSVC)
if (OMR)
target_link_libraries(${TARGET} omr poppler-qt5)
if (OCR)
target_link_libraries(${TARGET} tesseract_api)
endif (OCR)
endif (OMR)
if (MSVC)
target_link_libraries(
${TARGET}

View file

@ -37,8 +37,6 @@
#define INSTPREFIX "/usr/local"
#define VERSION "2.0.0"
/* #undef OMR */
/* #undef OCR */
#define OSC
/* #undef OPENGL */
#define SOUNDFONT3

View file

@ -78,9 +78,6 @@ const char* tests[] = {
"testoves/bdat/tst_ove_bdat",
"musicxml/io/tst_mxml_io", // FAIL
#endif
#ifdef OMR
"omr/notes/tst_notes",
#endif
};
//---------------------------------------------------------

View file

@ -1,16 +0,0 @@
#=============================================================================
# MuseScore
# Music Composition & Notation
#
# Copyright (C) 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 LICENSE.GPL
#=============================================================================
subdirs(
notes
)

View file

@ -1,16 +0,0 @@
#=============================================================================
# MuseScore
# Music Composition & Notation
#
# Copyright (C) 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 LICENSE.GPL
#=============================================================================
set(TARGET tst_notes)
include(${PROJECT_SOURCE_DIR}/mtest/cmake.inc)

View file

@ -1,329 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<museScore version="1.24">
<Score>
<LayerTag id="0" tag="default"></LayerTag>
<currentLayer>0</currentLayer>
<Division>480</Division>
<Style>
<staffLowerBorder>0</staffLowerBorder>
<akkoladeDistance>6.42857</akkoladeDistance>
<minSystemDistance>6</minSystemDistance>
<maxSystemDistance>6</maxSystemDistance>
<measureSpacing>1</measureSpacing>
<lastSystemFillLimit>0</lastSystemFillLimit>
<page-layout>
<page-height>1683.78</page-height>
<page-width>1190.55</page-width>
<page-margins type="even">
<left-margin>28.3465</left-margin>
<right-margin>85.0394</right-margin>
<top-margin>0</top-margin>
<bottom-margin>0</bottom-margin>
</page-margins>
<page-margins type="odd">
<left-margin>28.3465</left-margin>
<right-margin>85.0394</right-margin>
<top-margin>0</top-margin>
<bottom-margin>0</bottom-margin>
</page-margins>
</page-layout>
<Spatium>1.77823</Spatium>
</Style>
<showInvisible>1</showInvisible>
<showUnprintable>1</showUnprintable>
<showFrames>1</showFrames>
<showMargins>0</showMargins>
<metaTag name="copyright"></metaTag>
<metaTag name="movementNumber"></metaTag>
<metaTag name="movementTitle"></metaTag>
<metaTag name="source"></metaTag>
<metaTag name="workNumber"></metaTag>
<metaTag name="workTitle"></metaTag>
<PageList>
<Page>
</Page>
</PageList>
<Part>
<Staff id="1">
<type>0</type>
<bracket type="1" span="2"/>
<barLineSpan>1</barLineSpan>
</Staff>
<Staff id="2">
<type>0</type>
</Staff>
<trackName></trackName>
<Instrument>
<trackName></trackName>
<Channel name="normal">
<controller tick="0" channel="0" ctrl="0" value="0"/>
<controller tick="0" channel="0" ctrl="32" value="0"/>
<controller tick="0" channel="0" ctrl="7" value="100"/>
<controller tick="0" channel="0" ctrl="10" value="64"/>
<controller tick="0" channel="0" ctrl="93" value="30"/>
<controller tick="0" channel="0" ctrl="91" value="30"/>
</Channel>
</Instrument>
</Part>
<Staff id="1">
<Measure number="1">
<Clef>
<concertClefType>G</concertClefType>
<transposingClefType>G</transposingClefType>
</Clef>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>57</pitch>
<tpc>17</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>59</pitch>
<tpc>19</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>60</pitch>
<tpc>14</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>62</pitch>
<tpc>16</tpc>
</Note>
</Chord>
</Measure>
<Measure number="1">
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>64</pitch>
<tpc>18</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>65</pitch>
<tpc>13</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>67</pitch>
<tpc>15</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>69</pitch>
<tpc>17</tpc>
</Note>
</Chord>
</Measure>
<Measure number="1">
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>71</pitch>
<tpc>19</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>72</pitch>
<tpc>14</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>74</pitch>
<tpc>16</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>76</pitch>
<tpc>18</tpc>
</Note>
</Chord>
</Measure>
<Measure number="1">
<LayoutBreak>
<subtype>line</subtype>
<pause>3</pause>
</LayoutBreak>
<LayoutBreak>
<subtype>page</subtype>
<pause>3</pause>
</LayoutBreak>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>77</pitch>
<tpc>13</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>79</pitch>
<tpc>15</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>81</pitch>
<tpc>17</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>83</pitch>
<tpc>19</tpc>
</Note>
</Chord>
</Measure>
</Staff>
<Staff id="2">
<Measure number="1">
<Clef>
<concertClefType>F</concertClefType>
<transposingClefType>F</transposingClefType>
</Clef>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>36</pitch>
<tpc>14</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>38</pitch>
<tpc>16</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>40</pitch>
<tpc>18</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>41</pitch>
<tpc>13</tpc>
</Note>
</Chord>
</Measure>
<Measure number="1">
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>43</pitch>
<tpc>15</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>45</pitch>
<tpc>17</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>47</pitch>
<tpc>19</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>48</pitch>
<tpc>14</tpc>
</Note>
</Chord>
</Measure>
<Measure number="1">
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>50</pitch>
<tpc>16</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>52</pitch>
<tpc>18</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>53</pitch>
<tpc>13</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>55</pitch>
<tpc>15</tpc>
</Note>
</Chord>
</Measure>
<Measure number="1">
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>57</pitch>
<tpc>17</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>59</pitch>
<tpc>19</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>60</pitch>
<tpc>14</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>62</pitch>
<tpc>16</tpc>
</Note>
</Chord>
</Measure>
</Staff>
</Score>
</museScore>

View file

@ -1,380 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<museScore version="1.24">
<Score>
<LayerTag id="0" tag="default"></LayerTag>
<currentLayer>0</currentLayer>
<Division>480</Division>
<Style>
<page-layout>
<page-height>1683.78</page-height>
<page-width>1190.55</page-width>
<page-margins type="even">
<left-margin>56.6929</left-margin>
<right-margin>56.6929</right-margin>
<top-margin>56.6929</top-margin>
<bottom-margin>113.386</bottom-margin>
</page-margins>
<page-margins type="odd">
<left-margin>56.6929</left-margin>
<right-margin>56.6929</right-margin>
<top-margin>56.6929</top-margin>
<bottom-margin>113.386</bottom-margin>
</page-margins>
</page-layout>
<Spatium>1.76389</Spatium>
</Style>
<showInvisible>1</showInvisible>
<showUnprintable>1</showUnprintable>
<showFrames>1</showFrames>
<showMargins>0</showMargins>
<metaTag name="copyright"></metaTag>
<metaTag name="movementNumber"></metaTag>
<metaTag name="movementTitle"></metaTag>
<metaTag name="source"></metaTag>
<metaTag name="workNumber"></metaTag>
<metaTag name="workTitle">notes1</metaTag>
<PageList>
<Page>
</Page>
</PageList>
<Part>
<Staff id="1">
<type>0</type>
<bracket type="1" span="2"/>
<barLineSpan>1</barLineSpan>
</Staff>
<Staff id="2">
<type>0</type>
<bracket type="-1" span="0"/>
</Staff>
<trackName>Piano</trackName>
<Instrument>
<trackName>Piano</trackName>
<minPitchP>21</minPitchP>
<maxPitchP>108</maxPitchP>
<minPitchA>21</minPitchA>
<maxPitchA>108</maxPitchA>
<Articulation name="">
<velocity>100</velocity>
<gateTime>70</gateTime>
</Articulation>
<Articulation name="staccato">
<velocity>100</velocity>
<gateTime>40</gateTime>
</Articulation>
<Articulation name="tenuto">
<velocity>100</velocity>
<gateTime>100</gateTime>
</Articulation>
<Articulation name="sforzato">
<velocity>120</velocity>
<gateTime>100</gateTime>
</Articulation>
<Channel>
<controller tick="0" channel="0" ctrl="0" value="0"/>
<controller tick="0" channel="0" ctrl="32" value="0"/>
<program tick="0" channel="0" value="0"/>
<controller tick="0" channel="0" ctrl="7" value="100"/>
<controller tick="0" channel="0" ctrl="10" value="64"/>
<controller tick="0" channel="0" ctrl="93" value="30"/>
<controller tick="0" channel="0" ctrl="91" value="30"/>
</Channel>
</Instrument>
</Part>
<Staff id="1">
<VBox>
<height>10</height>
<Text>
<style>Title</style>
<text>notes1</text>
</Text>
</VBox>
<Measure number="1">
<Clef>
<concertClefType>G</concertClefType>
<transposingClefType>G</transposingClefType>
</Clef>
<KeySig>
<accidental>0</accidental>
<showCourtesySig>1</showCourtesySig>
<showNaturals>1</showNaturals>
</KeySig>
<TimeSig>
<sigN>4</sigN>
<sigD>4</sigD>
<showCourtesySig>1</showCourtesySig>
</TimeSig>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>57</pitch>
<tpc>17</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>59</pitch>
<tpc>19</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>60</pitch>
<tpc>14</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>62</pitch>
<tpc>16</tpc>
</Note>
</Chord>
<BarLine>
<subtype>normal</subtype>
<span>2</span>
</BarLine>
</Measure>
<Measure number="2">
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>64</pitch>
<tpc>18</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>65</pitch>
<tpc>13</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>67</pitch>
<tpc>15</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>69</pitch>
<tpc>17</tpc>
</Note>
</Chord>
<BarLine>
<subtype>normal</subtype>
<span>2</span>
</BarLine>
</Measure>
<Measure number="3">
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>71</pitch>
<tpc>19</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>72</pitch>
<tpc>14</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>74</pitch>
<tpc>16</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>76</pitch>
<tpc>18</tpc>
</Note>
</Chord>
<BarLine>
<subtype>normal</subtype>
<span>2</span>
</BarLine>
</Measure>
<Measure number="4">
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>77</pitch>
<tpc>13</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>79</pitch>
<tpc>15</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>81</pitch>
<tpc>17</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>83</pitch>
<tpc>19</tpc>
</Note>
</Chord>
<BarLine>
<subtype>normal</subtype>
<span>2</span>
</BarLine>
</Measure>
</Staff>
<Staff id="2">
<Measure number="1">
<Clef>
<concertClefType>F</concertClefType>
<transposingClefType>F</transposingClefType>
</Clef>
<KeySig>
<accidental>0</accidental>
<showCourtesySig>1</showCourtesySig>
<showNaturals>1</showNaturals>
</KeySig>
<TimeSig>
<sigN>4</sigN>
<sigD>4</sigD>
<showCourtesySig>1</showCourtesySig>
</TimeSig>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>36</pitch>
<tpc>14</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>38</pitch>
<tpc>16</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>40</pitch>
<tpc>18</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>41</pitch>
<tpc>13</tpc>
</Note>
</Chord>
</Measure>
<Measure number="2">
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>43</pitch>
<tpc>15</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>45</pitch>
<tpc>17</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>47</pitch>
<tpc>19</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>48</pitch>
<tpc>14</tpc>
</Note>
</Chord>
</Measure>
<Measure number="3">
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>50</pitch>
<tpc>16</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>52</pitch>
<tpc>18</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>53</pitch>
<tpc>13</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>55</pitch>
<tpc>15</tpc>
</Note>
</Chord>
</Measure>
<Measure number="4">
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>57</pitch>
<tpc>17</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>59</pitch>
<tpc>19</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>60</pitch>
<tpc>14</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>62</pitch>
<tpc>16</tpc>
</Note>
</Chord>
</Measure>
</Staff>
</Score>
</museScore>

View file

@ -1,273 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<museScore version="1.24">
<Score>
<LayerTag id="0" tag="default"></LayerTag>
<currentLayer>0</currentLayer>
<Division>480</Division>
<Style>
<staffLowerBorder>0</staffLowerBorder>
<akkoladeDistance>6.42857</akkoladeDistance>
<minSystemDistance>6</minSystemDistance>
<maxSystemDistance>6</maxSystemDistance>
<measureSpacing>1</measureSpacing>
<lastSystemFillLimit>0</lastSystemFillLimit>
<page-layout>
<page-height>1683.78</page-height>
<page-width>1190.55</page-width>
<page-margins type="even">
<left-margin>28.3465</left-margin>
<right-margin>85.0394</right-margin>
<top-margin>0</top-margin>
<bottom-margin>0</bottom-margin>
</page-margins>
<page-margins type="odd">
<left-margin>28.3465</left-margin>
<right-margin>85.0394</right-margin>
<top-margin>0</top-margin>
<bottom-margin>0</bottom-margin>
</page-margins>
</page-layout>
<Spatium>1.77823</Spatium>
</Style>
<showInvisible>1</showInvisible>
<showUnprintable>1</showUnprintable>
<showFrames>1</showFrames>
<showMargins>0</showMargins>
<metaTag name="copyright"></metaTag>
<metaTag name="movementNumber"></metaTag>
<metaTag name="movementTitle"></metaTag>
<metaTag name="source"></metaTag>
<metaTag name="workNumber"></metaTag>
<metaTag name="workTitle"></metaTag>
<PageList>
<Page>
</Page>
</PageList>
<Part>
<Staff id="1">
<type>0</type>
<bracket type="1" span="2"/>
<barLineSpan>1</barLineSpan>
</Staff>
<Staff id="2">
<type>0</type>
</Staff>
<trackName></trackName>
<Instrument>
<trackName></trackName>
<Channel name="normal">
<controller tick="0" channel="0" ctrl="0" value="0"/>
<controller tick="0" channel="0" ctrl="32" value="0"/>
<controller tick="0" channel="0" ctrl="7" value="100"/>
<controller tick="0" channel="0" ctrl="10" value="64"/>
<controller tick="0" channel="0" ctrl="93" value="30"/>
<controller tick="0" channel="0" ctrl="91" value="30"/>
</Channel>
</Instrument>
</Part>
<Staff id="1">
<Measure number="1">
<Clef>
<concertClefType>G</concertClefType>
<transposingClefType>G</transposingClefType>
</Clef>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>57</pitch>
<tpc>17</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>59</pitch>
<tpc>19</tpc>
</Note>
</Chord>
<Chord>
<durationType>half</durationType>
<Note>
<pitch>60</pitch>
<tpc>14</tpc>
</Note>
</Chord>
</Measure>
<Measure number="1">
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>64</pitch>
<tpc>18</tpc>
</Note>
</Chord>
<Chord>
<durationType>half</durationType>
<Note>
<pitch>65</pitch>
<tpc>13</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>69</pitch>
<tpc>17</tpc>
</Note>
</Chord>
</Measure>
<Measure number="1">
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>71</pitch>
<tpc>19</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>72</pitch>
<tpc>14</tpc>
</Note>
</Chord>
<Chord>
<durationType>half</durationType>
<Note>
<pitch>74</pitch>
<tpc>16</tpc>
</Note>
</Chord>
</Measure>
<Measure number="1">
<LayoutBreak>
<subtype>line</subtype>
<pause>3</pause>
</LayoutBreak>
<LayoutBreak>
<subtype>page</subtype>
<pause>3</pause>
</LayoutBreak>
<Chord>
<durationType>half</durationType>
<Note>
<pitch>77</pitch>
<tpc>13</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>81</pitch>
<tpc>17</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>83</pitch>
<tpc>19</tpc>
</Note>
</Chord>
</Measure>
</Staff>
<Staff id="2">
<Measure number="1">
<Clef>
<concertClefType>F</concertClefType>
<transposingClefType>F</transposingClefType>
</Clef>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>36</pitch>
<tpc>14</tpc>
</Note>
</Chord>
<Chord>
<durationType>half</durationType>
<Note>
<pitch>38</pitch>
<tpc>16</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>41</pitch>
<tpc>13</tpc>
</Note>
</Chord>
</Measure>
<Measure number="1">
<Chord>
<durationType>half</durationType>
<Note>
<pitch>43</pitch>
<tpc>15</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>47</pitch>
<tpc>19</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>48</pitch>
<tpc>14</tpc>
</Note>
</Chord>
</Measure>
<Measure number="1">
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>50</pitch>
<tpc>16</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>52</pitch>
<tpc>18</tpc>
</Note>
</Chord>
<Chord>
<durationType>half</durationType>
<Note>
<pitch>53</pitch>
<tpc>13</tpc>
</Note>
</Chord>
</Measure>
<Measure number="1">
<Chord>
<durationType>half</durationType>
<Note>
<pitch>57</pitch>
<tpc>17</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>60</pitch>
<tpc>14</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>62</pitch>
<tpc>16</tpc>
</Note>
</Chord>
</Measure>
</Staff>
</Score>
</museScore>

View file

@ -1,329 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<museScore version="1.24">
<programVersion>2.0.0</programVersion>
<programRevision>5524:5526M</programRevision>
<Score>
<LayerTag id="0" tag="default"></LayerTag>
<currentLayer>0</currentLayer>
<SyntiSettings>
</SyntiSettings>
<Division>480</Division>
<Style>
<page-layout>
<page-height>1683.78</page-height>
<page-width>1190.55</page-width>
<page-margins type="even">
<left-margin>56.6929</left-margin>
<right-margin>56.6929</right-margin>
<top-margin>56.6929</top-margin>
<bottom-margin>113.386</bottom-margin>
</page-margins>
<page-margins type="odd">
<left-margin>56.6929</left-margin>
<right-margin>56.6929</right-margin>
<top-margin>56.6929</top-margin>
<bottom-margin>113.386</bottom-margin>
</page-margins>
</page-layout>
<Spatium>1.76389</Spatium>
</Style>
<showInvisible>1</showInvisible>
<showUnprintable>1</showUnprintable>
<showFrames>1</showFrames>
<showMargins>0</showMargins>
<metaTag name="copyright"></metaTag>
<metaTag name="movementNumber"></metaTag>
<metaTag name="movementTitle"></metaTag>
<metaTag name="source"></metaTag>
<metaTag name="workNumber"></metaTag>
<metaTag name="workTitle">notes1</metaTag>
<PageList>
<Page>
</Page>
</PageList>
<Part>
<Staff id="1">
<type>0</type>
<bracket type="1" span="2"/>
<barLineSpan>1</barLineSpan>
</Staff>
<Staff id="2">
<type>0</type>
<bracket type="-1" span="0"/>
<barLineSpan>0</barLineSpan>
</Staff>
<trackName>Piano</trackName>
<Instrument>
<trackName>Piano</trackName>
<minPitchP>21</minPitchP>
<maxPitchP>108</maxPitchP>
<minPitchA>21</minPitchA>
<maxPitchA>108</maxPitchA>
<Articulation name="">
<velocity>100</velocity>
<gateTime>70</gateTime>
</Articulation>
<Articulation name="staccato">
<velocity>100</velocity>
<gateTime>40</gateTime>
</Articulation>
<Articulation name="tenuto">
<velocity>100</velocity>
<gateTime>100</gateTime>
</Articulation>
<Articulation name="sforzato">
<velocity>120</velocity>
<gateTime>100</gateTime>
</Articulation>
<Channel>
<controller tick="0" channel="0" ctrl="0" value="0"/>
<controller tick="0" channel="0" ctrl="32" value="0"/>
<program tick="0" channel="0" value="0"/>
<controller tick="0" channel="0" ctrl="7" value="100"/>
<controller tick="0" channel="0" ctrl="10" value="64"/>
<controller tick="0" channel="0" ctrl="93" value="30"/>
<controller tick="0" channel="0" ctrl="91" value="30"/>
</Channel>
</Instrument>
</Part>
<Staff id="1">
<VBox>
<height>10</height>
<Text>
<style>Title</style>
<text>notes1</text>
</Text>
</VBox>
<Measure number="1">
<Clef>
<concertClefType>G</concertClefType>
<transposingClefType>G</transposingClefType>
</Clef>
<KeySig>
<accidental>0</accidental>
<showCourtesySig>1</showCourtesySig>
<showNaturals>1</showNaturals>
</KeySig>
<TimeSig>
<sigN>4</sigN>
<sigD>4</sigD>
<showCourtesySig>1</showCourtesySig>
</TimeSig>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>57</pitch>
<tpc>17</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>59</pitch>
<tpc>19</tpc>
</Note>
</Chord>
<Chord>
<durationType>half</durationType>
<Note>
<pitch>60</pitch>
<tpc>14</tpc>
</Note>
</Chord>
<BarLine>
<subtype>normal</subtype>
<span>2</span>
</BarLine>
</Measure>
<Measure number="2">
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>64</pitch>
<tpc>18</tpc>
</Note>
</Chord>
<Chord>
<durationType>half</durationType>
<Note>
<pitch>65</pitch>
<tpc>13</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>69</pitch>
<tpc>17</tpc>
</Note>
</Chord>
<BarLine>
<subtype>normal</subtype>
<span>2</span>
</BarLine>
</Measure>
<Measure number="3">
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>71</pitch>
<tpc>19</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>72</pitch>
<tpc>14</tpc>
</Note>
</Chord>
<Chord>
<durationType>half</durationType>
<Note>
<pitch>74</pitch>
<tpc>16</tpc>
</Note>
</Chord>
<BarLine>
<subtype>normal</subtype>
<span>2</span>
</BarLine>
</Measure>
<Measure number="4">
<Chord>
<durationType>half</durationType>
<Note>
<pitch>77</pitch>
<tpc>13</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>81</pitch>
<tpc>17</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>83</pitch>
<tpc>19</tpc>
</Note>
</Chord>
<BarLine>
<subtype>normal</subtype>
<span>2</span>
</BarLine>
</Measure>
</Staff>
<Staff id="2">
<Measure number="1">
<Clef>
<concertClefType>F</concertClefType>
<transposingClefType>F</transposingClefType>
</Clef>
<KeySig>
<accidental>0</accidental>
<showCourtesySig>1</showCourtesySig>
<showNaturals>1</showNaturals>
</KeySig>
<TimeSig>
<sigN>4</sigN>
<sigD>4</sigD>
<showCourtesySig>1</showCourtesySig>
</TimeSig>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>36</pitch>
<tpc>14</tpc>
</Note>
</Chord>
<Chord>
<durationType>half</durationType>
<Note>
<pitch>38</pitch>
<tpc>16</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>41</pitch>
<tpc>13</tpc>
</Note>
</Chord>
</Measure>
<Measure number="2">
<Chord>
<durationType>half</durationType>
<Note>
<pitch>43</pitch>
<tpc>15</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>47</pitch>
<tpc>19</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>48</pitch>
<tpc>14</tpc>
</Note>
</Chord>
</Measure>
<Measure number="3">
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>50</pitch>
<tpc>16</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>52</pitch>
<tpc>18</tpc>
</Note>
</Chord>
<Chord>
<durationType>half</durationType>
<Note>
<pitch>53</pitch>
<tpc>13</tpc>
</Note>
</Chord>
</Measure>
<Measure number="4">
<Chord>
<durationType>half</durationType>
<Note>
<pitch>57</pitch>
<tpc>17</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>60</pitch>
<tpc>14</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>62</pitch>
<tpc>16</tpc>
</Note>
</Chord>
</Measure>
</Staff>
</Score>
</museScore>

View file

@ -1,67 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2012 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 <QtTest/QtTest>
#include "mtest/testutils.h"
#include "libmscore/score.h"
#define DIR QString("omr/notes/")
using namespace Ms;
//---------------------------------------------------------
// TestNotes
//---------------------------------------------------------
class TestNotes : public QObject, public MTest
{
Q_OBJECT
void omrFileTest(QString file);
private slots:
void initTestCase();
//void notes2() { omrFileTest("notes2"); }
//void notes1() { omrFileTest("notes1"); }
};
//---------------------------------------------------------
// initTestCase
//---------------------------------------------------------
void TestNotes::initTestCase()
{
initMTest();
}
//---------------------------------------------------------
// compat_data
// every "xxx" test requires two *.mscx files:
// xxx.mscx is the mscore 1.2 file
// xxx-ref.mscx is the corresponding (correct)
// mscore 2.0 file
//---------------------------------------------------------
void TestNotes::omrFileTest(QString file)
{
MasterScore* score = readScore(DIR + file + ".mscx");
score->doLayout();
QVERIFY(score);
savePdf(score, file + ".pdf");
Score* score1 = readCreatedScore(file + ".pdf");
QVERIFY(score1);
score1->doLayout();
QVERIFY(saveCompareScore(score1, file + ".mscx", DIR + file + "-ref.mscx"));
}
QTEST_MAIN(TestNotes)
#include "tst_notes.moc"

View file

@ -122,13 +122,7 @@ MasterScore* MTest::readCreatedScore(const QString& name)
rv = score->loadMsc(name, false);
} else if (csl == "mxl") {
rv = importCompressedMusicXml(score, name);
}
#ifdef OMR
else if (csl == "pdf") {
rv = importPdf(score, name);
}
#endif
else if (csl == "xml" || csl == "musicxml") {
} else if (csl == "xml" || csl == "musicxml") {
rv = importMusicXml(score, name);
} else if (csl == "gp3" || csl == "gp4" || csl == "gp5" || csl == "gpx" || csl == "gp" || csl == "ptb") {
rv = importGTP(score, name);

View file

@ -1,71 +0,0 @@
#=============================================================================
# MusE
# Linux Music Editor
#
# Copyright (C) 2002-2006 by Werner Schweer and others
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#=============================================================================
include (${PROJECT_SOURCE_DIR}/build/gch.cmake)
include_directories(
${PROJECT_SOURCE_DIR}
${PROJECT_BINARY_DIR}
)
if (OCR)
set (OCR_SRC ocr.cpp)
endif (OCR)
if (NOT MSVC)
set(_all_h_file "${PROJECT_BINARY_DIR}/all.h")
else (NOT MSVC)
set(_all_h_file "${PROJECT_SOURCE_DIR}/all.h")
endif (NOT MSVC)
add_library (
omr STATIC
${_all_h_file}
${PCH}
omrview.cpp pdf.cpp omrpage.cpp
skew.cpp utils.cpp
omr.cpp pattern.cpp importpdf.cpp
${OCR_SRC}
)
if (NOT MSVC)
set_target_properties (
omr
PROPERTIES
COMPILE_FLAGS "${PCH_INCLUDE} -g -Wall -Wextra -Winvalid-pch -Wno-unused-private-field"
)
else (NOT MSVC)
set_target_properties (
omr
PROPERTIES
COMPILE_FLAGS "${PCH_INCLUDE}" # TODO: Add disabling of unused private field warning?
)
endif (NOT MSVC)
xcode_pch(omr all)
# Use MSVC pre-compiled headers
vstudio_pch( omr )
# MSVC does not depend on mops1 & mops2 for PCH
if (NOT MSVC)
ADD_DEPENDENCIES(omr mops1)
ADD_DEPENDENCIES(omr mops2)
endif (NOT MSVC)

View file

@ -1,47 +0,0 @@
# Updates on Optical Music Recognition
### Graphical Model for System Identification
1. We can simply use vertical line detection to find bar lines. But the detection performance is unreliable due to noise such as note stems or lines in text. The other problem of solely relying on line detection is that we can hardly interpret the structure of systems based on what has been detected. The solution to this problem is using a graphical model to represent the system structure and encode useful distance or non-overlapping constraints, with which we can determine the grouping of staves into systems and the location of barlines in each system at the same time (simultaneously estimate both).
2. Suppose we have n staves (n-1 gaps), then there'll be 2^(n-1) ways of grouping systems if taking each gap as a binary switch connecting or not connecting the adjacent staves. In each system (staff group), barline positions will be commonly shared (a very strong and useful constraint!). We can use a nested dynamic programming to solve this problem. The optimal hypothesis (how the staves are grouped together) until the k-th stave yielding the max score h(k) = max(h(i) + system(i+1, ..., k)), based on previous optimal hypotheses h(i), i= 1,2,...,k-1.
In each hypothesized system(i,...,j) from i-th to j-th staves, we recognize shared barlines from left to right by finding the best scoring configuration
b_opt = max(b(k1) + b(k2) + ... + b(kn)) supposing each horizontal location corresponds to a bar or just background, where b(.) is the scoring function for barline in that column. We can also incorporate negative constraints (clef, key sigs, time sigs, or note stem) into this bar line recognition process.
<!--Likelihood Model for Symbol Template Matching
1, Given a binary image I and a symbol model M, we want to decide at any location (i,j) of I, whether there's a probable symbol candidate via data likelihood:
P(I(i,j)|M) = P(p(i,j)|M)*P(p(i+1,j)|M)*...*P(p(i+n,j)|M)
*P(p(i,j+1)|M)*P(p(i+1,j+1)|M)*...*P(p(i+n,j+1)|M)
*...
*P(p(i,j+m)|M)*P(p(i+1,j+m)|M)*...*P(p(i+n,j+m)|M)
which assumes each pixel in the region of interest is conditionally independent given the model M. The higher this likelihood is, the more possible there is such a symbol.
2, Training of M.
Given a set of symbol instances I(training dataset), we want to determine what's the probability distribution for each location (x,y) of model M. Since the observation is binary (only has two possible values: 0 or 1), the probability of M(x,y) can be easily estimated through Maximal-Likelihood-Estimation (MLE) from all the positive instances as follows:
P(black | M(x,y)) = #(black at I(x,y))/(#(black at I(x,y)) + #(white at I(x,y))), for all I in the training set
P(white | M(x,y)) = 1 - P(black | M(x,y))
3, Thresholding for candidate detection
For test image I, we obtain the background model B by counting the number of all black's and white's on the image.
P(black | B) = #(black on I)/#(pixels on I)
P(white | B) = 1 - P(black | B)
Then the candidate scoring function can be written as
S(I(i,j)) = log(P(I(i,j)|M) / P(I(i,j)|B)) = Sum( log(P(p(i+ii,j+jj)|M)) - log(P(p(i+ii,j+jj)|B))), where p(i+ii,j+jj) is the pixel value (0 or 1) at position (i+ii, j+jj).
If S(I(i,j)) is larger than 0, we say at position (i,j) there's a symbols candidate. This threshold 0 is automatically determined by our background model, but can also be tuned according to our request (e.g. for higher precision than recall the threshold should be larger).-->
### Demo
[Screenshots of some results](https://musescore.org/en/node/110306#comment-500796)
### Todo
* Add robust note detector to impose negative constraints for bar line identification. (see [here](https://github.com/musescore/MuseScore/blob/master/omr/omrpage.cpp#L292))
* Fix staff detection for vector graphs
* Optimize OMR performance and add clef/key recognitions

View file

@ -1,55 +0,0 @@
- Qualität messen: Rauschabstand
- Erkennungswahrscheinlichkeit: 0 - 1.0
- Abstand zwischen "false positive" und nicht erkannten Elementen = Rauschabstand
- Erkennen von Notenlinien:
- die horizontale Projektion soll Kanten berücksichtigen
- Zeichenerkennung
- Zeichenränder sollen mit einbezogen werden, um den Rauschabstand zu verbessern
- Rekursion
- erkannten Notenköpfe korrigieren die Position der Notenlinien
- Notenköpfe:
- Notenlinien und Notenhals in Muster einzeichnen:
- ergibt 6 Varianten per Kopf:
- zwischen den Notenlinien
- auf den Notenlinien
- Hals nach oben
- Hals nach unten
- Hals durchlaufend (Akkord)
TODO:
* Taktstriche erkennen
- Systeme erkennen
System-Preamble erkennen:
* Schlüssel erkennen
* Taktart erkennen
- Tonartvorzeichen erkennen
- Vorzeichen erkennen
- Notenhälse
- Flags
- Beams
===========================================
* create OmrMeasure
* distribute notes into measures
* detect timesig
- detect clef
* create notes in score
for simple cases
* create chords
panel:
- notehead detection threshold
score gui:
- hover with mouse and detect element
- show info about element

View file

@ -1,36 +0,0 @@
//=============================================================================
// MusE Reader
// Music Score Reader
//
// Copyright (C) 2010 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.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef __IMAGE_H__
#define __IMAGE_H__
namespace Ms {
//---------------------------------------------------------
// Image
//---------------------------------------------------------
class Image : public QImage
{
public:
};
extern double imageSkew(const QImage& image);
}
#endif

View file

@ -1,297 +0,0 @@
//=============================================================================
// MuseScore
// Linux Music Score Editor
//
// Copyright (C) 2002-2011 Werner Schweer and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "importpdf.h"
#include "libmscore/score.h"
#include "omr/omr.h"
#include "libmscore/part.h"
#include "libmscore/staff.h"
#include "libmscore/measure.h"
#include "libmscore/rest.h"
#include "omr/omrpage.h"
#include "libmscore/segment.h"
#include "libmscore/layoutbreak.h"
#include "libmscore/page.h"
#include "libmscore/clef.h"
#include "libmscore/bracket.h"
#include "libmscore/mscore.h"
#include "libmscore/chord.h"
#include "libmscore/note.h"
#include "libmscore/utils.h"
#include "libmscore/timesig.h"
#include "libmscore/keysig.h"
#include "libmscore/spacer.h"
#include "libmscore/box.h"
#include "libmscore/spatium.h"
namespace Ms {
//---------------------------------------------------------
// OmrState
//---------------------------------------------------------
class OmrState
{
public:
MasterScore* score = 0;
Fraction timesig { 4, 4 };
Fraction tick = Fraction(0, 1);
void importPdfPage(OmrPage* omrPage, qreal top);
Fraction importPdfSystem(OmrSystem* omrSystem);
void importPdfMeasure(OmrMeasure* m, const OmrSystem* omrSystem);
};
//---------------------------------------------------------
// importPdfMeasure
//---------------------------------------------------------
void OmrState::importPdfMeasure(OmrMeasure* m, const OmrSystem* omrSystem)
{
Measure* measure = new Measure(score);
measure->setTick(tick);
if (m->timesig()) {
timesig = m->timesig()->timesig;
score->sigmap()->add(tick.ticks(), SigEvent(timesig));
}
measure->setTimesig(timesig);
measure->setTicks(timesig);
TDuration d(TDuration::DurationType::V_MEASURE);
Rest* rest;
Segment* s = measure->getSegment(SegmentType::ChordRest, tick);
for (int staffIdx = 0; staffIdx < omrSystem->staves().size(); ++staffIdx) {
rest = new Rest(score, d);
rest->setTicks(timesig);
rest->setTrack(staffIdx * 4);
s->add(rest);
}
#if 0
for (int staffIdx = 0; staffIdx < omrSystem->staves().size(); ++staffIdx) {
if (tick == 0) {
const OmrStaff& omrStaff = omrSystem->staves()[staffIdx];
int keySigType = omrStaff.keySig().type;
KeySig* ks = new KeySig(score);
//ks->setSig(keySigType, keySigType);
ks->setTrack(staffIdx * VOICES);
Segment* s = measure->getSegment(SegmentType::KeySig, 0);
s->add(ks);
//score->staff(staffIdx)->setKey(0, keySigType);
}
if (m->timesig()) {
TimeSig* ts = new TimeSig(score);
Segment* s = measure->getSegment(SegmentType::TimeSig, tick);
ts->setSig(timesig);
ts->setTrack(staffIdx * VOICES);
s->add(ts);
}
Fraction nl;
QList<OmrChord>& chords = m->chords()[staffIdx];
if (timesig == Fraction(3,8)) {
if (chords.size() == 1) {
chords[0].duration = TDuration(timesig);
} else if (chords.size() == 3) {
int i = 0;
for (; i < 3; ++i) {
if (chords[i].duration.fraction() != Fraction(1,4)) {
break;
}
}
if (i == 3) {
for (i = 0; i < 3; ++i) {
chords[i].duration = TDuration(Fraction(1, 8));
}
}
}
}
foreach (const OmrChord& omrChord, chords) {
nl += omrChord.duration.fraction();
}
bool notesOk = nl == timesig;
if (notesOk) {
Fraction ltick = Fraction(0, 1);
foreach (const OmrChord& omrChord, chords) {
Chord* chord = new Chord(score);
chord->setDurationType(omrChord.duration);
chord->setDuration(omrChord.duration.fraction());
chord->setTrack(staffIdx * VOICES);
Segment* s = measure->getSegment(SegmentType::ChordRest, tick + ltick);
s->add(chord);
//int keyType = score->staff(staffIdx)->key(tick + ltick).accidentalType();
foreach (OmrNote* omrNote, omrChord.notes) {
Note* note = new Note(score);
//ClefType clef = score->staff(staffIdx)->initialClef()._concertClef;
//int pitch = line2pitch(omrNote->line, clef, keyType);
//note->setPitch(pitch);
note->setTpcFromPitch();
chord->add(note);
}
ltick += omrChord.duration.fraction();
}
} else {
TDuration d(TDuration::DurationType::V_MEASURE);
Segment* s = measure->getSegment(SegmentType::ChordRest, measure->tick());
Rest* rest = new Rest(score, d);
rest->setDuration(timesig);
rest->setTrack(staffIdx * VOICES);
s->add(rest);
}
}
#endif
score->measures()->add(measure);
tick += measure->timesig();
}
//---------------------------------------------------------
// importPdfSystem
//---------------------------------------------------------
Fraction OmrState::importPdfSystem(OmrSystem* omrSystem)
{
for (int i = 0; i < omrSystem->measures().size(); ++i) {
OmrMeasure* m = &omrSystem->measures()[i];
importPdfMeasure(m, omrSystem);
}
if (score->lastMeasure()) {
LayoutBreak* b = new LayoutBreak(score);
b->setLayoutBreakType(LayoutBreak::Type::LINE);
score->lastMeasure()->add(b);
}
return tick;
}
//---------------------------------------------------------
// importPdfPage
//---------------------------------------------------------
void OmrState::importPdfPage(OmrPage* omrPage, qreal top)
{
TDuration d(TDuration::DurationType::V_MEASURE);
int nsystems = omrPage->systems().size();
if (nsystems == 0) {
return;
}
//add top margin for alignment
MeasureBase* first_measure = score->first();
if (first_measure == 0 || first_measure->isVBox()) {
VBox* vbox = new VBox(score);
vbox->setNext(score->first());
vbox->setTick(Fraction(0,1));
vbox->setBoxHeight(Spatium(top));
vbox->setBottomMargin(0);
vbox->setBottomGap(0);
score->measures()->add(vbox);
}
for (int k = 0; k < nsystems; ++k) {
importPdfSystem(omrPage->system(nsystems - k - 1));
}
Measure* measure = score->lastMeasure();
if (measure) {
LayoutBreak* b = new LayoutBreak(score);
b->setLayoutBreakType(LayoutBreak::Type::PAGE);
measure->add(b);
}
measure = score->firstMeasure();
if (measure) {
if (!measure->vspacerUp(0)) {
Spacer* spacer = new Spacer(score);
spacer->setSpacerType(SpacerType::UP);
spacer->setTrack(0);
measure->add(spacer);
}
Spacer* sp = measure->vspacerUp(0);
sp->layout();
sp->setPos(sp->rxpos(), top);
}
}
//---------------------------------------------------------
// importPdf
//---------------------------------------------------------
Score::FileError importPdf(MasterScore* score, const QString& path)
{
Omr* omr = new Omr(path, score);
if (!omr->readPdf()) {
delete omr;
return Score::FileError::FILE_BAD_FORMAT;
}
score->setOmr(omr);
qreal sp = omr->spatiumMM();
if (sp == 0.0) {
sp = 1.5;
}
score->setSpatium(sp * DPMM);
score->style().set(Sid::lastSystemFillLimit, 0.0);
score->style().set(Sid::staffLowerBorder, 0.0);
score->style().set(Sid::measureSpacing, 1.0);
score->style().set(Sid::frameSystemDistance, 0);
score->style().set(Sid::pageEvenLeftMargin, 5.0 * DPMM / DPI);
score->style().set(Sid::pageEvenTopMargin, 0);
score->style().set(Sid::pageEvenBottomMargin, 0);
score->style().set(Sid::pageOddLeftMargin, 5.0 * DPMM / DPI);
score->style().set(Sid::pageOddTopMargin, 0);
score->style().set(Sid::pageOddBottomMargin, 0);
score->style().set(Sid::minSystemDistance, Spatium(omr->systemDistance()));
score->style().set(Sid::maxSystemDistance, Spatium(omr->systemDistance()));
score->style().set(Sid::akkoladeDistance, Spatium(omr->staffDistance()));
Part* part = new Part(score);
OmrPage* omrPage = omr->pages().front();
//may need to identify maximal number of staff per system and then high some of those
if (omrPage->systems().size() > 0) {
for (int i = 0; i < omrPage->systems().front().staves().size(); i++) {
Staff* staff = new Staff(score);
staff->setPart(part);
part->insertStaff(staff, -1);
score->staves().append(staff);
}
}
score->appendPart(part);
OmrState state;
state.score = score;
for (OmrPage* omrPage1 : omr->pages()) {
OmrStaff staff = omrPage1->systems().last().staves().first();
qreal top = staff.top() / omr->spatium();
state.importPdfPage(omrPage1, top);
}
//---create bracket
//score->staff(0)->setBracket(0, BracketType::BRACE);
//score->staff(0)->setBracketSpan(0, 2);
score->setShowOmr(true);
omr->page(0)->readHeader(score);
score->rebuildMidiMapping();
return Score::FileError::FILE_NO_ERROR;
}
}

View file

@ -1,29 +0,0 @@
//=============================================================================
// MuseScore
// Linux Music Score Editor
//
// Copyright (C) 2012 Werner Schweer and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef __IMPORT_PDF_H__
#define __IMPORT_PDF_H__
#include "libmscore/score.h"
namespace Ms {
extern Score::FileError importPdf(MasterScore*, const QString&);
}
#endif

View file

@ -1,79 +0,0 @@
//=============================================================================
// MusE Reader
// Music Score Reader
//
// Copyright (C) 2010 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.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "ocr.h"
#include <tesseract/baseapi.h>
#include <locale.h>
namespace Ms {
//---------------------------------------------------------
// Ocr
//---------------------------------------------------------
Ocr::Ocr()
{
tess = 0;
}
//---------------------------------------------------------
// init
//---------------------------------------------------------
void Ocr::init()
{
if (tess == 0) {
tess = new tesseract::TessBaseAPI;
}
tess->Init("/usr/local/share/tessdata", 0, 0, 0, false);
}
//---------------------------------------------------------
// readLine
//---------------------------------------------------------
QString Ocr::readLine(const OcrImage& img)
{
int w = img.r.width();
int h = img.r.height();
int bw = (w + 7) / 8;
uchar* d = new uchar[bw * h];
memset(d, 0, bw * h);
uchar* p = d;
int yo = img.r.y();
int xo = img.r.x();
for (int y = 0; y < h; ++y) {
for (int x = 0; x < bw; ++x) {
int mask = 0x80;
uchar dst = 0;
for (int xx = 0; xx < 8; ++xx) {
if (img.dot(x * 8 + xo + xx, y + yo)) {
dst |= mask;
}
mask >>= 1;
}
*p++ = ~dst;
}
}
char* txt = tess->TesseractRect(d, 0, bw, 0, 0, w, h);
return QString(txt);
}
}

View file

@ -1,62 +0,0 @@
//=============================================================================
// MusE Reader
// Music Score Reader
//
// Copyright (C) 2010 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.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef __OCR_H__
#define __OCR_H__
namespace tesseract {
class TessBaseAPI;
}
namespace Ms {
//---------------------------------------------------------
// OcrImage
//---------------------------------------------------------
struct OcrImage {
uint* image;
QRect r;
int stride; // uint* stride
OcrImage() {}
OcrImage(const uchar* p, const QRect& _r, int _s)
: image((uint*)p), r(_r), stride(_s) {}
OcrImage crop() const;
bool dot(int x, int y) const
{
return (*(image + (y * stride) + (x / 32))) & (0x1 << (x % 32));
}
};
//---------------------------------------------------------
// Ocr
//---------------------------------------------------------
class Ocr
{
tesseract::TessBaseAPI* tess;
public:
Ocr();
void init();
QString readLine(const OcrImage&);
};
}
#endif

View file

@ -1,299 +0,0 @@
//=============================================================================
// MusE Reader
// Music Score Reader
//
// Copyright (C) 2010 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.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "omr.h"
#include "omrview.h"
#include "libmscore/xml.h"
#include "libmscore/sym.h"
#include "omrpage.h"
#include "pdf.h"
#ifdef OCR
#include "ocr.h"
#endif
#include "utils.h"
#include "pattern.h"
namespace Ms {
#ifdef OMR
class ScoreView;
Pattern* Omr::quartheadPattern;
Pattern* Omr::halfheadPattern;
Pattern* Omr::sharpPattern;
Pattern* Omr::flatPattern;
Pattern* Omr::naturalPattern;
Pattern* Omr::trebleclefPattern;
Pattern* Omr::bassclefPattern;
Pattern* Omr::timesigPattern[10];
//---------------------------------------------------------
// Omr
//---------------------------------------------------------
Omr::Omr(Score* s)
{
_score = s;
#ifdef OCR
_ocr = 0;
#endif
ActionNames = QList<QString>() << QWidget::tr("Loading PDF") << QWidget::tr("Initializing Staves") << QWidget::tr(
"Identifying Systems");
initUtils();
}
Omr::Omr(const QString& p, Score* s)
{
_score = s;
_path = p;
_ocr = 0;
ActionNames = QList<QString>() << QWidget::tr("Loading PDF") << QWidget::tr("Initializing Staves") << QWidget::tr(
"Load Parameters") << QWidget::tr("Identifying Systems");
initUtils();
}
//---------------------------------------------------------
// newOmrView
//---------------------------------------------------------
OmrView* Omr::newOmrView(ScoreView* sv)
{
OmrView* ov = new OmrView(sv);
ov->setOmr(this);
return ov;
}
//---------------------------------------------------------
// write
//---------------------------------------------------------
void Omr::write(XmlWriter& xml) const
{
xml.stag("Omr");
xml.tag("path", _path);
xml.tag("spatium", _spatium);
xml.tag("dpmm", _dpmm);
for (OmrPage* page : _pages) {
page->write(xml);
}
xml.etag();
}
//---------------------------------------------------------
// read
//---------------------------------------------------------
void Omr::read(XmlReader& e)
{
_doc = 0;
#ifdef OCR
if (_ocr == 0) {
_ocr = new Ocr;
}
_ocr->init();
#endif
while (e.readNextStartElement()) {
const QStringRef& tag(e.name());
if (tag == "path") {
_path = e.readElementText();
} else if (tag == "OmrPage") {
OmrPage* page = new OmrPage(this);
page->read(e);
_pages.append(page);
} else if (tag == "spatium") {
_spatium = e.readDouble();
} else if (tag == "dpmm") {
_dpmm = e.readDouble();
} else {
e.unknown();
}
}
}
//---------------------------------------------------------
// pagesInDocument
//---------------------------------------------------------
int Omr::pagesInDocument() const
{
return _doc ? _doc->numPages() : 0;
}
//---------------------------------------------------------
// readPdf
// return true on success
//---------------------------------------------------------
bool Omr::readPdf()
{
QProgressDialog* progress = new QProgressDialog(QWidget::tr("Reading PDF…"), QWidget::tr(
"Cancel"), 0, 100, 0, Qt::FramelessWindowHint);
progress->setWindowModality(Qt::ApplicationModal);
progress->show();
progress->setRange(0, ACTION_NUM);
#ifdef OCR
if (_ocr == 0) {
_ocr = new Ocr;
}
_ocr->init();
#endif
int ID = READ_PDF;
int page = 0;
bool val;
while (ID < ACTION_NUM) {
if (ID != INIT_PAGE && ID != SYSTEM_IDENTIFICATION) {
page = 0;
progress->setLabelText(QWidget::tr("%1 at Page %2").arg(ActionNames.at(ID + 1)).arg(1));
val = omrActions(ID, page);
} else {
progress->setLabelText(QWidget::tr("%1 at Page %2").arg(ActionNames.at(ID)).arg(page + 1));
val = omrActions(ID, page);
page++;
}
if (!val || progress->wasCanceled()) {
progress->close();
return false;
} else {
if (ID < ACTION_NUM) {
progress->setValue(ID);
} else {
progress->setValue(ACTION_NUM - 1);
}
qApp->processEvents();
}
}
progress->close();
delete progress;
return true;
}
//---------------------------------------------------------
// actions
//---------------------------------------------------------
bool Omr::omrActions(int& ID, int page)
{
if (ID == READ_PDF) {
_doc = new Pdf();
if (!_doc->open(_path)) {
delete _doc;
_doc = 0;
return false;
}
int n = _doc->numPages();
//printf("readPdf: %d pages\n", n);
for (int i = 0; i < n; ++i) {
OmrPage* page1 = new OmrPage(this);
QImage image = _doc->page(i);
if (image.isNull()) {
return false;
}
page1->setImage(image);
_pages.append(page1);
}
_spatium = 15.0; //constant spatium, image will be rescaled according to this parameter
ID++;
return true;
} else if (ID == INIT_PAGE) {
//load one page and rescale
_pages[page]->read();
//do the rescaling here
int new_w = _pages[page]->image().width() * _spatium / _pages[page]->spatium();
int new_h = _pages[page]->image().height() * _spatium / _pages[page]->spatium();
QImage image = _pages[page]->image().scaled(new_w,new_h, Qt::KeepAspectRatio);
_pages[page]->setImage(image);
_pages[page]->read();
if (page == _pages.size() - 1) {
ID++;
}
return true;
} else if (ID == FINALIZE_PARMS) {
int n = _pages.size();
double w = 0;
for (int i = 0; i < n; ++i) {
w += _pages[i]->width();
}
w /= n;
_dpmm = w / 210.0; // PaperSize A4
quartheadPattern = new Pattern(_score, "solid_note_head");
halfheadPattern = new Pattern(_score, SymId::noteheadHalf, _spatium);
sharpPattern = new Pattern(_score, SymId::accidentalSharp, _spatium);
flatPattern = new Pattern(_score, SymId::accidentalFlat, _spatium);
naturalPattern = new Pattern(_score, SymId::accidentalNatural,_spatium);
trebleclefPattern = new Pattern(_score, SymId::gClef,_spatium);
bassclefPattern = new Pattern(_score, SymId::fClef,_spatium);
timesigPattern[0] = new Pattern(_score, SymId::timeSig0, _spatium);
timesigPattern[1] = new Pattern(_score, SymId::timeSig1, _spatium);
timesigPattern[2] = new Pattern(_score, SymId::timeSig2, _spatium);
timesigPattern[3] = new Pattern(_score, SymId::timeSig3, _spatium);
timesigPattern[4] = new Pattern(_score, SymId::timeSig4, _spatium);
timesigPattern[5] = new Pattern(_score, SymId::timeSig5, _spatium);
timesigPattern[6] = new Pattern(_score, SymId::timeSig6, _spatium);
timesigPattern[7] = new Pattern(_score, SymId::timeSig7, _spatium);
timesigPattern[8] = new Pattern(_score, SymId::timeSig8, _spatium);
timesigPattern[9] = new Pattern(_score, SymId::timeSig9, _spatium);
ID++;
return true;
} else if (ID == SYSTEM_IDENTIFICATION) {
_pages[page]->identifySystems();
if (page == _pages.size() - 1) {
ID++;
}
return true;
}
return false;
}
//---------------------------------------------------------
// spatiumMM
//---------------------------------------------------------
double Omr::spatiumMM() const
{
return _spatium / _dpmm;
}
//---------------------------------------------------------
// staffDistance
//---------------------------------------------------------
double Omr::staffDistance() const
{
return _pages[0]->staffDistance();
}
//---------------------------------------------------------
// systemDistance
//---------------------------------------------------------
double Omr::systemDistance() const
{
return _pages[0]->systemDistance();
}
#endif
}

242
omr/omr.h
View file

@ -1,242 +0,0 @@
//=============================================================================
// MusE Reader
// Music Score Reader
//
// Copyright (C) 2010 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.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef __OMR_H__
#define __OMR_H__
#include "config.h"
namespace Ms {
class OmrView;
class XmlWriter;
class Pdf;
class OmrPage;
class Ocr;
class Score;
class ScoreView;
class XmlReader;
class Pattern;
#ifdef OMR
//---------------------------------------------------------
// Omr
//---------------------------------------------------------
class Omr
{
QString _path;
double _spatium;
double _dpmm;
Pdf* _doc;
QList<OmrPage*> _pages;
Ocr* _ocr;
Score* _score;
static void initUtils();
void process1(int page);
enum ActionID {
READ_PDF, INIT_PAGE, FINALIZE_PARMS, SYSTEM_IDENTIFICATION, ACTION_NUM
};
QList<QString> ActionNames;
public:
Omr(Score*);
Omr(const QString& path, Score*);
static char bitsSetTable[256];
bool readPdf();
int pagesInDocument() const;
int numPages() const
{
return _pages.size();
}
OmrPage* page(int idx)
{
return _pages[idx];
}
OmrView* newOmrView(ScoreView*);
const QList<OmrPage*>& pages() const
{
return _pages;
}
#ifdef OCR
Ocr* ocr() const
{
return _ocr;
}
#endif
void write(XmlWriter&) const;
void read(XmlReader&);
double spatiumMM() const; // spatium in millimeter
double spatium() const
{
return _spatium;
}
void setSpatium(double val)
{
_spatium = val;
}
double dpmm() const
{
return _dpmm;
}
void setDpmm(double val)
{
_dpmm = val;
}
double staffDistance() const;
double systemDistance() const;
Score* score() const
{
return _score;
}
const QString& path() const
{
return _path;
}
bool omrActions(int& ID, int page = 0);
static Pattern* quartheadPattern;
static Pattern* halfheadPattern;
static Pattern* sharpPattern;
static Pattern* flatPattern;
static Pattern* naturalPattern;
static Pattern* trebleclefPattern;
static Pattern* bassclefPattern;
static Pattern* timesigPattern[10];
};
#else
//---------------------------------------------------------
// Omr
//---------------------------------------------------------
class Omr
{
QString _path;
QList<OmrPage*> _pages;
public:
Omr(Score*)
{
}
Omr(const QString&, Score*)
{
}
bool readPdf()
{
return false;
}
int pagesInDocument() const
{
return 0;
}
int numPages() const
{
return 0;
}
OmrPage* page(int)
{
return 0;
}
const QList<OmrPage*>& pages() const
{
return _pages;
}
OmrView* newOmrView(ScoreView*)
{
return 0;
}
#ifdef OCR
Ocr* ocr() const
{
return 0;
}
#endif
void write(XmlWriter&) const
{
}
void read(XmlReader&)
{
}
double spatiumMM() const
{
return 0;
}
double spatium() const
{
return 0;
}
double dpmm() const
{
return 0;
}
double staffDistance() const
{
return 0;
}
double systemDistance() const
{
return 0;
}
Score* score() const
{
return 0;
}
const QString& path() const
{
return _path;
}
};
#endif
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,272 +0,0 @@
//=============================================================================
// MusE Reader
// Music Score Reader
//
// Copyright (C) 2010 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.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef __OMRPAGE_H__
#define __OMRPAGE_H__
#include "libmscore/mscore.h"
#include "libmscore/durationtype.h"
#include "libmscore/fraction.h"
#include "libmscore/clef.h"
#include "libmscore/xml.h"
#include "libmscore/sym.h"
namespace Ms {
class Omr;
class Score;
class XmlWriter;
class XmlReader;
class Pattern;
class OmrPage;
//---------------------------------------------------------
// HLine
//---------------------------------------------------------
struct HLine {
int x1, x2, y;
HLine() {}
HLine(int a, int b, int c)
: x1(a), x2(b), y(c) {}
};
//---------------------------------------------------------
// OmrPattern
//---------------------------------------------------------
class OmrPattern : public QRect
{
public:
OmrPattern()
: QRect(), sym(SymId::noSym), prob(0.0) {}
SymId sym;
double prob;
};
//---------------------------------------------------------
// OmrClef
//---------------------------------------------------------
class OmrClef : public OmrPattern
{
public:
OmrClef()
: OmrPattern() {}
OmrClef(const OmrPattern& p)
: OmrPattern(p) {}
ClefType type = ClefType::G; //CLEF_G;
};
//---------------------------------------------------------
// OmrNote
// object on staff line
//---------------------------------------------------------
class OmrNote : public OmrPattern
{
public:
int line;
};
//---------------------------------------------------------
// OmrChord
//---------------------------------------------------------
class OmrChord
{
public:
TDuration duration;
QList<OmrNote*> notes;
};
//---------------------------------------------------------
// OmrTimesig
//---------------------------------------------------------
class OmrTimesig : public QRect
{
public:
OmrTimesig() {}
OmrTimesig(const QRect& r)
: QRect(r) {}
Fraction timesig;
};
//---------------------------------------------------------
// OmrKeySig
//---------------------------------------------------------
class OmrKeySig : public QRect
{
public:
OmrKeySig() {}
OmrKeySig(const QRect& r)
: QRect(r) {}
int type = 0; // -7 -> +7
};
//---------------------------------------------------------
// OmrMeasure
//---------------------------------------------------------
class OmrMeasure
{
int _x1, _x2;
QList<QList<OmrChord> > _chords; // list of notes for every staff
OmrTimesig* _timesig = 0;
public:
OmrMeasure() {}
OmrMeasure(int x1, int x2)
: _x1(x1), _x2(x2) {}
QList<QList<OmrChord> >& chords() { return _chords; }
const QList<QList<OmrChord> >& chords() const { return _chords; }
int x1() const { return _x1; }
int x2() const { return _x2; }
OmrTimesig* timesig() const { return _timesig; }
void setTimesig(OmrTimesig* ts) { _timesig = ts; }
};
//---------------------------------------------------------
// OmrStaff
// rectangle of staff lines
//---------------------------------------------------------
class OmrStaff : public QRect
{
QList<OmrNote*> _notes;
OmrClef _clef;
OmrKeySig _keySig;
public:
OmrStaff()
: QRect() {}
OmrStaff(const QRect& r)
: QRect(r) {}
OmrStaff(int x, int y, int w, int h)
: QRect(x, y, w, h) {}
QList<OmrNote*>& notes() { return _notes; }
const QList<OmrNote*>& notes() const { return _notes; }
OmrClef clef() const { return _clef; }
void setClef(const OmrClef& c) { _clef = c; }
OmrKeySig keySig() const { return _keySig; }
void setKeySig(const OmrKeySig& s) { _keySig = s; }
};
//---------------------------------------------------------
// OmrSystem
//---------------------------------------------------------
class OmrSystem
{
OmrPage* _page;
QList<OmrStaff> _staves;
QList<OmrMeasure> _measures;
void searchNotes(QList<OmrNote*>*, int x1, int x2, int y, int line);
public:
OmrSystem(OmrPage* p) { _page = p; }
const QList<OmrStaff>& staves() const { return _staves; }
QList<OmrStaff>& staves() { return _staves; }
QList<OmrMeasure>& measures() { return _measures; }
const QList<OmrMeasure>& measures() const { return _measures; }
QList<QLine> barLines;
void searchSysBarLines();
float searchBarLinesvar(int n_staff, int** note_labels);
void searchNotes();
void searchNotes(int* note_labels, int ran);
};
//---------------------------------------------------------
// OmrPage
//---------------------------------------------------------
class OmrPage
{
Omr* _omr;
QImage _image;
double _spatium;
double _ratio;
int cropL, cropR; // crop values in words (32 bit) units
int cropT, cropB; // crop values in pixel units
QList<QRect> _slices;
QList<OmrStaff> staves;
QList<HLine> slines;
QList<QLine> lines;
QList<OmrSystem> _systems;
void removeBorder();
void crop();
void slice();
double skew(const QRect&);
void deSkew();
void getStaffLines();
void getRatio();
double xproject2(int y);
int xproject(const uint* p, int wl);
void radonTransform(ulong* projection, int w, int n, const QRect&);
OmrTimesig* searchTimeSig(OmrSystem* system);
OmrClef searchClef(OmrSystem* system, OmrStaff* staff);
void searchKeySig(OmrSystem* system, OmrStaff* staff);
OmrPattern searchPattern(const std::vector<Pattern*>& pl, int y, int x1, int x2);
public:
OmrPage(Omr* _parent);
void setImage(const QImage& i) { _image = i; }
const QImage& image() const { return _image; }
QImage& image() { return _image; }
void read();
int width() const { return _image.width(); }
int height() const { return _image.height(); }
const uint* scanLine(int y) const { return (const uint*)_image.scanLine(y); }
const uint* bits() const { return (const uint*)_image.bits(); }
int wordsPerLine() const { return (_image.bytesPerLine() + 3) / 4; }
const QList<QLine>& sl() { return lines; }
const QList<HLine>& l() { return slines; }
const QList<QRect>& slices() const { return _slices; }
double spatium() const { return _spatium; }
double ratio() const { return _ratio; }
double staffDistance() const;
double systemDistance() const;
void readHeader(Score* score);
void readBarLines();
float searchBarLines(int start_staff, int end_staff);
void identifySystems();
const QList<OmrSystem>& systems() const { return _systems; }
//QList<OmrSystem>& systems() { return _systems; }
OmrSystem* system(int idx) { return &_systems[idx]; }
void write(XmlWriter&) const;
void read(XmlReader&);
bool dot(int x, int y) const;
bool isBlack(int x, int y) const;
};
}
#endif

View file

@ -1,470 +0,0 @@
//=============================================================================
// MusE Reader
// Music Score Reader
//
// Copyright (C) 2010 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.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "mscore/globals.h"
#include "omrview.h"
#include "omr.h"
#include "libmscore/page.h"
#include "omrpage.h"
#include "libmscore/score.h"
#include "mscore/scoreview.h"
#include "libmscore/sym.h"
#include "libmscore/mscore.h"
namespace Ms {
//---------------------------------------------------------
// OmrView
//---------------------------------------------------------
OmrView::OmrView(ScoreView* sv, QWidget* parent)
: QWidget(parent)
{
setFocusPolicy(Qt::StrongFocus);
setAttribute(Qt::WA_InputMethodEnabled);
setAttribute(Qt::WA_KeyCompression);
setMouseTracking(true);
_omr = 0;
_scoreView = sv;
double m = .25;
_fotoMode = false;
_matrix = QTransform(m, 0.0, 0.0, m, 0.0, 0.0);
xoff = yoff = 0;
_showLines = false;
_showBarlines = true;
_showSlices = true;
_showStaves = true;
}
//---------------------------------------------------------
// setOmr
//---------------------------------------------------------
void OmrView::setOmr(Omr* s)
{
delete _omr;
_omr = s;
if (s == 0 || s->numPages() == 0) {
maxTiles = 0;
return;
}
int n = s->numPages();
OmrPage* page = _omr->page(0);
const QImage& i = page->image();
Score* score = _scoreView->score();
double mag = _omr->spatium() / score->spatium();
pageWidth = lrint(score->styleD(Sid::pageWidth) * mag * DPI);
int htiles = ((pageWidth + TILE_W - 1) / TILE_W);
pageWidth = htiles * TILE_W;
int vtiles = (i.height() + TILE_H - 1) / TILE_H;
maxTiles = n * htiles * vtiles;
}
//---------------------------------------------------------
// initTile
//---------------------------------------------------------
void OmrView::initTile(Tile* t)
{
int page1 = t->r.x() / pageWidth;
if (page1 < 0) {
page1 = 0;
}
int n = _omr->numPages();
if (page1 >= n) {
return;
}
t->page = _omr->page(page1);
t->pageNo = page1;
const QImage& i = t->page->image();
int xoffset = 0; // (pageWidth - i.width()) / 2;
int x = t->r.x() - (t->pageNo * pageWidth) - xoffset;
t->pm = QPixmap::fromImage(i.copy(x, t->r.y(), TILE_W, TILE_H));
}
//---------------------------------------------------------
// Tile
//---------------------------------------------------------
Tile::Tile()
: no(0), r(0, 0, TILE_W, TILE_H), pm(TILE_W, TILE_H)
{
}
//---------------------------------------------------------
// paintEvent
//---------------------------------------------------------
void OmrView::paintEvent(QPaintEvent* event)
{
if (_omr == 0) {
return;
}
QPainter p(this);
p.setTransform(_matrix);
QRect r(event->rect());
//
// remove unused tiles
//
QRect rr = _matrix.inverted().mapRect(QRectF(r)).toRect();
rr.adjust(-1, -1, 2, 2);
QList<Tile*> nl;
for (Tile* t : usedTiles) {
if (t->r.intersects(rr)) {
nl.append(t);
} else {
freeTiles.append(t);
}
}
#if QT_VERSION >= 0x040800
usedTiles.swap(nl);
#else
QList<Tile*> tmp = nl;
nl = usedTiles;
usedTiles = tmp;
#endif
//
// add visible tiles
//
Score* score = _scoreView->score();
double sSpatium = score->spatium();
double spatium = _omr->spatium();
double mag = spatium / sSpatium;
int w = pageWidth;
int h = lrint(score->styleD(Sid::pageHeight) * mag * DPI);
int n = _omr->numPages();
int nx = (w * n) / TILE_W;
int ny = (h + TILE_H - 1) / TILE_H;
int y1 = rr.y() / TILE_H;
int y2 = (rr.y() + rr.height() + TILE_H - 1) / TILE_H;
int x1 = rr.x() / TILE_W;
int x2 = (rr.x() + rr.width() + TILE_W - 1) / TILE_W;
if (x1 < 0) {
x1 = 0;
}
if (y1 < 0) {
y1 = 0;
}
if (x2 > nx) {
x2 = nx;
}
if (y2 > ny) {
y2 = ny;
}
for (int y = y1; y < y2; ++y) {
for (int x = x1; x < x2; ++x) {
int no = nx * y + x;
if (no < 0 || no >= maxTiles) {
continue;
}
int i;
for (i = 0; i < usedTiles.size(); ++i) {
if (usedTiles[i]->no == no) {
break;
}
}
if (i == usedTiles.size()) {
// create new tile
Tile* t = freeTiles.isEmpty() ? new Tile : freeTiles.pop();
t->no = no;
t->r = QRect(x * TILE_W, y * TILE_H, TILE_W, TILE_H);
initTile(t);
usedTiles.append(t);
}
}
}
int minPage = 9000;
int maxPage = 0;
for (const Tile* t : usedTiles) {
p.drawPixmap(t->r, t->pm);
if (t->pageNo < minPage) {
minPage = t->pageNo;
}
if (t->pageNo > maxPage) {
maxPage = t->pageNo;
}
}
for (int pageNo = minPage; pageNo <= maxPage; ++pageNo) {
OmrPage* page = _omr->page(pageNo);
p.save();
p.translate(w * pageNo, 0);
if (_showLines) {
p.setPen(QPen(QColor(255, 0, 0, 80), 1.0));
for (QLine l : page->sl()) {
p.drawLine(QLineF(l.x1() + .5, l.y1() + .5, l.x2() + .5, l.y2() + .5));
}
}
if (_showSlices) {
for (const QRect r1 : page->slices()) {
p.fillRect(r1, QBrush(QColor(0, 100, 100, 50)));
}
}
if (_showStaves) {
for (const OmrSystem& s : page->systems()) { // staves
for (const OmrStaff& r1 : s.staves()) {
p.fillRect(r1, QBrush(QColor(0, 0, 100, 50)));
}
}
}
for (const OmrSystem& system : page->systems()) {
if (_showBarlines) {
p.setPen(QPen(Qt::blue, 3.0));
for (const QLineF& l : system.barLines) {
for (int w1 = 0; w1 < 10; w1++) {
p.drawLine(l.x1() + w1, l.y1(), l.x2() + w1, l.y2()); //add width to barline
}
}
}
for (const OmrStaff& staff : system.staves()) {
for (const OmrNote* n1 : staff.notes()) {
if (n1->sym == SymId::noteheadBlack) {
p.setPen(QPen(QColor(255, 0, 0), 2.0));
} else {
p.setPen(QPen(QColor(0, 0, 255), 2.0));
}
p.drawRect(*n1);
}
}
}
p.restore();
}
if (fotoMode()) {
// TODO
p.setBrush(QColor(0, 0, 50, 50));
QPen pen(QColor(0, 0, 255));
// always 2 pixel width
qreal w1 = 2.0 / p.matrix().m11();
pen.setWidthF(w1);
p.setPen(pen);
p.drawRect(_foto);
}
}
//---------------------------------------------------------
// mousePressEvent
//---------------------------------------------------------
void OmrView::mousePressEvent(QMouseEvent* e)
{
startDrag = e->pos();
}
//---------------------------------------------------------
// mouseMoveEvent
//---------------------------------------------------------
void OmrView::mouseMoveEvent(QMouseEvent* e)
{
if (QApplication::mouseButtons()) {
QPoint delta = e->pos() - startDrag;
int dx = delta.x();
int dy = delta.y();
xoff += dx;
yoff += dy;
_matrix.setMatrix(_matrix.m11(), _matrix.m12(), _matrix.m13(), _matrix.m21(),
_matrix.m22(), _matrix.m23(), _matrix.dx() + dx, _matrix.dy() + dy, _matrix.m33());
scroll(dx, dy, QRect(0, 0, width(), height()));
startDrag = e->pos();
}
}
//---------------------------------------------------------
// setMag
//---------------------------------------------------------
void OmrView::setMag(double nmag)
{
qreal m = mag();
if (nmag == m) {
return;
}
double deltamag = nmag / m;
_matrix.setMatrix(nmag, _matrix.m12(), _matrix.m13(), _matrix.m21(),
nmag, _matrix.m23(), _matrix.dx() * deltamag, _matrix.dy() * deltamag, _matrix.m33());
}
//---------------------------------------------------------
// zoom
//---------------------------------------------------------
void OmrView::zoom(int step, const QPoint& pos)
{
QTransform imatrix(_matrix.inverted());
QPointF p1 = imatrix.map(QPointF(pos));
double _scale = mag();
if (step > 0) {
for (int i = 0; i < step; ++i) {
_scale *= 1.1;
}
} else {
for (int i = 0; i < -step; ++i) {
_scale /= 1.1;
}
}
if (_scale > 16.0) {
_scale = 16.0;
} else if (_scale < 0.05) {
_scale = 0.05;
}
setMag(_scale);
QPointF p2 = imatrix.map(QPointF(pos));
QPointF p3 = p2 - p1;
int dx = lrint(p3.x() * _scale);
int dy = lrint(p3.y() * _scale);
_matrix.setMatrix(_matrix.m11(), _matrix.m12(), _matrix.m13(), _matrix.m21(),
_matrix.m22(), _matrix.m23(), _matrix.dx() + dx, _matrix.dy() + dy, _matrix.m33());
scroll(dx, dy, QRect(0, 0, width(), height()));
update();
}
//---------------------------------------------------------
// wheelEvent
//---------------------------------------------------------
void OmrView::wheelEvent(QWheelEvent* event)
{
if (event->modifiers() & Qt::ControlModifier) {
QApplication::sendPostedEvents(this, 0);
zoom(event->delta() / 120, event->pos());
return;
}
int dx = 0;
int dy = 0;
if (event->modifiers() & Qt::ShiftModifier || event->orientation() == Qt::Horizontal) {
//
// scroll horizontal
//
int n = width() / 10;
if (n < 2) {
n = 2;
}
dx = event->delta() * n / 120;
} else {
//
// scroll vertical
//
int n = height() / 10;
if (n < 2) {
n = 2;
}
dy = event->delta() * n / 120;
}
_matrix.setMatrix(_matrix.m11(), _matrix.m12(), _matrix.m13(), _matrix.m21(),
_matrix.m22(), _matrix.m23(), _matrix.dx() + dx, _matrix.dy() + dy, _matrix.m33());
scroll(dx, dy, QRect(0, 0, width(), height()));
}
//---------------------------------------------------------
// setScale
//---------------------------------------------------------
void OmrView::setScale(double v)
{
double spatium = _omr->spatium();
setMag(v / spatium);
update();
}
//---------------------------------------------------------
// setOffset
//---------------------------------------------------------
void OmrView::setOffset(double x, double y)
{
Score* score = _omr->score();
double sSpatium = score->spatium() * _scoreView->matrix().m11();
double spatium = _omr->spatium() * _matrix.m11();
double nx = x / sSpatium * spatium + xoff;
double ny = y / sSpatium * spatium + yoff;
double ox = _matrix.dx();
double oy = _matrix.dy();
_matrix.setMatrix(_matrix.m11(), _matrix.m12(), _matrix.m13(), _matrix.m21(),
_matrix.m22(), _matrix.m23(), nx, ny, _matrix.m33());
scroll(ox - nx, oy - ny, QRect(0, 0, width(), height()));
update();
}
//---------------------------------------------------------
// contextMenuEvent
//---------------------------------------------------------
void OmrView::contextMenuEvent(QContextMenuEvent*)
{
//printf("context menu\n");
}
//---------------------------------------------------------
// setShowBarlines
//---------------------------------------------------------
void OmrView::setShowBarlines(bool val)
{
_showBarlines = val;
update();
}
//---------------------------------------------------------
// setShowSlices
//---------------------------------------------------------
void OmrView::setShowSlices(bool val)
{
_showSlices = val;
update();
}
//---------------------------------------------------------
// setShowStaves
//---------------------------------------------------------
void OmrView::setShowStaves(bool val)
{
_showStaves = val;
update();
}
}

View file

@ -1,112 +0,0 @@
//=============================================================================
// MusE Reader
// Linux Music Score Reader
//
// Copyright (C) 2010 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.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef __SCAN_VIEW_H__
#define __SCAN_VIEW_H__
namespace Ms {
class Omr;
class Page;
class ScoreView;
class OmrPage;
//---------------------------------------------------------
// Tile
//---------------------------------------------------------
struct Tile {
int no;
QRect r;
QPixmap pm;
OmrPage* page;
int pageNo;
Tile();
};
static const int TILE_H = 512;
static const int TILE_W = 512;
//---------------------------------------------------------
// OmrView
//---------------------------------------------------------
class OmrView : public QWidget
{
Q_OBJECT
Omr * _omr;
ScoreView* _scoreView;
int maxTiles;
QList<Tile*> usedTiles;
QStack<Tile*> freeTiles;
QPoint startDrag;
QTransform _matrix;
int xoff, yoff;
int pageWidth;
bool _fotoMode;
QRectF _foto;
bool _showLines;
bool _showBarlines;
bool _showSlices;
bool _showStaves;
void zoom(int step, const QPoint& pos);
virtual void mousePressEvent(QMouseEvent*);
virtual void mouseMoveEvent(QMouseEvent*);
virtual void wheelEvent(QWheelEvent*);
virtual void paintEvent(QPaintEvent*);
virtual void contextMenuEvent(QContextMenuEvent*);
qreal mag() const { return _matrix.m11(); }
void setMag(double mag);
void initTile(Tile* t);
public slots:
void setScale(double);
void setOffset(double, double);
signals:
void pageNumberChanged(int);
void xPosChanged(int);
void yPosChanged(int);
public:
OmrView(ScoreView*, QWidget* parent = 0);
void setOmr(Omr*);
Omr* omr() const { return _omr; }
bool fotoMode() const { return _fotoMode; }
void setFotoMode(bool val) { _fotoMode = val; }
void setShowLines(bool val) { _showLines = val; }
bool showLines() const { return _showLines; }
bool showBarlines() const { return _showBarlines; }
bool showSlices() const { return _showSlices; }
bool showStaves() const { return _showStaves; }
void setShowBarlines(bool val);
void setShowSlices(bool val);
void setShowStaves(bool val);
};
}
#endif

View file

@ -1,264 +0,0 @@
//=============================================================================
// MusE Reader
// Music Score Reader
//
// 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.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "pattern.h"
#include "utils.h"
#include "libmscore/sym.h"
#include "omr.h"
#include <math.h>
namespace Ms {
//---------------------------------------------------------
// Pattern
//---------------------------------------------------------
Pattern::Pattern()
{
}
Pattern::~Pattern()
{
#if 0
for (int i = 0; i < rows; ++i) {
delete []model[i];
}
delete []model;
#endif
}
//---------------------------------------------------------
// patternMatch
// compare two patterns for similarity
// return:
// 1.0 - identical
// 0.5 - 50% of all pixel match
// 0.0 - no match
//---------------------------------------------------------
double Pattern::match(const Pattern* a) const
{
int n = image()->byteCount();
if (n != a->image()->byteCount()) {
return 0.0;
}
int k = 0;
const uchar* p1 = image()->bits();
const uchar* p2 = a->image()->bits();
for (int i = 0; i < n; ++i) {
uchar v = (*(p1++)) ^ (*(p2++));
k += Omr::bitsSetTable[v];
}
return 1.0 - (double(k) / (h() * w()));
}
double Pattern::match(const QImage*, int, int) const
{
//QImage *image, int col, int row
return 0.0;
}
double Pattern::match(const QImage* img, int col, int row, double bg_parm) const
{
#if 0
double scr = 0;
for (int y = 0; y < rows; ++y) {
for (int x = 0; x < cols; x++) {
if (col + x >= img->size().width() || row + y >= img->size().height()) {
continue;
}
QRgb c = img->pixel(col + x, row + y);
bool black = (qGray(c) < 125);
scr += black ? 1 : 0;
}
}
return scr;
#endif
double k = 0;
//return k;
if (bg_parm < 0.00001) {
bg_parm = 0.00001;
}
if (bg_parm > 0.99999) {
bg_parm = 0.99999;
}
double log_bg_black = log(bg_parm);
double log_bg_white = log(1.0 - bg_parm);
for (int y = 0; y < rows; ++y) {
for (int x = 0; x < cols; x++) {
if (col + x >= img->size().width() || row + y >= img->size().height()) {
continue;
}
QRgb c = img->pixel(col + x, row + y);
bool black = (qGray(c) < 125);
double bs_scr = model[y][x];
if (bs_scr < 0.00001) {
bs_scr = 0.00001;
}
if (bs_scr > 0.99999) {
bs_scr = 0.99999;
}
double log_black = log(bs_scr) - log_bg_black;
double log_white = log(1.0 - bs_scr) - log_bg_white;
k += black ? log_black : log_white;
}
}
return k;
#if 0
for (int x = 0; x < bytes; ++x) {
uchar a = *p1++;
uchar b1 = *p2;
uchar b2 = *(p2 + 1);
p2++;
uchar b = (b1 >> shift) | (b2 << (7 - shift));
uchar v = a ^ b;
k += Omr::bitsSetTable[v];
}
uchar a = *p1++;
uchar b1 = *p2;
uchar b2 = *(p2 + 1) & (0xff << eshift);
uchar b = (b1 >> shift) | (b2 << (7 - shift));
uchar v = a ^ b;
k += Omr::bitsSetTable[v];
#endif
}
//---------------------------------------------------------
// Pattern
// create a Pattern from symbol
//---------------------------------------------------------
Pattern::Pattern(Score* s, SymId id, double spatium)
{
_score = s;
_id = id;
QFont f("Bravura");
f.setPixelSize(lrint(spatium * 4));
QFontMetrics fm(f);
QRectF r = _score->scoreFont()->bbox(id, 9.0);
int _w = r.right() - r.left() + 2;
int _h = ((r.height() + 1) / 2) * 2;
_base = QPoint(-r.left(), -r.top());
_image = QImage(_w, _h, QImage::Format_MonoLSB);
QVector<QRgb> ct(2);
ct[0] = qRgb(255, 255, 255);
ct[1] = qRgb(0, 0, 0);
_image.setColorTable(ct);
_image.fill(0);
QPainter painter;
painter.begin(&_image);
painter.setFont(f);
painter.drawText(-r.left() + 1, -r.y(), _score->scoreFont()->toString(id));
painter.end();
int ww = _w % 32;
if (ww == 0) {
return;
}
uint mask = 0xffffffff << ww;
int n = ((_w + 31) / 32) - 1;
for (int i = 0; i < _h; ++i) {
uint* p = ((uint*)_image.scanLine(i)) + n;
*p = ((*p) & ~mask);
}
}
//---------------------------------------------------------
// Pattern
// create a Pattern from symbol name
//---------------------------------------------------------
Pattern::Pattern(Score* s, QString name)
{
_score = s;
QFile f(QString(":/data/%1.dat").arg(name));
if (!f.open(QIODevice::ReadOnly)) {
rows = 0;
cols = 0;
} else {
QTextStream in(&f);
in >> rows >> cols;
model = new float*[rows];
for (int i = 0; i < rows; i++) {
model[i] = new float[cols];
}
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
in >> model[i][j];
}
}
}
f.close();
}
//---------------------------------------------------------
// Pattern
// create a Pattern from image
//---------------------------------------------------------
Pattern::Pattern(QImage* img, int x, int y, int w, int h)
{
_image = img->copy(x, y, w, h);
int ww = w % 32;
if (ww == 0) {
return;
}
uint mask = 0xffffffff << ww;
int n = ((w + 31) / 32) - 1;
for (int i = 0; i < h; ++i) {
uint* p = ((uint*)_image.scanLine(i)) + n;
*p &= ~mask;
}
}
//---------------------------------------------------------
// dump
//---------------------------------------------------------
void Pattern::dump() const
{
printf("pattern %d x %d\n", _image.width(), _image.height());
for (int y = 0; y < _image.height(); ++y) {
for (int x = 0; x < _image.width(); ++x) {
QRgb pixel = _image.pixel(x, y);
printf("%c", pixel & 0xffffff ? '-' : '*');
}
printf("\n");
}
}
//---------------------------------------------------------
// dot
//---------------------------------------------------------
bool Pattern::dot(int x, int y) const
{
const uint* p = (const uint*)_image.scanLine(y) + (x / 32);
return (*p) & (0x1 << (x % 32));
}
}

View file

@ -1,68 +0,0 @@
//=============================================================================
// MusE Reader
// Music Score Reader
//
// Copyright (C) 2010 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.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef __PATTERN_H__
#define __PATTERN_H__
#include "libmscore/score.h"
namespace Ms {
enum class SymId;
class Sym;
//---------------------------------------------------------
// Pattern
// _n % sizeof(int) is zero, patterns are 32bit padded
//---------------------------------------------------------
class Pattern
{
protected:
QImage _image;
SymId _id;
QPoint _base;
Score* _score;
float** model;
int rows;
int cols;
public:
Pattern();
~Pattern();
Pattern(Score* s, SymId id, double spatium);
Pattern(Score* s, QString name);
Pattern(QImage*, int, int, int, int);
double match(const Pattern*) const;
double match(const QImage*, int, int) const;
double match(const QImage* img, int col, int row, double bg_parm) const;
void dump() const;
const QImage* image() const { return &_image; }
int w() const { return cols; /*_image.width();*/ }
int h() const { return rows; /*_image.height();*/ }
bool dot(int x, int y) const;
SymId id() const { return _id; }
void setId(SymId val) { _id = val; }
const QPoint& base() const { return _base; }
void setBase(const QPoint& v) { _base = v; }
};
}
#endif

View file

@ -1,151 +0,0 @@
//=============================================================================
// MusE Reader
// Music Score Reader
//
// Copyright (C) 2010 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.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "pdf.h"
namespace Ms {
int Pdf::references;
//---------------------------------------------------------
// numPages
//---------------------------------------------------------
int Pdf::numPages() const
{
return _document->numPages();
}
//---------------------------------------------------------
// Pdf
//---------------------------------------------------------
Pdf::Pdf()
{
++references;
}
//---------------------------------------------------------
// open
//---------------------------------------------------------
bool Pdf::open(const QString& path)
{
_document = Poppler::Document::load(path);
if (!_document || _document->isLocked()) {
delete _document;
return false;
}
return true;
}
//---------------------------------------------------------
// ~Pdf
//---------------------------------------------------------
Pdf::~Pdf()
{
if (_document) {
delete(_document);
}
--references;
}
//---------------------------------------------------------
// binarization
//---------------------------------------------------------
QImage Pdf::binarization(QImage image)
{
QImage bw = QImage(image.width(), image.height(), QImage::Format_MonoLSB);
QVector<QRgb> ct(2);
ct[0] = qRgb(255, 255, 255);
ct[1] = qRgb(0, 0, 0);
bw.setColorTable(ct);
bw.fill(0);
float thresh = 128;
float new_thresh = 0;
while (thresh != new_thresh) {
float sum_black = 0;
float sum_white = 0;
int num_black = 0;
int num_white = 0;
new_thresh = thresh;
for (int x = 0; x < image.width(); x++) {
for (int y = 0; y < image.height(); y++) {
QRgb c = image.pixel(x, y);
float g = qGray(c);
if (g < thresh) {
sum_black += g;
num_black++;
} else {
sum_white += g;
num_white++;
}
}
}
thresh = (sum_black / num_black + sum_white / num_white) / 2.0;
}
int stride = (bw.width() + 7) / 8;
uchar* p = bw.bits();
for (int y = 0; y < bw.height(); ++y) {
p = bw.scanLine(y);
for (int x = 0; x < stride; ++x) {
int temp = 0;
for (int i = 0; i < 8; i++) {
if (x * 8 + i >= bw.width()) {
continue;
}
QRgb c = image.pixel(x * 8 + i, y);
float g = qGray(c);
temp += ((g < thresh) ? 1 : 0) << i;
}
*p++ = temp;
}
}
return bw;
}
//---------------------------------------------------------
// page
//---------------------------------------------------------
QImage Pdf::page(int i)
{
QImage image;
// Paranoid safety check
if (_document == 0) {
return image;
}
Poppler::Page* pdfPage = _document->page(i); // Document starts at page 0
if (pdfPage == 0) {
return image;
}
QSize size = pdfPage->pageSize();
float scale = 2.0;
// the size can be decided more intelligently
image = pdfPage->renderToImage(scale * 72.0, scale * 72.0, 0, 0, scale * size.width(), scale * size.height());
delete pdfPage;
return binarization(image);
}
}

View file

@ -1,50 +0,0 @@
//=============================================================================
// MusE Reader
// Music Score Reader
//
// Copyright (C) 2010 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.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef __PDF_H__
#define __PDF_H__
#include "qt5/poppler-qt5.h"
class PDFDoc;
class QImageOutputDev;
namespace Ms {
//---------------------------------------------------------
// Pdf
//---------------------------------------------------------
class Pdf
{
static int references;
PDFDoc* _doc;
QImageOutputDev* imgOut;
Poppler::Document* _document;
public:
Pdf();
bool open(const QString& path);
~Pdf();
int numPages() const;
QImage page(int);
QImage binarization(QImage image);
};
}
#endif

View file

@ -1,189 +0,0 @@
//=============================================================================
// MusE Reader
// Music Score Reader
//
// Copyright (C) 2010 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.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "image.h"
#include "utils.h"
#include "omr.h"
#include "omrpage.h"
namespace Ms {
//=============================================================================
// inspired by ImageMagick (http://www.imagemagick.org)
//=============================================================================
// imageSkew() calculates skew of image. Skew is an artifact that
// occurs in scanned images because of the camera being misaligned,
// imperfections in the scanning or surface, or simply because the paper was
// not placed completely flat when scanned.
//
// The format of the imageSkew method is:
//
// double imageSkew(const QImage *image)
//
// Benchmark 7.3sec test2 first page
// 6
// 5.7
// 5.3
// 3.74
// 3.30
// 0.47sec RELEASE
#define MyPI 3.14159265358979323846264338327950288419716939937510
//---------------------------------------------------------
// RadiansToDegrees
//---------------------------------------------------------
static inline double RadiansToDegrees(double r)
{
return 180.0 * r / MyPI;
}
//---------------------------------------------------------
// RadonInfo
//---------------------------------------------------------
class RadonInfo
{
int size;
public:
ushort* cells;
int width, height;
RadonInfo(ulong w, ulong h)
{
width = w;
height = h;
size = w * h;
cells = new ushort[size];
}
~RadonInfo() { delete[] cells; }
void reset() { memset(cells, 0, size * sizeof(*cells)); }
ushort getCell(int x, int y) const { return cells[height * x + y]; }
void setCell(int x, int y, ushort value) { cells[height * x + y] = value; }
};
//---------------------------------------------------------
// radonProjection
//---------------------------------------------------------
static void radonProjection(RadonInfo* src, RadonInfo* dst, int sign, ulong* projection)
{
RadonInfo* p = src;
RadonInfo* q = dst;
for (int step = 1; step < p->width; step *= 2) {
for (int x = 0; x < p->width; x += 2 * step) {
for (int i = 0; i < step; i++) {
int y;
for (y = 0; y < (p->height - i - 1); y++) {
ushort cell = p->getCell(x + i, y);
q->setCell(x + 2 * i, y, cell + p->getCell(x + i + step, y + i));
q->setCell(x + 2 * i + 1, y, cell + p->getCell(x + i + step, y + i + 1));
}
for (; y < (p->height - i); y++) {
ushort cell = p->getCell(x + i, y);
q->setCell(x + 2 * i, y, cell + p->getCell(x + i + step, y + i));
q->setCell(x + 2 * i + 1, y, cell);
}
for (; y < p->height; y++) {
ushort cell = p->getCell(x + i, y);
q->setCell(x + 2 * i, y, cell);
q->setCell(x + 2 * i + 1, y, cell);
}
}
}
RadonInfo* swap = p;
p = q;
q = swap;
}
for (int x = 0; x < p->width; x++) {
uint sum = 0;
for (int y = 0; y < (p->height - 1); y++) {
int delta = p->getCell(x, y) - p->getCell(x, y + 1);
sum += delta * delta;
}
projection[p->width + sign * x - 1] = sum;
}
}
//---------------------------------------------------------
// radonTransform
//---------------------------------------------------------
void OmrPage::radonTransform(ulong* projection, int w, int n, const QRect& r)
{
int h = r.height();
RadonInfo* src = new RadonInfo(w, h);
RadonInfo* dst = new RadonInfo(w, h);
src->reset();
for (int y = 0; y < h; y++) {
int i = n;
const uchar* p = (const uchar*)scanLine(r.y() + y);
for (int x = 0; x < n; ++x) {
src->setCell(--i, y, Omr::bitsSetTable[*p++]);
}
}
radonProjection(src, dst, -1, projection);
src->reset();
for (int y = 0; y < h; y++) {
const uchar* p = (const uchar*)scanLine(r.y() + y);
for (int x = 0; x < n; ++x) {
src->setCell(x, y, Omr::bitsSetTable[*p++]);
}
}
radonProjection(src, dst, 1, projection);
delete dst;
delete src;
}
//---------------------------------------------------------
// skew
// compute image skew angle
//---------------------------------------------------------
double OmrPage::skew(const QRect& r)
{
// Benchmark bench("imageSkew");
int nn = wordsPerLine() * 4;
int width = 1;
for (; width < nn; width <<= 1) {
}
int n = 2 * width - 1;
ulong* projection = new ulong[n];
radonTransform(projection, width, nn, r);
uint max_projection = 0;
int skew = 0;
for (int i = 0; i < n; i++) {
if (projection[i] > max_projection) {
skew = i - width + 1;
max_projection = projection[i];
}
}
delete[] projection;
return RadiansToDegrees(-atan((double)skew / width / 8));
}
}

View file

@ -1,87 +0,0 @@
//=============================================================================
// MusE Reader
// Music Score Reader
//
// Copyright (C) 2010 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.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "utils.h"
#include "omr.h"
namespace Ms {
char Omr::bitsSetTable[256];
//---------------------------------------------------------
// initUtils
//---------------------------------------------------------
void Omr::initUtils()
{
static bool initialized = false;
if (initialized) {
return;
}
initialized = true;
//
// populate the bitsSetTable
bitsSetTable[0] = 0;
for (int i = 1; i < 256; i++) {
bitsSetTable[i] = (i & 1) + bitsSetTable[i / 2];
}
}
//---------------------------------------------------------
// mean
// Compute the arithmetic mean of a dataset using the
// recurrence relation
// mean_(n) = mean(n-1) + (data[n] - mean(n-1))/(n+1)
//---------------------------------------------------------
double mean(const double data[], int size)
{
long double mean = 0;
for (int i = 0; i < size; i++) {
mean += (data[i] - mean) / (i + 1);
}
return mean;
}
//---------------------------------------------------------
// covariance
//---------------------------------------------------------
double covariance(const double data1[],
const double data2[], int n, double mean1, double mean2)
{
long double covariance = 0.0;
/* find the sum of the squares */
for (size_t i = 0; i < (size_t)n; i++) {
const long double delta1 = (data1[i] - mean1);
const long double delta2 = (data2[i] - mean2);
covariance += (delta1 * delta2 - covariance) / (i + 1);
}
return covariance;
}
double covariance(const double data1[], const double data2[], int n)
{
double mean1 = mean(data1, n);
double mean2 = mean(data2, n);
return covariance(data1, data2, n, mean1, mean2);
}
}

View file

@ -1,53 +0,0 @@
//=============================================================================
// MusE Reader
// Linux Music Score Reader
//
// Copyright (C) 2010 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.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef __UTILS_H__
#define __UTILS_H__
namespace Ms {
extern double curTime();
//---------------------------------------------------------
// Benchmark
//---------------------------------------------------------
class Benchmark
{
double startTime;
const char* msg;
public:
Benchmark(const char* p)
{
msg = p;
startTime = curTime();
//printf("===%s start\n", msg);
}
~Benchmark()
{
//double elapsed = curTime() - startTime;
//printf("===%s elapsed %f\n", msg, elapsed);
}
};
extern double covariance(const double data1[], const double data2[], int n);
}
#endif

View file

@ -1,174 +0,0 @@
add_library(poppler-qt5 STATIC
poppler/Annot.cc
poppler/Array.cc
poppler/BuiltinFont.cc
poppler/BuiltinFontTables.cc
poppler/CachedFile.cc
poppler/Catalog.cc
poppler/CharCodeToUnicode.cc
poppler/CMap.cc
poppler/DateInfo.cc
poppler/Decrypt.cc
poppler/Dict.cc
poppler/Error.cc
poppler/FileSpec.cc
poppler/FontEncodingTables.cc
poppler/Form.cc
poppler/FontInfo.cc
poppler/Function.cc
poppler/Gfx.cc
poppler/GfxFont.cc
poppler/GfxState.cc
poppler/GlobalParams.cc
poppler/Hints.cc
poppler/JArithmeticDecoder.cc
poppler/JBIG2Stream.cc
poppler/JPXStream.cc
poppler/Lexer.cc
poppler/Linearization.cc
poppler/Link.cc
poppler/LocalPDFDocBuilder.cc
poppler/MarkedContentOutputDev.cc
poppler/Movie.cc
poppler/NameToCharCode.cc
poppler/Object.cc
poppler/OptionalContent.cc
poppler/Outline.cc
poppler/OutputDev.cc
poppler/Page.cc
poppler/PageLabelInfo.h
poppler/PageLabelInfo.cc
poppler/PageTransition.cc
poppler/Parser.cc
poppler/PDFDoc.cc
poppler/PDFDocEncoding.cc
poppler/PDFDocFactory.cc
poppler/PopplerCache.cc
poppler/PreScanOutputDev.cc
poppler/ProfileData.cc
poppler/PSOutputDev.cc
poppler/PSTokenizer.cc
poppler/Rendition.cc
poppler/SecurityHandler.cc
poppler/SignatureInfo.cc
poppler/Sound.cc
poppler/SplashOutputDev.cc
poppler/StdinCachedFile.cc
poppler/StdinPDFDocBuilder.cc
poppler/Stream.cc
poppler/strtok_r.cpp
poppler/StructElement.cc
poppler/StructTreeRoot.cc
poppler/TextOutputDev.cc
poppler/UnicodeMap.cc
poppler/UnicodeTypeTable.cc
poppler/UTF.cc
poppler/ViewerPreferences.cc
poppler/XRef.cc
goo/FixedPoint.cc
goo/gfile.cc
goo/gmem.cc
goo/gmempp.cc
goo/GooHash.cc
goo/GooList.cc
goo/GooString.cc
goo/GooTimer.cc
goo/grandom.cc
goo/gstrtod.cc
goo/ImgWriter.cc
goo/JpegWriter.cc
goo/NetPBMWriter.cc
goo/PNGWriter.cc
goo/TiffWriter.cc
goo/glibc.cc
fofi/FoFiBase.cc
fofi/FoFiEncodings.cc
fofi/FoFiIdentifier.cc
fofi/FoFiTrueType.cc
fofi/FoFiType1.cc
fofi/FoFiType1C.cc
splash/Splash.cc
splash/SplashBitmap.cc
splash/SplashClip.cc
splash/SplashFont.cc
splash/SplashFontEngine.cc
splash/SplashFontFile.cc
splash/SplashFontFileID.cc
splash/SplashFTFont.cc
splash/SplashFTFontEngine.cc
splash/SplashFTFontFile.cc
splash/SplashPath.cc
splash/SplashPattern.cc
splash/SplashScreen.cc
splash/SplashState.cc
splash/SplashT1Font.cc
splash/SplashT1FontEngine.cc
splash/SplashT1FontFile.cc
splash/SplashXPath.cc
splash/SplashXPathScanner.cc
qt5/ArthurOutputDev.cc
qt5/poppler-annotation.cc
qt5/poppler-base-converter.cc
qt5/poppler-document.cc
qt5/poppler-embeddedfile.cc
qt5/poppler-fontinfo.cc
qt5/poppler-form.cc
qt5/poppler-link-extractor.cc
qt5/poppler-link.cc
qt5/poppler-media.cc
qt5/poppler-movie.cc
qt5/poppler-optcontent.cc
qt5/poppler-page-transition.cc
qt5/poppler-page.cc
qt5/poppler-pdf-converter.cc
qt5/poppler-private.cc
qt5/poppler-ps-converter.cc
qt5/poppler-qiodeviceoutstream.cc
qt5/poppler-sound.cc
qt5/poppler-textbox.cc
)
if (APPLE)
set ( POPPLER_COMPILE_FLAGS "-O2 -Wno-unknown-warning-option -Wno-write-strings -ansi -Wnon-virtual-dtor -Woverloaded-virtual -Wno-unused-private-field -Wno-return-stack-address -Wno-shift-negative-value -std=c++11")
else (APPLE)
if (MINGW)
if (BUILD_64)
set (POPPLER_COMPILE_FLAGS "-O2 -Wall -Wextra -Wno-write-strings -ansi -Wnon-virtual-dtor -Woverloaded-virtual -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-but-set-variable -Wno-format -Wno-shift-negative-value -Wno-stringop-overflow -std=c++11")
else (BUILD_64)
set (POPPLER_COMPILE_FLAGS "-O2 -Wall -Wextra -Wno-write-strings -ansi -Wnon-virtual-dtor -Woverloaded-virtual -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-but-set-variable -Wno-format -std=c++11")
endif (BUILD_64)
else (MINGW)
if (NOT MSVC)
set (POPPLER_COMPILE_FLAGS "-O2 -Wno-write-strings -ansi -Wnon-virtual-dtor -Woverloaded-virtual -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-but-set-variable -std=c++11")
else (NOT MSVC)
# For MSVC:
# -O2: controls optimization, not compatible with global options
# -ansi & -std=c++11 -> gloablly set /std:c++14 should take care.
# -Wno-write-strings -> ???
# -Wno-unused-parameter -> Warning C4100: 'identifier' : unreferenced formal parameter
# -Wnon-virtual-dtor -> /Wall enabled all warnings, no need to enable particularly (Warning C4265: 'classname': class has virtual functions, but destructor is not virtual\n instances of this class may not be destructed correctly)
# -Woverloaded-virtual -> /Wall enabled all warnings, no need to enable particularly
# -Wno-missing-field-initializers -> ???
# -Wno-unused-but-set-variable -> Warning C4189: 'identifier': local variable is initialized but not referenced
set (POPPLER_COMPILE_FLAGS "/wd4065 /wd4100 /wd4121 /wd4127 /wd4189 /wd4244 /wd4245 /wd4310 /wd4255 /wd4267 /wd4309 /wd4334 /wd4456 /wd4458 /wd4459 /wd4701 /wd4702 /wd4703 /wd4706 /wd4805 /wd4828 /wd4996")
endif (NOT MSVC)
endif(MINGW)
endif(APPLE)
set_target_properties(poppler-qt5
PROPERTIES
COMPILE_FLAGS
${POPPLER_COMPILE_FLAGS}
)
include_directories(
${PROJECT_SOURCE_DIR}/thirdparty/poppler/goo
${PROJECT_SOURCE_DIR}/thirdparty/poppler/fofi
${PROJECT_SOURCE_DIR}/thirdparty/poppler/splash
${PROJECT_SOURCE_DIR}/thirdparty/poppler/qt5
)

View file

@ -1,295 +0,0 @@
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define if building universal (internal helper macro) */
/* #undef AC_APPLE_UNIVERSAL_BUILD */
/* Build against libcurl. */
/* #undef ENABLE_LIBCURL */
/* Use libjpeg instead of builtin jpeg decoder. */
/* #undef ENABLE_LIBJPEG */
/* Use libopenjpeg instead of builtin jpeg2000 decoder. */
#define ENABLE_LIBOPENJPEG 1
/* Build against libpng. */
/* #undef ENABLE_LIBPNG */
/* Build against libtiff. */
/* #undef ENABLE_LIBTIFF */
/* Build Poppler against NSS for digital signature support. */
/* #undef ENABLE_NSS3 */
/* Do not hardcode the library location */
/* #undef ENABLE_RELOCATABLE */
/* Build against zlib. */
/* #undef ENABLE_ZLIB */
/* Use zlib instead of builtin zlib decoder to uncompress flate streams. */
/* #undef ENABLE_ZLIB_UNCOMPRESS */
/* Use cairo for rendering. */
/* #undef HAVE_CAIRO */
/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
*/
#define HAVE_DIRENT_H 1
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
/* Define to 1 if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
/* Have FreeType2 include files */
#define HAVE_FREETYPE_H 1
/* Define to 1 if you have the `fseek64' function. */
/* #undef HAVE_FSEEK64 */
/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
#if (!defined (_MSCVER) && !defined (_MSC_VER))
// MSVC does not have fseeko/ftello. Might be uncommented if an implementation is added.
#define HAVE_FSEEKO 1
#endif
/* Define to 1 if you have the `ftell64' function. */
/* #undef HAVE_FTELL64 */
/* Defines if gettimeofday is available on your system */
#define HAVE_GETTIMEOFDAY 1
/* Defines if gmtime_r is available on your system */
/* #undef HAVE_GMTIME_R 1*/
/* Define if you have the iconv() function and it works. */
#define HAVE_ICONV 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the `tiff' library (-ltiff). */
/* #undef HAVE_LIBTIFF */
/* Define to 1 if you have the `z' library (-lz). */
/* #undef HAVE_LIBZ */
/* Defines if localtime_r is available on your system */
#define HAVE_LOCALTIME_R 1
/* Define to 1 if you have the `lseek64' function. */
/* #undef HAVE_LSEEK64 */
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the `mkstemp' function. */
#define HAVE_MKSTEMP 1
/* Define to 1 if you have the `mkstemps' function. */
#define HAVE_MKSTEMPS 1
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
/* #undef HAVE_NDIR_H */
/* Define to 1 if you have the <openjpeg.h> header file. */
/* #undef HAVE_OPENJPEG_H */
/* Define to 1 if you have the `popen' function. */
#define HAVE_POPEN 1
/* Define to 1 if you have the `pread64' function. */
/* #undef HAVE_PREAD64 */
/* Define if you have POSIX threads libraries and header files. */
#define HAVE_PTHREAD 1
/* Have PTHREAD_PRIO_INHERIT. */
#define HAVE_PTHREAD_PRIO_INHERIT 1
/* Defines if rand_r is available on your system */
/* #undef HAVE_RAND_R 1*/
/* Use splash for rendering. */
#define HAVE_SPLASH 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the `strcat_s' function. */
/* #undef HAVE_STRCAT_S */
/* Define to 1 if you have the `strcpy_s' function. */
/* #undef HAVE_STRCPY_S */
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
*/
/* #undef HAVE_SYS_DIR_H */
/* Define to 1 if you have the <sys/mman.h> header file. */
/* #undef HAVE_SYS_MMAN_H */
/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
*/
/* #undef HAVE_SYS_NDIR_H */
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <tiffio.h> header file. */
/* #undef HAVE_TIFFIO_H */
/* Define to 1 if you have the <unistd.h> header file. */
#if (!defined (_MSCVER) && !defined (_MSC_VER))
// MSVC does not have <unistd.h>. Might be uncommented if an implementation is added.
#define HAVE_UNISTD_H 1
#endif
/* Define to 1 if you have the <zlib.h> header file. */
#define HAVE_ZLIB_H 1
/* Define as const if the declaration of iconv() needs const. */
#define ICONV_CONST
/* Define to the sub-directory where libtool stores uninstalled libraries. */
#define LT_OBJDIR ".libs/"
/* Enable multithreading support. */
#define MULTITHREADED 1
/* Generate OPI comments in PS output. */
#define OPI_SUPPORT 1
/* Name of package */
#define PACKAGE "poppler"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "https://bugs.freedesktop.org/enter_bug.cgi?product=poppler"
/* Define to the full name of this package. */
#define PACKAGE_NAME "poppler"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "poppler 0.45.0"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "poppler"
/* Define to the home page for this package. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "0.45.0"
/* Poppler data dir */
#define POPPLER_DATADIR "/opt/local/share/poppler"
/* Support for curl based doc builder is compiled in. */
/* #undef POPPLER_HAS_CURL_SUPPORT */
/* Defines the poppler version */
//#define POPPLER_VERSION "0.45.0"
/* Define to necessary symbol if this constant uses a non-standard name on
your system. */
/* #undef PTHREAD_CREATE_JOINABLE */
/* Include support for CMYK rasterization */
/* #undef SPLASH_CMYK */
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Enable word list support. */
#define TEXTOUT_WORD_LIST 1
/* Defines if use cms */
/* #undef USE_CMS */
/* Use fixed point arithmetic in the Splash backend */
/* #undef USE_FIXEDPOINT */
/* Use single precision arithmetic in the Splash backend */
/* #undef USE_FLOAT */
/* Defines if use lcms1 */
/* #undef USE_LCMS1 */
/* Defined if using openjpeg1 */
#define USE_OPENJPEG1 1
/* Defined if using openjpeg2 */
/* #undef USE_OPENJPEG2 */
/* Version number of package */
#define VERSION "0.45.0"
/* Use fontconfig font configuration backend */
/* #undef WITH_FONTCONFIGURATION_FONTCONFIG */
/* Use win32 font configuration backend */
/* #undef WITH_FONTCONFIGURATION_WIN32 */
/* OpenJPEG with the OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG flag. */
#define WITH_OPENJPEG_IGNORE_PCLR_CMAP_CDEF_FLAG 1
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD
# if defined __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
# endif
#else
# ifndef WORDS_BIGENDIAN
/* # undef WORDS_BIGENDIAN */
# endif
#endif
/* Define to 1 if the X Window System is missing or not being used. */
/* #undef X_DISPLAY_MISSING */
/*
* jpeg.h needs HAVE_BOOLEAN, when the system uses boolean in system
* headers and I'm too lazy to write a configure test as long as only
* unixware is related
*/
#ifdef _UNIXWARE
#define HAVE_BOOLEAN
#endif
/* Enable large inode numbers on Mac OS X 10.5. */
#ifndef _DARWIN_USE_64_BIT_INODE
# define _DARWIN_USE_64_BIT_INODE 1
#endif
/* Number of bits in a file offset, on hosts where this is settable. */
/* #undef _FILE_OFFSET_BITS */
/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
/* #undef _LARGEFILE_SOURCE */
/* Define for large files, on AIX-style hosts. */
/* #undef _LARGE_FILES */
#if (defined (_MSCVER) || defined (_MSC_VER))
// Undefine UNICODE for MSVC to get the char-based library functions
#ifdef UNICODE
#undef UNICODE
#endif
#endif

View file

@ -1,201 +0,0 @@
//========================================================================
//
// FoFiBase.cc
//
// Copyright 1999-2003 Glyph & Cog, LLC
//
//========================================================================
//========================================================================
//
// Modified under the Poppler project - http://poppler.freedesktop.org
//
// All changes made under the Poppler project to this file are licensed
// under GPL version 2 or later
//
// Copyright (C) 2008 Ed Avis <eda@waniasset.com>
// Copyright (C) 2011 Jim Meyering <jim@meyering.net>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
//
//========================================================================
#include <config.h>
#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
#include <stdio.h>
#include <limits.h>
#include "goo/gmem.h"
#include "poppler/Error.h"
#include "FoFiBase.h"
//------------------------------------------------------------------------
// FoFiBase
//------------------------------------------------------------------------
FoFiBase::FoFiBase(char *fileA, int lenA, GBool freeFileDataA) {
fileData = file = (Guchar *)fileA;
len = lenA;
freeFileData = freeFileDataA;
}
FoFiBase::~FoFiBase() {
if (freeFileData) {
gfree(fileData);
}
}
char *FoFiBase::readFile(char *fileName, int *fileLen) {
FILE *f;
char *buf;
int n;
if (!(f = fopen(fileName, "rb"))) {
error(errIO, -1, "Cannot open '{0:s}'", fileName);
return NULL;
}
if (fseek(f, 0, SEEK_END) != 0) {
error(errIO, -1, "Cannot seek to end of '{0:s}'", fileName);
fclose(f);
return NULL;
}
n = (int)ftell(f);
if (n < 0) {
error(errIO, -1, "Cannot determine length of '{0:s}'", fileName);
fclose(f);
return NULL;
}
if (fseek(f, 0, SEEK_SET) != 0) {
error(errIO, -1, "Cannot seek to start of '{0:s}'", fileName);
fclose(f);
return NULL;
}
buf = (char *)gmalloc(n);
if ((int)fread(buf, 1, n, f) != n) {
gfree(buf);
fclose(f);
return NULL;
}
fclose(f);
*fileLen = n;
return buf;
}
int FoFiBase::getS8(int pos, GBool *ok) {
int x;
if (pos < 0 || pos >= len) {
*ok = gFalse;
return 0;
}
x = file[pos];
if (x & 0x80) {
x |= ~0xff;
}
return x;
}
int FoFiBase::getU8(int pos, GBool *ok) {
if (pos < 0 || pos >= len) {
*ok = gFalse;
return 0;
}
return file[pos];
}
int FoFiBase::getS16BE(int pos, GBool *ok) {
int x;
if (pos < 0 || pos+1 >= len || pos > INT_MAX - 1) {
*ok = gFalse;
return 0;
}
x = file[pos];
x = (x << 8) + file[pos+1];
if (x & 0x8000) {
x |= ~0xffff;
}
return x;
}
int FoFiBase::getU16BE(int pos, GBool *ok) {
int x;
if (pos < 0 || pos+1 >= len || pos > INT_MAX - 1) {
*ok = gFalse;
return 0;
}
x = file[pos];
x = (x << 8) + file[pos+1];
return x;
}
int FoFiBase::getS32BE(int pos, GBool *ok) {
int x;
if (pos < 0 || pos+3 >= len || pos > INT_MAX - 3) {
*ok = gFalse;
return 0;
}
x = file[pos];
x = (x << 8) + file[pos+1];
x = (x << 8) + file[pos+2];
x = (x << 8) + file[pos+3];
if (x & 0x80000000) {
x |= ~0xffffffff;
}
return x;
}
Guint FoFiBase::getU32BE(int pos, GBool *ok) {
Guint x;
if (pos < 0 || pos+3 >= len || pos > INT_MAX - 3) {
*ok = gFalse;
return 0;
}
x = file[pos];
x = (x << 8) + file[pos+1];
x = (x << 8) + file[pos+2];
x = (x << 8) + file[pos+3];
return x;
}
Guint FoFiBase::getU32LE(int pos, GBool *ok) {
Guint x;
if (pos < 0 || pos+3 >= len || pos > INT_MAX - 3) {
*ok = gFalse;
return 0;
}
x = file[pos+3];
x = (x << 8) + file[pos+2];
x = (x << 8) + file[pos+1];
x = (x << 8) + file[pos];
return x;
}
Guint FoFiBase::getUVarBE(int pos, int size, GBool *ok) {
Guint x;
int i;
if (pos < 0 || pos + size > len || pos > INT_MAX - size) {
*ok = gFalse;
return 0;
}
x = 0;
for (i = 0; i < size; ++i) {
x = (x << 8) + file[pos + i];
}
return x;
}
GBool FoFiBase::checkRegion(int pos, int size) {
return pos >= 0 &&
pos + size >= pos &&
pos + size <= len;
}

View file

@ -1,56 +0,0 @@
//========================================================================
//
// FoFiBase.h
//
// Copyright 1999-2003 Glyph & Cog, LLC
//
//========================================================================
#ifndef FOFIBASE_H
#define FOFIBASE_H
#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
#include "goo/gtypes.h"
//------------------------------------------------------------------------
typedef void (*FoFiOutputFunc)(void *stream, const char *data, int len);
//------------------------------------------------------------------------
// FoFiBase
//------------------------------------------------------------------------
class FoFiBase {
public:
virtual ~FoFiBase();
protected:
FoFiBase(char *fileA, int lenA, GBool freeFileDataA);
static char *readFile(char *fileName, int *fileLen);
// S = signed / U = unsigned
// 8/16/32/Var = word length, in bytes
// BE = big endian
int getS8(int pos, GBool *ok);
int getU8(int pos, GBool *ok);
int getS16BE(int pos, GBool *ok);
int getU16BE(int pos, GBool *ok);
int getS32BE(int pos, GBool *ok);
Guint getU32BE(int pos, GBool *ok);
Guint getU32LE(int pos, GBool *ok);
Guint getUVarBE(int pos, int size, GBool *ok);
GBool checkRegion(int pos, int size);
Guchar *fileData;
Guchar *file;
int len;
GBool freeFileData;
};
#endif

View file

@ -1,994 +0,0 @@
//========================================================================
//
// FoFiEncodings.cc
//
// Copyright 1999-2003 Glyph & Cog, LLC
//
//========================================================================
#include <config.h>
#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
#include <stdlib.h>
#include "FoFiEncodings.h"
//------------------------------------------------------------------------
// Type 1 and 1C font data
//------------------------------------------------------------------------
const char *fofiType1StandardEncoding[256] = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
"space",
"exclam",
"quotedbl",
"numbersign",
"dollar",
"percent",
"ampersand",
"quoteright",
"parenleft",
"parenright",
"asterisk",
"plus",
"comma",
"hyphen",
"period",
"slash",
"zero",
"one",
"two",
"three",
"four",
"five",
"six",
"seven",
"eight",
"nine",
"colon",
"semicolon",
"less",
"equal",
"greater",
"question",
"at",
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z",
"bracketleft",
"backslash",
"bracketright",
"asciicircum",
"underscore",
"quoteleft",
"a",
"b",
"c",
"d",
"e",
"f",
"g",
"h",
"i",
"j",
"k",
"l",
"m",
"n",
"o",
"p",
"q",
"r",
"s",
"t",
"u",
"v",
"w",
"x",
"y",
"z",
"braceleft",
"bar",
"braceright",
"asciitilde",
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
"exclamdown",
"cent",
"sterling",
"fraction",
"yen",
"florin",
"section",
"currency",
"quotesingle",
"quotedblleft",
"guillemotleft",
"guilsinglleft",
"guilsinglright",
"fi",
"fl",
NULL,
"endash",
"dagger",
"daggerdbl",
"periodcentered",
NULL,
"paragraph",
"bullet",
"quotesinglbase",
"quotedblbase",
"quotedblright",
"guillemotright",
"ellipsis",
"perthousand",
NULL,
"questiondown",
NULL,
"grave",
"acute",
"circumflex",
"tilde",
"macron",
"breve",
"dotaccent",
"dieresis",
NULL,
"ring",
"cedilla",
NULL,
"hungarumlaut",
"ogonek",
"caron",
"emdash",
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
"AE",
NULL,
"ordfeminine",
NULL,
NULL,
NULL,
NULL,
"Lslash",
"Oslash",
"OE",
"ordmasculine",
NULL,
NULL,
NULL,
NULL,
NULL,
"ae",
NULL,
NULL,
NULL,
"dotlessi",
NULL,
NULL,
"lslash",
"oslash",
"oe",
"germandbls",
NULL,
NULL,
NULL,
NULL
};
const char *fofiType1ExpertEncoding[256] = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
"space",
"exclamsmall",
"Hungarumlautsmall",
NULL,
"dollaroldstyle",
"dollarsuperior",
"ampersandsmall",
"Acutesmall",
"parenleftsuperior",
"parenrightsuperior",
"twodotenleader",
"onedotenleader",
"comma",
"hyphen",
"period",
"fraction",
"zerooldstyle",
"oneoldstyle",
"twooldstyle",
"threeoldstyle",
"fouroldstyle",
"fiveoldstyle",
"sixoldstyle",
"sevenoldstyle",
"eightoldstyle",
"nineoldstyle",
"colon",
"semicolon",
"commasuperior",
"threequartersemdash",
"periodsuperior",
"questionsmall",
NULL,
"asuperior",
"bsuperior",
"centsuperior",
"dsuperior",
"esuperior",
NULL,
NULL,
NULL,
"isuperior",
NULL,
NULL,
"lsuperior",
"msuperior",
"nsuperior",
"osuperior",
NULL,
NULL,
"rsuperior",
"ssuperior",
"tsuperior",
NULL,
"ff",
"fi",
"fl",
"ffi",
"ffl",
"parenleftinferior",
NULL,
"parenrightinferior",
"Circumflexsmall",
"hyphensuperior",
"Gravesmall",
"Asmall",
"Bsmall",
"Csmall",
"Dsmall",
"Esmall",
"Fsmall",
"Gsmall",
"Hsmall",
"Ismall",
"Jsmall",
"Ksmall",
"Lsmall",
"Msmall",
"Nsmall",
"Osmall",
"Psmall",
"Qsmall",
"Rsmall",
"Ssmall",
"Tsmall",
"Usmall",
"Vsmall",
"Wsmall",
"Xsmall",
"Ysmall",
"Zsmall",
"colonmonetary",
"onefitted",
"rupiah",
"Tildesmall",
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
"exclamdownsmall",
"centoldstyle",
"Lslashsmall",
NULL,
NULL,
"Scaronsmall",
"Zcaronsmall",
"Dieresissmall",
"Brevesmall",
"Caronsmall",
NULL,
"Dotaccentsmall",
NULL,
NULL,
"Macronsmall",
NULL,
NULL,
"figuredash",
"hypheninferior",
NULL,
NULL,
"Ogoneksmall",
"Ringsmall",
"Cedillasmall",
NULL,
NULL,
NULL,
"onequarter",
"onehalf",
"threequarters",
"questiondownsmall",
"oneeighth",
"threeeighths",
"fiveeighths",
"seveneighths",
"onethird",
"twothirds",
NULL,
NULL,
"zerosuperior",
"onesuperior",
"twosuperior",
"threesuperior",
"foursuperior",
"fivesuperior",
"sixsuperior",
"sevensuperior",
"eightsuperior",
"ninesuperior",
"zeroinferior",
"oneinferior",
"twoinferior",
"threeinferior",
"fourinferior",
"fiveinferior",
"sixinferior",
"seveninferior",
"eightinferior",
"nineinferior",
"centinferior",
"dollarinferior",
"periodinferior",
"commainferior",
"Agravesmall",
"Aacutesmall",
"Acircumflexsmall",
"Atildesmall",
"Adieresissmall",
"Aringsmall",
"AEsmall",
"Ccedillasmall",
"Egravesmall",
"Eacutesmall",
"Ecircumflexsmall",
"Edieresissmall",
"Igravesmall",
"Iacutesmall",
"Icircumflexsmall",
"Idieresissmall",
"Ethsmall",
"Ntildesmall",
"Ogravesmall",
"Oacutesmall",
"Ocircumflexsmall",
"Otildesmall",
"Odieresissmall",
"OEsmall",
"Oslashsmall",
"Ugravesmall",
"Uacutesmall",
"Ucircumflexsmall",
"Udieresissmall",
"Yacutesmall",
"Thornsmall",
"Ydieresissmall"
};
//------------------------------------------------------------------------
// Type 1C font data
//------------------------------------------------------------------------
const char *fofiType1CStdStrings[391] = {
".notdef",
"space",
"exclam",
"quotedbl",
"numbersign",
"dollar",
"percent",
"ampersand",
"quoteright",
"parenleft",
"parenright",
"asterisk",
"plus",
"comma",
"hyphen",
"period",
"slash",
"zero",
"one",
"two",
"three",
"four",
"five",
"six",
"seven",
"eight",
"nine",
"colon",
"semicolon",
"less",
"equal",
"greater",
"question",
"at",
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z",
"bracketleft",
"backslash",
"bracketright",
"asciicircum",
"underscore",
"quoteleft",
"a",
"b",
"c",
"d",
"e",
"f",
"g",
"h",
"i",
"j",
"k",
"l",
"m",
"n",
"o",
"p",
"q",
"r",
"s",
"t",
"u",
"v",
"w",
"x",
"y",
"z",
"braceleft",
"bar",
"braceright",
"asciitilde",
"exclamdown",
"cent",
"sterling",
"fraction",
"yen",
"florin",
"section",
"currency",
"quotesingle",
"quotedblleft",
"guillemotleft",
"guilsinglleft",
"guilsinglright",
"fi",
"fl",
"endash",
"dagger",
"daggerdbl",
"periodcentered",
"paragraph",
"bullet",
"quotesinglbase",
"quotedblbase",
"quotedblright",
"guillemotright",
"ellipsis",
"perthousand",
"questiondown",
"grave",
"acute",
"circumflex",
"tilde",
"macron",
"breve",
"dotaccent",
"dieresis",
"ring",
"cedilla",
"hungarumlaut",
"ogonek",
"caron",
"emdash",
"AE",
"ordfeminine",
"Lslash",
"Oslash",
"OE",
"ordmasculine",
"ae",
"dotlessi",
"lslash",
"oslash",
"oe",
"germandbls",
"onesuperior",
"logicalnot",
"mu",
"trademark",
"Eth",
"onehalf",
"plusminus",
"Thorn",
"onequarter",
"divide",
"brokenbar",
"degree",
"thorn",
"threequarters",
"twosuperior",
"registered",
"minus",
"eth",
"multiply",
"threesuperior",
"copyright",
"Aacute",
"Acircumflex",
"Adieresis",
"Agrave",
"Aring",
"Atilde",
"Ccedilla",
"Eacute",
"Ecircumflex",
"Edieresis",
"Egrave",
"Iacute",
"Icircumflex",
"Idieresis",
"Igrave",
"Ntilde",
"Oacute",
"Ocircumflex",
"Odieresis",
"Ograve",
"Otilde",
"Scaron",
"Uacute",
"Ucircumflex",
"Udieresis",
"Ugrave",
"Yacute",
"Ydieresis",
"Zcaron",
"aacute",
"acircumflex",
"adieresis",
"agrave",
"aring",
"atilde",
"ccedilla",
"eacute",
"ecircumflex",
"edieresis",
"egrave",
"iacute",
"icircumflex",
"idieresis",
"igrave",
"ntilde",
"oacute",
"ocircumflex",
"odieresis",
"ograve",
"otilde",
"scaron",
"uacute",
"ucircumflex",
"udieresis",
"ugrave",
"yacute",
"ydieresis",
"zcaron",
"exclamsmall",
"Hungarumlautsmall",
"dollaroldstyle",
"dollarsuperior",
"ampersandsmall",
"Acutesmall",
"parenleftsuperior",
"parenrightsuperior",
"twodotenleader",
"onedotenleader",
"zerooldstyle",
"oneoldstyle",
"twooldstyle",
"threeoldstyle",
"fouroldstyle",
"fiveoldstyle",
"sixoldstyle",
"sevenoldstyle",
"eightoldstyle",
"nineoldstyle",
"commasuperior",
"threequartersemdash",
"periodsuperior",
"questionsmall",
"asuperior",
"bsuperior",
"centsuperior",
"dsuperior",
"esuperior",
"isuperior",
"lsuperior",
"msuperior",
"nsuperior",
"osuperior",
"rsuperior",
"ssuperior",
"tsuperior",
"ff",
"ffi",
"ffl",
"parenleftinferior",
"parenrightinferior",
"Circumflexsmall",
"hyphensuperior",
"Gravesmall",
"Asmall",
"Bsmall",
"Csmall",
"Dsmall",
"Esmall",
"Fsmall",
"Gsmall",
"Hsmall",
"Ismall",
"Jsmall",
"Ksmall",
"Lsmall",
"Msmall",
"Nsmall",
"Osmall",
"Psmall",
"Qsmall",
"Rsmall",
"Ssmall",
"Tsmall",
"Usmall",
"Vsmall",
"Wsmall",
"Xsmall",
"Ysmall",
"Zsmall",
"colonmonetary",
"onefitted",
"rupiah",
"Tildesmall",
"exclamdownsmall",
"centoldstyle",
"Lslashsmall",
"Scaronsmall",
"Zcaronsmall",
"Dieresissmall",
"Brevesmall",
"Caronsmall",
"Dotaccentsmall",
"Macronsmall",
"figuredash",
"hypheninferior",
"Ogoneksmall",
"Ringsmall",
"Cedillasmall",
"questiondownsmall",
"oneeighth",
"threeeighths",
"fiveeighths",
"seveneighths",
"onethird",
"twothirds",
"zerosuperior",
"foursuperior",
"fivesuperior",
"sixsuperior",
"sevensuperior",
"eightsuperior",
"ninesuperior",
"zeroinferior",
"oneinferior",
"twoinferior",
"threeinferior",
"fourinferior",
"fiveinferior",
"sixinferior",
"seveninferior",
"eightinferior",
"nineinferior",
"centinferior",
"dollarinferior",
"periodinferior",
"commainferior",
"Agravesmall",
"Aacutesmall",
"Acircumflexsmall",
"Atildesmall",
"Adieresissmall",
"Aringsmall",
"AEsmall",
"Ccedillasmall",
"Egravesmall",
"Eacutesmall",
"Ecircumflexsmall",
"Edieresissmall",
"Igravesmall",
"Iacutesmall",
"Icircumflexsmall",
"Idieresissmall",
"Ethsmall",
"Ntildesmall",
"Ogravesmall",
"Oacutesmall",
"Ocircumflexsmall",
"Otildesmall",
"Odieresissmall",
"OEsmall",
"Oslashsmall",
"Ugravesmall",
"Uacutesmall",
"Ucircumflexsmall",
"Udieresissmall",
"Yacutesmall",
"Thornsmall",
"Ydieresissmall",
"001.000",
"001.001",
"001.002",
"001.003",
"Black",
"Bold",
"Book",
"Light",
"Medium",
"Regular",
"Roman",
"Semibold"
};
Gushort fofiType1CISOAdobeCharset[229] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
160, 161, 162, 163, 164, 165, 166, 167, 168, 169,
170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
220, 221, 222, 223, 224, 225, 226, 227, 228
};
Gushort fofiType1CExpertCharset[166] = {
0, 1, 229, 230, 231, 232, 233, 234, 235, 236,
237, 238, 13, 14, 15, 99, 239, 240, 241, 242,
243, 244, 245, 246, 247, 248, 27, 28, 249, 250,
251, 252, 253, 254, 255, 256, 257, 258, 259, 260,
261, 262, 263, 264, 265, 266, 109, 110, 267, 268,
269, 270, 271, 272, 273, 274, 275, 276, 277, 278,
279, 280, 281, 282, 283, 284, 285, 286, 287, 288,
289, 290, 291, 292, 293, 294, 295, 296, 297, 298,
299, 300, 301, 302, 303, 304, 305, 306, 307, 308,
309, 310, 311, 312, 313, 314, 315, 316, 317, 318,
158, 155, 163, 319, 320, 321, 322, 323, 324, 325,
326, 150, 164, 169, 327, 328, 329, 330, 331, 332,
333, 334, 335, 336, 337, 338, 339, 340, 341, 342,
343, 344, 345, 346, 347, 348, 349, 350, 351, 352,
353, 354, 355, 356, 357, 358, 359, 360, 361, 362,
363, 364, 365, 366, 367, 368, 369, 370, 371, 372,
373, 374, 375, 376, 377, 378
};
Gushort fofiType1CExpertSubsetCharset[87] = {
0, 1, 231, 232, 235, 236, 237, 238, 13, 14,
15, 99, 239, 240, 241, 242, 243, 244, 245, 246,
247, 248, 27, 28, 249, 250, 251, 253, 254, 255,
256, 257, 258, 259, 260, 261, 262, 263, 264, 265,
266, 109, 110, 267, 268, 269, 270, 272, 300, 301,
302, 305, 314, 315, 158, 155, 163, 320, 321, 322,
323, 324, 325, 326, 150, 164, 169, 327, 328, 329,
330, 331, 332, 333, 334, 335, 336, 337, 338, 339,
340, 341, 342, 343, 344, 345, 346
};

View file

@ -1,34 +0,0 @@
//========================================================================
//
// FoFiEncodings.h
//
// Copyright 1999-2003 Glyph & Cog, LLC
//
//========================================================================
#ifndef FOFIENCODINGS_H
#define FOFIENCODINGS_H
#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
#include "goo/gtypes.h"
//------------------------------------------------------------------------
// Type 1 and 1C font data
//------------------------------------------------------------------------
extern const char *fofiType1StandardEncoding[256];
extern const char *fofiType1ExpertEncoding[256];
//------------------------------------------------------------------------
// Type 1C font data
//------------------------------------------------------------------------
extern const char *fofiType1CStdStrings[391];
extern Gushort fofiType1CISOAdobeCharset[229];
extern Gushort fofiType1CExpertCharset[166];
extern Gushort fofiType1CExpertSubsetCharset[87];
#endif

View file

@ -1,648 +0,0 @@
//========================================================================
//
// FoFiIdentifier.cc
//
// Copyright 2009 Glyph & Cog, LLC
//
//========================================================================
//========================================================================
//
// Modified under the Poppler project - http://poppler.freedesktop.org
//
// All changes made under the Poppler project to this file are licensed
// under GPL version 2 or later
//
// Copyright (C) 2013 Christoph Duelli <duelli@melosgmbh.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
//
//========================================================================
#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include "goo/gtypes.h"
#include "FoFiIdentifier.h"
//------------------------------------------------------------------------
namespace { // do not pollute global namespace
class Reader {
public:
virtual ~Reader() {}
// Read one byte. Returns -1 if past EOF.
virtual int getByte(int pos) = 0;
// Read a big-endian unsigned 16-bit integer. Fills in *val and
// returns true if successful.
virtual GBool getU16BE(int pos, int *val) = 0;
// Read a big-endian unsigned 32-bit integer. Fills in *val and
// returns true if successful.
virtual GBool getU32BE(int pos, Guint *val) = 0;
// Read a little-endian unsigned 32-bit integer. Fills in *val and
// returns true if successful.
virtual GBool getU32LE(int pos, Guint *val) = 0;
// Read a big-endian unsigned <size>-byte integer, where 1 <= size
// <= 4. Fills in *val and returns true if successful.
virtual GBool getUVarBE(int pos, int size, Guint *val) = 0;
// Compare against a string. Returns true if equal.
virtual GBool cmp(int pos, const char *s) = 0;
};
//------------------------------------------------------------------------
class MemReader: public Reader {
public:
static MemReader *make(char *bufA, int lenA);
virtual ~MemReader();
virtual int getByte(int pos);
virtual GBool getU16BE(int pos, int *val);
virtual GBool getU32BE(int pos, Guint *val);
virtual GBool getU32LE(int pos, Guint *val);
virtual GBool getUVarBE(int pos, int size, Guint *val);
virtual GBool cmp(int pos, const char *s);
private:
MemReader(char *bufA, int lenA);
char *buf;
int len;
};
MemReader *MemReader::make(char *bufA, int lenA) {
return new MemReader(bufA, lenA);
}
MemReader::MemReader(char *bufA, int lenA) {
buf = bufA;
len = lenA;
}
MemReader::~MemReader() {
}
int MemReader::getByte(int pos) {
if (pos < 0 || pos >= len) {
return -1;
}
return buf[pos] & 0xff;
}
GBool MemReader::getU16BE(int pos, int *val) {
if (pos < 0 || pos > len - 2) {
return gFalse;
}
*val = ((buf[pos] & 0xff) << 8) +
(buf[pos+1] & 0xff);
return gTrue;
}
GBool MemReader::getU32BE(int pos, Guint *val) {
if (pos < 0 || pos > len - 4) {
return gFalse;
}
*val = ((buf[pos] & 0xff) << 24) +
((buf[pos+1] & 0xff) << 16) +
((buf[pos+2] & 0xff) << 8) +
(buf[pos+3] & 0xff);
return gTrue;
}
GBool MemReader::getU32LE(int pos, Guint *val) {
if (pos < 0 || pos > len - 4) {
return gFalse;
}
*val = (buf[pos] & 0xff) +
((buf[pos+1] & 0xff) << 8) +
((buf[pos+2] & 0xff) << 16) +
((buf[pos+3] & 0xff) << 24);
return gTrue;
}
GBool MemReader::getUVarBE(int pos, int size, Guint *val) {
int i;
if (size < 1 || size > 4 || pos < 0 || pos > len - size) {
return gFalse;
}
*val = 0;
for (i = 0; i < size; ++i) {
*val = (*val << 8) + (buf[pos + i] & 0xff);
}
return gTrue;
}
GBool MemReader::cmp(int pos, const char *s) {
int n;
n = (int)strlen(s);
if (pos < 0 || len < n || pos > len - n) {
return gFalse;
}
return !memcmp(buf + pos, s, n);
}
//------------------------------------------------------------------------
class FileReader: public Reader {
public:
static FileReader *make(char *fileName);
virtual ~FileReader();
virtual int getByte(int pos);
virtual GBool getU16BE(int pos, int *val);
virtual GBool getU32BE(int pos, Guint *val);
virtual GBool getU32LE(int pos, Guint *val);
virtual GBool getUVarBE(int pos, int size, Guint *val);
virtual GBool cmp(int pos, const char *s);
private:
FileReader(FILE *fA);
GBool fillBuf(int pos, int len);
FILE *f;
char buf[1024];
int bufPos, bufLen;
};
FileReader *FileReader::make(char *fileName) {
FILE *fA;
if (!(fA = fopen(fileName, "rb"))) {
return NULL;
}
return new FileReader(fA);
}
FileReader::FileReader(FILE *fA) {
f = fA;
bufPos = 0;
bufLen = 0;
}
FileReader::~FileReader() {
fclose(f);
}
int FileReader::getByte(int pos) {
if (!fillBuf(pos, 1)) {
return -1;
}
return buf[pos - bufPos] & 0xff;
}
GBool FileReader::getU16BE(int pos, int *val) {
if (!fillBuf(pos, 2)) {
return gFalse;
}
*val = ((buf[pos - bufPos] & 0xff) << 8) +
(buf[pos - bufPos + 1] & 0xff);
return gTrue;
}
GBool FileReader::getU32BE(int pos, Guint *val) {
if (!fillBuf(pos, 4)) {
return gFalse;
}
*val = ((buf[pos - bufPos] & 0xff) << 24) +
((buf[pos - bufPos + 1] & 0xff) << 16) +
((buf[pos - bufPos + 2] & 0xff) << 8) +
(buf[pos - bufPos + 3] & 0xff);
return gTrue;
}
GBool FileReader::getU32LE(int pos, Guint *val) {
if (!fillBuf(pos, 4)) {
return gFalse;
}
*val = (buf[pos - bufPos] & 0xff) +
((buf[pos - bufPos + 1] & 0xff) << 8) +
((buf[pos - bufPos + 2] & 0xff) << 16) +
((buf[pos - bufPos + 3] & 0xff) << 24);
return gTrue;
}
GBool FileReader::getUVarBE(int pos, int size, Guint *val) {
int i;
if (size < 1 || size > 4 || !fillBuf(pos, size)) {
return gFalse;
}
*val = 0;
for (i = 0; i < size; ++i) {
*val = (*val << 8) + (buf[pos - bufPos + i] & 0xff);
}
return gTrue;
}
GBool FileReader::cmp(int pos, const char *s) {
int n;
n = (int)strlen(s);
if (!fillBuf(pos, n)) {
return gFalse;
}
return !memcmp(buf - bufPos + pos, s, n);
}
GBool FileReader::fillBuf(int pos, int len) {
if (pos < 0 || len < 0 || len > (int)sizeof(buf) ||
pos > INT_MAX - (int)sizeof(buf)) {
return gFalse;
}
if (pos >= bufPos && pos + len <= bufPos + bufLen) {
return gTrue;
}
if (fseek(f, pos, SEEK_SET)) {
return gFalse;
}
bufPos = pos;
bufLen = (int)fread(buf, 1, sizeof(buf), f);
if (bufLen < len) {
return gFalse;
}
return gTrue;
}
//------------------------------------------------------------------------
class StreamReader: public Reader {
public:
static StreamReader *make(int (*getCharA)(void *data), void *dataA);
virtual ~StreamReader();
virtual int getByte(int pos);
virtual GBool getU16BE(int pos, int *val);
virtual GBool getU32BE(int pos, Guint *val);
virtual GBool getU32LE(int pos, Guint *val);
virtual GBool getUVarBE(int pos, int size, Guint *val);
virtual GBool cmp(int pos, const char *s);
private:
StreamReader(int (*getCharA)(void *data), void *dataA);
GBool fillBuf(int pos, int len);
int (*getChar)(void *data);
void *data;
int streamPos;
char buf[1024];
int bufPos, bufLen;
};
StreamReader *StreamReader::make(int (*getCharA)(void *data), void *dataA) {
return new StreamReader(getCharA, dataA);
}
StreamReader::StreamReader(int (*getCharA)(void *data), void *dataA) {
getChar = getCharA;
data = dataA;
streamPos = 0;
bufPos = 0;
bufLen = 0;
}
StreamReader::~StreamReader() {
}
int StreamReader::getByte(int pos) {
if (!fillBuf(pos, 1)) {
return -1;
}
return buf[pos - bufPos] & 0xff;
}
GBool StreamReader::getU16BE(int pos, int *val) {
if (!fillBuf(pos, 2)) {
return gFalse;
}
*val = ((buf[pos - bufPos] & 0xff) << 8) +
(buf[pos - bufPos + 1] & 0xff);
return gTrue;
}
GBool StreamReader::getU32BE(int pos, Guint *val) {
if (!fillBuf(pos, 4)) {
return gFalse;
}
*val = ((buf[pos - bufPos] & 0xff) << 24) +
((buf[pos - bufPos + 1] & 0xff) << 16) +
((buf[pos - bufPos + 2] & 0xff) << 8) +
(buf[pos - bufPos + 3] & 0xff);
return gTrue;
}
GBool StreamReader::getU32LE(int pos, Guint *val) {
if (!fillBuf(pos, 4)) {
return gFalse;
}
*val = (buf[pos - bufPos] & 0xff) +
((buf[pos - bufPos + 1] & 0xff) << 8) +
((buf[pos - bufPos + 2] & 0xff) << 16) +
((buf[pos - bufPos + 3] & 0xff) << 24);
return gTrue;
}
GBool StreamReader::getUVarBE(int pos, int size, Guint *val) {
int i;
if (size < 1 || size > 4 || !fillBuf(pos, size)) {
return gFalse;
}
*val = 0;
for (i = 0; i < size; ++i) {
*val = (*val << 8) + (buf[pos - bufPos + i] & 0xff);
}
return gTrue;
}
GBool StreamReader::cmp(int pos, const char *s) {
int n;
n = (int)strlen(s);
if (!fillBuf(pos, n)) {
return gFalse;
}
return !memcmp(buf - bufPos + pos, s, n);
}
GBool StreamReader::fillBuf(int pos, int len) {
int c;
if (pos < 0 || len < 0 || len > (int)sizeof(buf) ||
pos > INT_MAX - (int)sizeof(buf)) {
return gFalse;
}
if (pos < bufPos) {
return gFalse;
}
// if requested region will not fit in the current buffer...
if (pos + len > bufPos + (int)sizeof(buf)) {
// if the start of the requested data is already in the buffer, move
// it to the start of the buffer
if (pos < bufPos + bufLen) {
bufLen -= pos - bufPos;
memmove(buf, buf + (pos - bufPos), bufLen);
bufPos = pos;
// otherwise discard data from the
// stream until we get to the requested position
} else {
bufPos += bufLen;
bufLen = 0;
while (bufPos < pos) {
if ((c = (*getChar)(data)) < 0) {
return gFalse;
}
++bufPos;
}
}
}
// read the rest of the requested data
while (bufPos + bufLen < pos + len) {
if ((c = (*getChar)(data)) < 0) {
return gFalse;
}
buf[bufLen++] = (char)c;
}
return gTrue;
}
}
//------------------------------------------------------------------------
static FoFiIdentifierType identify(Reader *reader);
static FoFiIdentifierType identifyOpenType(Reader *reader);
static FoFiIdentifierType identifyCFF(Reader *reader, int start);
FoFiIdentifierType FoFiIdentifier::identifyMem(char *file, int len) {
MemReader *reader;
FoFiIdentifierType type;
if (!(reader = MemReader::make(file, len))) {
return fofiIdError;
}
type = identify(reader);
delete reader;
return type;
}
FoFiIdentifierType FoFiIdentifier::identifyFile(char *fileName) {
FileReader *reader;
FoFiIdentifierType type;
if (!(reader = FileReader::make(fileName))) {
return fofiIdError;
}
type = identify(reader);
delete reader;
return type;
}
FoFiIdentifierType FoFiIdentifier::identifyStream(int (*getChar)(void *data),
void *data) {
StreamReader *reader;
FoFiIdentifierType type;
if (!(reader = StreamReader::make(getChar, data))) {
return fofiIdError;
}
type = identify(reader);
delete reader;
return type;
}
static FoFiIdentifierType identify(Reader *reader) {
Guint n;
//----- PFA
if (reader->cmp(0, "%!PS-AdobeFont-1") ||
reader->cmp(0, "%!FontType1")) {
return fofiIdType1PFA;
}
//----- PFB
if (reader->getByte(0) == 0x80 &&
reader->getByte(1) == 0x01 &&
reader->getU32LE(2, &n)) {
if ((n >= 16 && reader->cmp(6, "%!PS-AdobeFont-1")) ||
(n >= 11 && reader->cmp(6, "%!FontType1"))) {
return fofiIdType1PFB;
}
}
//----- TrueType
if ((reader->getByte(0) == 0x00 &&
reader->getByte(1) == 0x01 &&
reader->getByte(2) == 0x00 &&
reader->getByte(3) == 0x00) ||
(reader->getByte(0) == 0x74 && // 'true'
reader->getByte(1) == 0x72 &&
reader->getByte(2) == 0x75 &&
reader->getByte(3) == 0x65)) {
return fofiIdTrueType;
}
if (reader->getByte(0) == 0x74 && // 'ttcf'
reader->getByte(1) == 0x74 &&
reader->getByte(2) == 0x63 &&
reader->getByte(3) == 0x66) {
return fofiIdTrueTypeCollection;
}
//----- OpenType
if (reader->getByte(0) == 0x4f && // 'OTTO
reader->getByte(1) == 0x54 &&
reader->getByte(2) == 0x54 &&
reader->getByte(3) == 0x4f) {
return identifyOpenType(reader);
}
//----- CFF
if (reader->getByte(0) == 0x01 &&
reader->getByte(1) == 0x00) {
return identifyCFF(reader, 0);
}
// some tools embed CFF fonts with an extra whitespace char at the
// beginning
if (reader->getByte(1) == 0x01 &&
reader->getByte(2) == 0x00) {
return identifyCFF(reader, 1);
}
return fofiIdUnknown;
}
static FoFiIdentifierType identifyOpenType(Reader *reader) {
FoFiIdentifierType type;
Guint offset;
int nTables, i;
if (!reader->getU16BE(4, &nTables)) {
return fofiIdUnknown;
}
for (i = 0; i < nTables; ++i) {
if (reader->cmp(12 + i*16, "CFF ")) {
if (reader->getU32BE(12 + i*16 + 8, &offset) &&
offset < (Guint)INT_MAX) {
type = identifyCFF(reader, (int)offset);
if (type == fofiIdCFF8Bit) {
type = fofiIdOpenTypeCFF8Bit;
} else if (type == fofiIdCFFCID) {
type = fofiIdOpenTypeCFFCID;
}
return type;
}
return fofiIdUnknown;
}
}
return fofiIdUnknown;
}
static FoFiIdentifierType identifyCFF(Reader *reader, int start) {
Guint offset0, offset1;
int hdrSize, offSize0, offSize1, pos, endPos, b0, n, i;
//----- read the header
if (reader->getByte(start) != 0x01 ||
reader->getByte(start + 1) != 0x00) {
return fofiIdUnknown;
}
if ((hdrSize = reader->getByte(start + 2)) < 0) {
return fofiIdUnknown;
}
if ((offSize0 = reader->getByte(start + 3)) < 1 || offSize0 > 4) {
return fofiIdUnknown;
}
pos = start + hdrSize;
if (pos < 0) {
return fofiIdUnknown;
}
//----- skip the name index
if (!reader->getU16BE(pos, &n)) {
return fofiIdUnknown;
}
if (n == 0) {
pos += 2;
} else {
if ((offSize1 = reader->getByte(pos + 2)) < 1 || offSize1 > 4) {
return fofiIdUnknown;
}
if (!reader->getUVarBE(pos + 3 + n * offSize1, offSize1, &offset1) ||
offset1 > (Guint)INT_MAX) {
return fofiIdUnknown;
}
pos += 3 + (n + 1) * offSize1 + (int)offset1 - 1;
}
if (pos < 0) {
return fofiIdUnknown;
}
//----- parse the top dict index
if (!reader->getU16BE(pos, &n) || n < 1) {
return fofiIdUnknown;
}
if ((offSize1 = reader->getByte(pos + 2)) < 1 || offSize1 > 4) {
return fofiIdUnknown;
}
if (!reader->getUVarBE(pos + 3, offSize1, &offset0) ||
offset0 > (Guint)INT_MAX ||
!reader->getUVarBE(pos + 3 + offSize1, offSize1, &offset1) ||
offset1 > (Guint)INT_MAX ||
offset0 > offset1) {
return fofiIdUnknown;
}
pos = pos + 3 + (n + 1) * offSize1 + (int)offset0 - 1;
endPos = pos + 3 + (n + 1) * offSize1 + (int)offset1 - 1;
if (pos < 0 || endPos < 0 || pos > endPos) {
return fofiIdUnknown;
}
//----- parse the top dict, look for ROS as first entry
// for a CID font, the top dict starts with:
// <int> <int> <int> ROS
for (i = 0; i < 3; ++i) {
b0 = reader->getByte(pos++);
if (b0 == 0x1c) {
pos += 2;
} else if (b0 == 0x1d) {
pos += 4;
} else if (b0 >= 0xf7 && b0 <= 0xfe) {
pos += 1;
} else if (b0 < 0x20 || b0 > 0xf6) {
return fofiIdCFF8Bit;
}
if (pos >= endPos || pos < 0) {
return fofiIdCFF8Bit;
}
}
if (pos + 1 < endPos &&
reader->getByte(pos) == 12 &&
reader->getByte(pos + 1) == 30) {
return fofiIdCFFCID;
} else {
return fofiIdCFF8Bit;
}
}

View file

@ -1,42 +0,0 @@
//========================================================================
//
// FoFiIdentifier.h
//
// Copyright 2009 Glyph & Cog, LLC
//
//========================================================================
#ifndef FOFIIDENTIFIER_H
#define FOFIIDENTIFIER_H
#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
//------------------------------------------------------------------------
// FoFiIdentifier
//------------------------------------------------------------------------
enum FoFiIdentifierType {
fofiIdType1PFA, // Type 1 font in PFA format
fofiIdType1PFB, // Type 1 font in PFB format
fofiIdCFF8Bit, // 8-bit CFF font
fofiIdCFFCID, // CID CFF font
fofiIdTrueType, // TrueType font
fofiIdTrueTypeCollection, // TrueType collection
fofiIdOpenTypeCFF8Bit, // OpenType wrapper with 8-bit CFF font
fofiIdOpenTypeCFFCID, // OpenType wrapper with CID CFF font
fofiIdUnknown, // unknown type
fofiIdError // error in reading the file
};
class FoFiIdentifier {
public:
static FoFiIdentifierType identifyMem(char *file, int len);
static FoFiIdentifierType identifyFile(char *fileName);
static FoFiIdentifierType identifyStream(int (*getChar)(void *data),
void *data);
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,209 +0,0 @@
//========================================================================
//
// FoFiTrueType.h
//
// Copyright 1999-2003 Glyph & Cog, LLC
//
//========================================================================
//========================================================================
//
// Modified under the Poppler project - http://poppler.freedesktop.org
//
// All changes made under the Poppler project to this file are licensed
// under GPL version 2 or later
//
// Copyright (C) 2006 Takashi Iwai <tiwai@suse.de>
// Copyright (C) 2007 Koji Otani <sho@bbr.jp>
// Copyright (C) 2011, 2012 Albert Astals Cid <aacid@kde.org>
// Copyright (C) 2012 Suzuki Toshiya <mpsuzuki@hiroshima-u.ac.jp>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
//
//========================================================================
#ifndef FOFITRUETYPE_H
#define FOFITRUETYPE_H
#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
#include "stddef.h"
#include "goo/gtypes.h"
#include "FoFiBase.h"
class GooString;
class GooHash;
struct TrueTypeTable;
struct TrueTypeCmap;
//------------------------------------------------------------------------
// FoFiTrueType
//------------------------------------------------------------------------
class FoFiTrueType: public FoFiBase {
public:
// Create a FoFiTrueType object from a memory buffer.
static FoFiTrueType *make(char *fileA, int lenA, int faceIndexA=0);
// Create a FoFiTrueType object from a file on disk.
static FoFiTrueType *load(char *fileName, int faceIndexA=0);
virtual ~FoFiTrueType();
// Returns true if this an OpenType font containing CFF data, false
// if it's a TrueType font (or OpenType font with TrueType data).
GBool isOpenTypeCFF() { return openTypeCFF; }
// Return the number of cmaps defined by this font.
int getNumCmaps();
// Return the platform ID of the <i>th cmap.
int getCmapPlatform(int i);
// Return the encoding ID of the <i>th cmap.
int getCmapEncoding(int i);
// Return the index of the cmap for <platform>, <encoding>. Returns
// -1 if there is no corresponding cmap.
int findCmap(int platform, int encoding);
// Return the GID corresponding to <c> according to the <i>th cmap.
int mapCodeToGID(int i, Guint c);
// map gid to vertical glyph gid if exist.
// if not exist return original gid
Guint mapToVertGID(Guint orgGID);
// Returns the GID corresponding to <name> according to the post
// table. Returns 0 if there is no mapping for <name> or if the
// font does not have a post table.
int mapNameToGID(char *name);
// Return the mapping from CIDs to GIDs, and return the number of
// CIDs in *<nCIDs>. This is only useful for CID fonts. (Only
// useful for OpenType CFF fonts.)
int *getCIDToGIDMap(int *nCIDs);
// Returns the least restrictive embedding licensing right (as
// defined by the TrueType spec):
// * 4: OS/2 table is missing or invalid
// * 3: installable embedding
// * 2: editable embedding
// * 1: preview & print embedding
// * 0: restricted license embedding
int getEmbeddingRights();
// Return the font matrix as an array of six numbers. (Only useful
// for OpenType CFF fonts.)
void getFontMatrix(double *mat);
// Convert to a Type 42 font, suitable for embedding in a PostScript
// file. <psName> will be used as the PostScript font name (so we
// don't need to depend on the 'name' table in the font). The
// <encoding> array specifies the mapping from char codes to names.
// If <encoding> is NULL, the encoding is unknown or undefined. The
// <codeToGID> array specifies the mapping from char codes to GIDs.
// (Not useful for OpenType CFF fonts.)
void convertToType42(char *psName, char **encoding,
int *codeToGID,
FoFiOutputFunc outputFunc, void *outputStream);
// Convert to a Type 1 font, suitable for embedding in a PostScript
// file. This is only useful with 8-bit fonts. If <newEncoding> is
// not NULL, it will be used in place of the encoding in the Type 1C
// font. If <ascii> is true the eexec section will be hex-encoded,
// otherwise it will be left as binary data. If <psName> is
// non-NULL, it will be used as the PostScript font name. (Only
// useful for OpenType CFF fonts.)
void convertToType1(char *psName, const char **newEncoding, GBool ascii,
FoFiOutputFunc outputFunc, void *outputStream);
// Convert to a Type 2 CIDFont, suitable for embedding in a
// PostScript file. <psName> will be used as the PostScript font
// name (so we don't need to depend on the 'name' table in the
// font). The <cidMap> array maps CIDs to GIDs; it has <nCIDs>
// entries. (Not useful for OpenType CFF fonts.)
void convertToCIDType2(char *psName, int *cidMap, int nCIDs,
GBool needVerticalMetrics,
FoFiOutputFunc outputFunc, void *outputStream);
// Convert to a Type 0 CIDFont, suitable for embedding in a
// PostScript file. <psName> will be used as the PostScript font
// name. (Only useful for OpenType CFF fonts.)
void convertToCIDType0(char *psName, int *cidMap, int nCIDs,
FoFiOutputFunc outputFunc, void *outputStream);
// Convert to a Type 0 (but non-CID) composite font, suitable for
// embedding in a PostScript file. <psName> will be used as the
// PostScript font name (so we don't need to depend on the 'name'
// table in the font). The <cidMap> array maps CIDs to GIDs; it has
// <nCIDs> entries. (Not useful for OpenType CFF fonts.)
void convertToType0(char *psName, int *cidMap, int nCIDs,
GBool needVerticalMetrics,
FoFiOutputFunc outputFunc, void *outputStream);
// Convert to a Type 0 (but non-CID) composite font, suitable for
// embedding in a PostScript file. <psName> will be used as the
// PostScript font name. (Only useful for OpenType CFF fonts.)
void convertToType0(char *psName, int *cidMap, int nCIDs,
FoFiOutputFunc outputFunc, void *outputStream);
// Returns a pointer to the CFF font embedded in this OpenType font.
// If successful, sets *<start> and *<length>, and returns true.
// Otherwise returns false. (Only useful for OpenType CFF fonts).
GBool getCFFBlock(char **start, int *length);
// setup vert/vrt2 GSUB for default lang
int setupGSUB(const char *scriptName);
// setup vert/vrt2 GSUB for specified lang
int setupGSUB(const char *scriptName, const char* languageName);
private:
FoFiTrueType(char *fileA, int lenA, GBool freeFileDataA, int faceIndexA);
void cvtEncoding(char **encoding,
FoFiOutputFunc outputFunc,
void *outputStream);
void cvtCharStrings(char **encoding,
int *codeToGID,
FoFiOutputFunc outputFunc,
void *outputStream);
void cvtSfnts(FoFiOutputFunc outputFunc,
void *outputStream, GooString *name,
GBool needVerticalMetrics,
int *maxUsedGlyph);
void dumpString(Guchar *s, int length,
FoFiOutputFunc outputFunc,
void *outputStream);
Guint computeTableChecksum(Guchar *data, int length);
void parse();
void readPostTable();
int seekTable(const char *tag);
Guint charToTag(const char *tagName);
Guint doMapToVertGID(Guint orgGID);
Guint scanLookupList(Guint listIndex, Guint orgGID);
Guint scanLookupSubTable(Guint subTable, Guint orgGID);
int checkGIDInCoverage(Guint coverage, Guint orgGID);
TrueTypeTable *tables;
int nTables;
TrueTypeCmap *cmaps;
int nCmaps;
int nGlyphs;
int locaFmt;
int bbox[4];
GooHash *nameToGID;
GBool openTypeCFF;
GBool parsedOk;
int faceIndex;
Guint gsubFeatureTable;
Guint gsubLookupList;
};
#endif

View file

@ -1,359 +0,0 @@
//========================================================================
//
// FoFiType1.cc
//
// Copyright 1999-2003 Glyph & Cog, LLC
//
//========================================================================
//========================================================================
//
// Modified under the Poppler project - http://poppler.freedesktop.org
//
// All changes made under the Poppler project to this file are licensed
// under GPL version 2 or later
//
// Copyright (C) 2005, 2008, 2010 Albert Astals Cid <aacid@kde.org>
// Copyright (C) 2005 Kristian Høgsberg <krh@redhat.com>
// Copyright (C) 2010 Jakub Wilk <jwilk@jwilk.net>
// Copyright (C) 2014 Carlos Garcia Campos <carlosgc@gnome.org>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
//
//========================================================================
#include <config.h>
#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
#include <stdlib.h>
#include <string.h>
#include "goo/gmem.h"
#include "goo/GooLikely.h"
#include "FoFiEncodings.h"
#include "FoFiType1.h"
#include "poppler/Error.h"
//------------------------------------------------------------------------
// FoFiType1
//------------------------------------------------------------------------
FoFiType1 *FoFiType1::make(char *fileA, int lenA) {
return new FoFiType1(fileA, lenA, gFalse);
}
FoFiType1 *FoFiType1::load(char *fileName) {
char *fileA;
int lenA;
if (!(fileA = FoFiBase::readFile(fileName, &lenA))) {
return NULL;
}
return new FoFiType1(fileA, lenA, gTrue);
}
FoFiType1::FoFiType1(char *fileA, int lenA, GBool freeFileDataA):
FoFiBase(fileA, lenA, freeFileDataA)
{
name = NULL;
encoding = NULL;
fontMatrix[0] = 0.001;
fontMatrix[1] = 0;
fontMatrix[2] = 0;
fontMatrix[3] = 0.001;
fontMatrix[4] = 0;
fontMatrix[5] = 0;
parsed = gFalse;
undoPFB();
}
FoFiType1::~FoFiType1() {
int i;
if (name) {
gfree(name);
}
if (encoding && const_cast<const char**>(encoding) != fofiType1StandardEncoding) {
for (i = 0; i < 256; ++i) {
gfree(encoding[i]);
}
gfree(encoding);
}
}
char *FoFiType1::getName() {
if (!parsed) {
parse();
}
return name;
}
char **FoFiType1::getEncoding() {
if (!parsed) {
parse();
}
return encoding;
}
void FoFiType1::getFontMatrix(double *mat) {
int i;
if (!parsed) {
parse();
}
for (i = 0; i < 6; ++i) {
mat[i] = fontMatrix[i];
}
}
void FoFiType1::writeEncoded(const char **newEncoding,
FoFiOutputFunc outputFunc, void *outputStream) {
char buf[512];
char *line, *line2, *p;
int i;
// copy everything up to the encoding
for (line = (char *)file;
line && strncmp(line, "/Encoding", 9);
line = getNextLine(line)) ;
if (!line) {
// no encoding - just copy the whole font file
(*outputFunc)(outputStream, (char *)file, len);
return;
}
(*outputFunc)(outputStream, (char *)file, line - (char *)file);
// write the new encoding
(*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
(*outputFunc)(outputStream,
"0 1 255 {1 index exch /.notdef put} for\n", 40);
for (i = 0; i < 256; ++i) {
if (newEncoding[i]) {
sprintf(buf, "dup %d /%s put\n", i, newEncoding[i]);
(*outputFunc)(outputStream, buf, strlen(buf));
}
}
(*outputFunc)(outputStream, "readonly def\n", 13);
// find the end of the encoding data
//~ this ought to parse PostScript tokens
if (!strncmp(line, "/Encoding StandardEncoding def", 30)) {
line = getNextLine(line);
} else {
// skip "/Encoding" + one whitespace char,
// then look for 'def' preceded by PostScript whitespace
p = line + 10;
line = NULL;
for (; p < (char *)file + len; ++p) {
if ((*p == ' ' || *p == '\t' || *p == '\x0a' ||
*p == '\x0d' || *p == '\x0c' || *p == '\0') &&
p + 4 <= (char *)file + len &&
!strncmp(p + 1, "def", 3)) {
line = p + 4;
break;
}
}
}
// some fonts have two /Encoding entries in their dictionary, so we
// check for a second one here
if (line) {
for (line2 = line, i = 0;
i < 20 && line2 && strncmp(line2, "/Encoding", 9);
line2 = getNextLine(line2), ++i) ;
if (i < 20 && line2) {
(*outputFunc)(outputStream, line, line2 - line);
if (!strncmp(line2, "/Encoding StandardEncoding def", 30)) {
line = getNextLine(line2);
} else {
// skip "/Encoding" + one whitespace char,
// then look for 'def' preceded by PostScript whitespace
p = line2 + 10;
line = NULL;
for (; p < (char *)file + len; ++p) {
if ((*p == ' ' || *p == '\t' || *p == '\x0a' ||
*p == '\x0d' || *p == '\x0c' || *p == '\0') &&
p + 4 <= (char *)file + len &&
!strncmp(p + 1, "def", 3)) {
line = p + 4;
break;
}
}
}
}
// copy everything after the encoding
if (line) {
(*outputFunc)(outputStream, line, ((char *)file + len) - line);
}
}
}
char *FoFiType1::getNextLine(char *line) {
while (line < (char *)file + len && *line != '\x0a' && *line != '\x0d') {
++line;
}
if (line < (char *)file + len && *line == '\x0d') {
++line;
}
if (line < (char *)file + len && *line == '\x0a') {
++line;
}
if (line >= (char *)file + len) {
return NULL;
}
return line;
}
void FoFiType1::parse() {
char *line, *line1, *p, *p2;
char buf[256];
char c;
int n, code, base, i, j;
char *tokptr;
GBool gotMatrix;
gotMatrix = gFalse;
for (i = 1, line = (char *)file;
i <= 100 && line && (!name || !encoding);
++i) {
// get font name
if (!name && !strncmp(line, "/FontName", 9)) {
strncpy(buf, line, 255);
buf[255] = '\0';
if ((p = strchr(buf+9, '/')) &&
(p = strtok_r(p+1, " \t\n\r", &tokptr))) {
name = copyString(p);
}
line = getNextLine(line);
// get encoding
} else if (!encoding &&
!strncmp(line, "/Encoding StandardEncoding def", 30)) {
encoding = (char **)fofiType1StandardEncoding;
} else if (!encoding &&
!strncmp(line, "/Encoding 256 array", 19)) {
encoding = (char **)gmallocn(256, sizeof(char *));
for (j = 0; j < 256; ++j) {
encoding[j] = NULL;
}
for (j = 0, line = getNextLine(line);
j < 300 && line && (line1 = getNextLine(line));
++j, line = line1) {
if ((n = (int)(line1 - line)) > 255) {
error(errSyntaxWarning, -1, "FoFiType1::parse a line has more than 255 characters, we don't support this");
n = 255;
}
strncpy(buf, line, n);
buf[n] = '\0';
for (p = buf; *p == ' ' || *p == '\t'; ++p) ;
if (!strncmp(p, "dup", 3)) {
while (1) {
p += 3;
for (; *p == ' ' || *p == '\t'; ++p) ;
code = 0;
if (*p == '8' && p[1] == '#') {
base = 8;
p += 2;
} else if (*p >= '0' && *p <= '9') {
base = 10;
} else {
break;
}
for (; *p >= '0' && *p < '0' + base && code < INT_MAX / (base + (*p - '0')); ++p) {
code = code * base + (*p - '0');
}
for (; *p == ' ' || *p == '\t'; ++p) ;
if (*p != '/') {
break;
}
++p;
for (p2 = p; *p2 && *p2 != ' ' && *p2 != '\t'; ++p2) ;
if (code >= 0 && code < 256) {
c = *p2;
*p2 = '\0';
encoding[code] = copyString(p);
*p2 = c;
}
for (p = p2; *p == ' ' || *p == '\t'; ++p) ;
if (strncmp(p, "put", 3)) {
break;
}
for (p += 3; *p == ' ' || *p == '\t'; ++p) ;
if (strncmp(p, "dup", 3)) {
break;
}
}
} else {
if (strtok_r(buf, " \t", &tokptr) &&
(p = strtok_r(NULL, " \t\n\r", &tokptr)) && !strcmp(p, "def")) {
break;
}
}
}
//~ check for getinterval/putinterval junk
} else if (!gotMatrix && !strncmp(line, "/FontMatrix", 11)) {
strncpy(buf, line + 11, 255);
buf[255] = '\0';
if ((p = strchr(buf, '['))) {
++p;
if ((p2 = strchr(p, ']'))) {
*p2 = '\0';
for (j = 0; j < 6; ++j) {
if ((p = strtok(j == 0 ? p : (char *)NULL, " \t\n\r"))) {
fontMatrix[j] = atof(p);
} else {
break;
}
}
}
}
gotMatrix = gTrue;
} else {
line = getNextLine(line);
}
}
parsed = gTrue;
}
// Undo the PFB encoding, i.e., remove the PFB headers.
void FoFiType1::undoPFB() {
GBool ok;
Guchar *file2;
int pos1, pos2, type;
Guint segLen;
ok = gTrue;
if (getU8(0, &ok) != 0x80 || !ok) {
return;
}
file2 = (Guchar *)gmalloc(len);
pos1 = pos2 = 0;
while (getU8(pos1, &ok) == 0x80 && ok) {
type = getU8(pos1 + 1, &ok);
if (type < 1 || type > 2 || !ok) {
break;
}
segLen = getU32LE(pos1 + 2, &ok);
pos1 += 6;
if (!ok || !checkRegion(pos1, segLen)) {
break;
}
memcpy(file2 + pos2, file + pos1, segLen);
pos1 += segLen;
pos2 += segLen;
}
if (freeFileData) {
gfree(fileData);
}
file = fileData = file2;
freeFileData = gTrue;
len = pos2;
}

Some files were not shown because too many files have changed in this diff Show more