Start font reading support.
This commit is contained in:
parent
92e7a78710
commit
ed925afabf
22 changed files with 599 additions and 220 deletions
|
@ -3,6 +3,7 @@ add_subdirectory(database)
|
||||||
add_subdirectory(network)
|
add_subdirectory(network)
|
||||||
add_subdirectory(geometry)
|
add_subdirectory(geometry)
|
||||||
add_subdirectory(audio)
|
add_subdirectory(audio)
|
||||||
|
add_subdirectory(fonts)
|
||||||
add_subdirectory(image)
|
add_subdirectory(image)
|
||||||
add_subdirectory(console)
|
add_subdirectory(console)
|
||||||
add_subdirectory(client)
|
add_subdirectory(client)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include "AudioWriter.h"
|
#include "AudioWriter.h"
|
||||||
|
|
||||||
#include "File.h"
|
#include "File.h"
|
||||||
#include "BinaryFile.h"
|
#include "BinaryStream.h"
|
||||||
#include "AudioSample.h"
|
#include "AudioSample.h"
|
||||||
|
|
||||||
AudioWriter::AudioWriter()
|
AudioWriter::AudioWriter()
|
||||||
|
@ -36,22 +36,22 @@ void AudioWriter::Write(const AudioSamplePtr& sample)
|
||||||
const auto num_samples = data.size();
|
const auto num_samples = data.size();
|
||||||
unsigned content_size = 36 + bytes_per_sample* num_samples*num_channels;
|
unsigned content_size = 36 + bytes_per_sample* num_samples*num_channels;
|
||||||
|
|
||||||
BinaryFile::Write<int>(handle, content_size);
|
BinaryStream::write<int>(handle, content_size);
|
||||||
handle->write("WAVE", 4);
|
handle->write("WAVE", 4);
|
||||||
|
|
||||||
/* write fmt subchunk */
|
/* write fmt subchunk */
|
||||||
handle->write("fmt ", 4);
|
handle->write("fmt ", 4);
|
||||||
BinaryFile::Write<int>(handle, 16); // SubChunk1Size
|
BinaryStream::write<int>(handle, 16); // SubChunk1Size
|
||||||
BinaryFile::Write<short>(handle, 1); // PCM Format
|
BinaryStream::write<short>(handle, 1); // PCM Format
|
||||||
BinaryFile::Write<short>(handle, num_channels);
|
BinaryStream::write<short>(handle, num_channels);
|
||||||
BinaryFile::Write<int>(handle, sample_rate);
|
BinaryStream::write<int>(handle, sample_rate);
|
||||||
BinaryFile::Write<int>(handle, byte_rate);
|
BinaryStream::write<int>(handle, byte_rate);
|
||||||
BinaryFile::Write<short>(handle, num_channels*bytes_per_sample); // block align
|
BinaryStream::write<short>(handle, num_channels*bytes_per_sample); // block align
|
||||||
BinaryFile::Write<short>(handle, 8*bytes_per_sample); // bits/sample
|
BinaryStream::write<short>(handle, 8*bytes_per_sample); // bits/sample
|
||||||
|
|
||||||
/* write data subchunk */
|
/* write data subchunk */
|
||||||
handle->write("data", 4);
|
handle->write("data", 4);
|
||||||
BinaryFile::Write<int>(handle, bytes_per_sample* num_samples*num_channels); // bits/sample
|
BinaryStream::write<int>(handle, bytes_per_sample* num_samples*num_channels); // bits/sample
|
||||||
|
|
||||||
handle->write(reinterpret_cast<const char*>(&data[0]), data.size()*sizeof(short));
|
handle->write(reinterpret_cast<const char*>(&data[0]), data.size()*sizeof(short));
|
||||||
outfile.Close();
|
outfile.Close();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "MidiChannelEventAdapter.h"
|
#include "MidiChannelEventAdapter.h"
|
||||||
|
|
||||||
#include "BinaryFile.h"
|
#include "BinaryStream.h"
|
||||||
#include "ByteUtils.h"
|
#include "ByteUtils.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
@ -15,7 +15,7 @@ int MidiChannelEventAdapter::ReadEvent(std::ifstream* file, char firstByte, Midi
|
||||||
unsigned byteCount = 0;
|
unsigned byteCount = 0;
|
||||||
std::cout << "Channel: " << midi_channel << std::endl;
|
std::cout << "Channel: " << midi_channel << std::endl;
|
||||||
|
|
||||||
const bool isStatusByte = ByteUtils::MSBIsOne(firstByte);
|
const bool isStatusByte = ByteUtils::MostSignificantBitIsOne(firstByte);
|
||||||
if(isStatusByte)
|
if(isStatusByte)
|
||||||
{
|
{
|
||||||
event->SetTypeAndChannel(firstByte);
|
event->SetTypeAndChannel(firstByte);
|
||||||
|
@ -44,8 +44,7 @@ int MidiChannelEventAdapter::ReadEvent(std::ifstream* file, char firstByte, Midi
|
||||||
}
|
}
|
||||||
case MidiChannelEvent::Type::PROGRAM:
|
case MidiChannelEvent::Type::PROGRAM:
|
||||||
{
|
{
|
||||||
int value0 = 0;
|
int value0 = *BinaryStream::getNextByteAsInt(file);
|
||||||
BinaryFile::GetNextByteAsInt(file, value0);
|
|
||||||
byteCount ++;
|
byteCount ++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -59,19 +58,15 @@ int MidiChannelEventAdapter::ReadEvent(std::ifstream* file, char firstByte, Midi
|
||||||
int MidiChannelEventAdapter::ReadEventData(std::ifstream* file, MidiChannelEvent* event, char c)
|
int MidiChannelEventAdapter::ReadEventData(std::ifstream* file, MidiChannelEvent* event, char c)
|
||||||
{
|
{
|
||||||
int value0 = int(c);
|
int value0 = int(c);
|
||||||
int value1 = 0;
|
int value1 = *BinaryStream::getNextByteAsInt(file);
|
||||||
BinaryFile::GetNextByteAsInt(file, value1);
|
|
||||||
event->SetValues(value0, value1);
|
event->SetValues(value0, value1);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MidiChannelEventAdapter::ReadEventData(std::ifstream* file, MidiChannelEvent* event)
|
int MidiChannelEventAdapter::ReadEventData(std::ifstream* file, MidiChannelEvent* event)
|
||||||
{
|
{
|
||||||
int value0 = 0;
|
int value0 = *BinaryStream::getNextByteAsInt(file);
|
||||||
BinaryFile::GetNextByteAsInt(file, value0);
|
int value1 = *BinaryStream::getNextByteAsInt(file);
|
||||||
|
|
||||||
int value1 = 0;
|
|
||||||
BinaryFile::GetNextByteAsInt(file, value1);
|
|
||||||
event->SetValues(value0, value1);
|
event->SetValues(value0, value1);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "MidiMetaEventAdapter.h"
|
#include "MidiMetaEventAdapter.h"
|
||||||
|
|
||||||
#include "BinaryFile.h"
|
#include "BinaryStream.h"
|
||||||
#include "ByteUtils.h"
|
#include "ByteUtils.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
@ -35,8 +35,7 @@ int MidiMetaEventAdapter::ReadEvent(std::ifstream* file, MetaMidiEvent* event, i
|
||||||
break;
|
break;
|
||||||
case MetaMidiEvent::Type::END_TRACK:
|
case MetaMidiEvent::Type::END_TRACK:
|
||||||
{
|
{
|
||||||
int length = 0;
|
int length = *BinaryStream::getNextByteAsInt(file);
|
||||||
BinaryFile::GetNextByteAsInt(file, length);
|
|
||||||
byteCount ++;
|
byteCount ++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -66,8 +65,7 @@ int MidiMetaEventAdapter::ReadEvent(std::ifstream* file, MetaMidiEvent* event, i
|
||||||
|
|
||||||
int MidiMetaEventAdapter::ReadUnknownEvent(std::ifstream* file)
|
int MidiMetaEventAdapter::ReadUnknownEvent(std::ifstream* file)
|
||||||
{
|
{
|
||||||
int length = 0;
|
int length = *BinaryStream::getNextByteAsInt(file);
|
||||||
BinaryFile::GetNextByteAsInt(file, length);
|
|
||||||
|
|
||||||
char c;
|
char c;
|
||||||
for(unsigned idx=0; idx<length; idx++)
|
for(unsigned idx=0; idx<length; idx++)
|
||||||
|
@ -81,12 +79,11 @@ int MidiMetaEventAdapter::ReadStringEvent(std::ifstream* file, MetaMidiEvent* ev
|
||||||
{
|
{
|
||||||
unsigned byteCount = 0;
|
unsigned byteCount = 0;
|
||||||
|
|
||||||
int length = 0;
|
int length = *BinaryStream::getNextByteAsInt(file);
|
||||||
BinaryFile::GetNextByteAsInt(file, length);
|
|
||||||
byteCount++;
|
byteCount++;
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
BinaryFile::GetNextString(file, name, length);
|
BinaryStream::getNextString(file, name, length);
|
||||||
byteCount += length;
|
byteCount += length;
|
||||||
event->SetLabel(name);
|
event->SetLabel(name);
|
||||||
return byteCount;
|
return byteCount;
|
||||||
|
@ -102,15 +99,15 @@ int MidiMetaEventAdapter::ReadIntEvent(std::ifstream* file, MetaMidiEvent* event
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
BinaryFile::GetNextByteAsInt(file, length);
|
length = *BinaryStream::getNextByteAsInt(file);
|
||||||
byteCount ++;
|
byteCount ++;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string buffer;
|
std::string buffer;
|
||||||
BinaryFile::GetNextNBytes(file, buffer.data(), length);
|
BinaryStream::getNextNBytes(file, buffer.data(), length);
|
||||||
byteCount += length;
|
byteCount += length;
|
||||||
|
|
||||||
const int value = ByteUtils::ToInt(buffer.data(), length);
|
const int value = ByteUtils::ToType<ByteUtils::DWord>(buffer.data(), length);
|
||||||
event->SetValue(value);
|
event->SetValue(value);
|
||||||
return byteCount;
|
return byteCount;
|
||||||
}
|
}
|
||||||
|
@ -118,15 +115,14 @@ int MidiMetaEventAdapter::ReadIntEvent(std::ifstream* file, MetaMidiEvent* event
|
||||||
int MidiMetaEventAdapter::ReadChannelPrefixEvent(std::ifstream* file, MetaMidiEvent* event, int& lastMidiChannel)
|
int MidiMetaEventAdapter::ReadChannelPrefixEvent(std::ifstream* file, MetaMidiEvent* event, int& lastMidiChannel)
|
||||||
{
|
{
|
||||||
unsigned byteCount = 0;
|
unsigned byteCount = 0;
|
||||||
int length = 0;
|
int length = *BinaryStream::getNextByteAsInt(file);
|
||||||
BinaryFile::GetNextByteAsInt(file, length);
|
|
||||||
byteCount ++;
|
byteCount ++;
|
||||||
|
|
||||||
std::string buffer;
|
std::string buffer;
|
||||||
BinaryFile::GetNextNBytes(file, buffer.data(), length);
|
BinaryStream::getNextNBytes(file, buffer.data(), length);
|
||||||
byteCount += length;
|
byteCount += length;
|
||||||
|
|
||||||
const int value = ByteUtils::ToInt(buffer.data(), length);
|
const int value = ByteUtils::ToType<ByteUtils::DWord>(buffer.data(), length);
|
||||||
event->SetValue(value);
|
event->SetValue(value);
|
||||||
lastMidiChannel = value;
|
lastMidiChannel = value;
|
||||||
return byteCount;
|
return byteCount;
|
||||||
|
@ -135,15 +131,14 @@ int MidiMetaEventAdapter::ReadChannelPrefixEvent(std::ifstream* file, MetaMidiEv
|
||||||
int MidiMetaEventAdapter::ReadTimeSignatureEvent(std::ifstream* file, MetaMidiEvent* event)
|
int MidiMetaEventAdapter::ReadTimeSignatureEvent(std::ifstream* file, MetaMidiEvent* event)
|
||||||
{
|
{
|
||||||
unsigned byteCount = 0;
|
unsigned byteCount = 0;
|
||||||
int length = 0;
|
int length = *BinaryStream::getNextByteAsInt(file);
|
||||||
BinaryFile::GetNextByteAsInt(file, length);
|
|
||||||
byteCount++;
|
byteCount++;
|
||||||
|
|
||||||
MidiTimeSignature timeSig;
|
MidiTimeSignature timeSig;
|
||||||
BinaryFile::GetNextByteAsInt(file, timeSig.mNumer);
|
timeSig.mNumer = *BinaryStream::getNextByteAsInt(file);
|
||||||
BinaryFile::GetNextByteAsInt(file, timeSig.mDenom);
|
timeSig.mDenom = *BinaryStream::getNextByteAsInt(file);
|
||||||
BinaryFile::GetNextByteAsInt(file, timeSig.mMetro);
|
timeSig.mMetro = *BinaryStream::getNextByteAsInt(file);
|
||||||
BinaryFile::GetNextByteAsInt(file, timeSig.mF32);
|
timeSig.mF32 = *BinaryStream::getNextByteAsInt(file);
|
||||||
byteCount +=4;
|
byteCount +=4;
|
||||||
|
|
||||||
if (length > 4)
|
if (length > 4)
|
||||||
|
@ -161,13 +156,12 @@ int MidiMetaEventAdapter::ReadTimeSignatureEvent(std::ifstream* file, MetaMidiEv
|
||||||
int MidiMetaEventAdapter::ReadKeySignatureEvent(std::ifstream* file, MetaMidiEvent* event)
|
int MidiMetaEventAdapter::ReadKeySignatureEvent(std::ifstream* file, MetaMidiEvent* event)
|
||||||
{
|
{
|
||||||
unsigned byteCount = 0;
|
unsigned byteCount = 0;
|
||||||
int length = 0;
|
int length = *BinaryStream::getNextByteAsInt(file);
|
||||||
BinaryFile::GetNextByteAsInt(file, length);
|
|
||||||
byteCount++;
|
byteCount++;
|
||||||
|
|
||||||
MidiKeySignature keySig;
|
MidiKeySignature keySig;
|
||||||
BinaryFile::GetNextByteAsInt(file, keySig.mSharpsFlats);
|
keySig.mSharpsFlats = *BinaryStream::getNextByteAsInt(file);
|
||||||
BinaryFile::GetNextByteAsInt(file, keySig.mMinor);
|
keySig.mMinor = *BinaryStream::getNextByteAsInt(file);
|
||||||
byteCount +=2;
|
byteCount +=2;
|
||||||
return byteCount;
|
return byteCount;
|
||||||
}
|
}
|
||||||
|
@ -175,16 +169,15 @@ int MidiMetaEventAdapter::ReadKeySignatureEvent(std::ifstream* file, MetaMidiEve
|
||||||
int MidiMetaEventAdapter::ReadTimeCodeEvent(std::ifstream* file, MetaMidiEvent* event)
|
int MidiMetaEventAdapter::ReadTimeCodeEvent(std::ifstream* file, MetaMidiEvent* event)
|
||||||
{
|
{
|
||||||
unsigned byteCount = 0;
|
unsigned byteCount = 0;
|
||||||
int length = 0;
|
int length = *BinaryStream::getNextByteAsInt(file);
|
||||||
BinaryFile::GetNextByteAsInt(file, length);
|
|
||||||
byteCount++;
|
byteCount++;
|
||||||
|
|
||||||
MidiSmtpeTimecode timeCode;
|
MidiSmtpeTimecode timeCode;
|
||||||
BinaryFile::GetNextByteAsInt(file, timeCode.mHr);
|
timeCode.mHr = *BinaryStream::getNextByteAsInt(file);
|
||||||
BinaryFile::GetNextByteAsInt(file, timeCode.mMin);
|
timeCode.mMin = *BinaryStream::getNextByteAsInt(file);
|
||||||
BinaryFile::GetNextByteAsInt(file, timeCode.mSec);
|
timeCode.mSec = *BinaryStream::getNextByteAsInt(file);
|
||||||
BinaryFile::GetNextByteAsInt(file, timeCode.mFrame);
|
timeCode.mFrame = *BinaryStream::getNextByteAsInt(file);
|
||||||
BinaryFile::GetNextByteAsInt(file, timeCode.mFrameFrac);
|
timeCode.mFrameFrac = *BinaryStream::getNextByteAsInt(file);
|
||||||
byteCount +=5;
|
byteCount +=5;
|
||||||
return byteCount;
|
return byteCount;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include "MidiDocument.h"
|
#include "MidiDocument.h"
|
||||||
#include "ByteUtils.h"
|
#include "ByteUtils.h"
|
||||||
#include "MidiTrack.h"
|
#include "MidiTrack.h"
|
||||||
#include "BinaryFile.h"
|
#include "BinaryStream.h"
|
||||||
#include "FileLogger.h"
|
#include "FileLogger.h"
|
||||||
#include "MidiElements.h"
|
#include "MidiElements.h"
|
||||||
#include "MidiTimeAdapter.h"
|
#include "MidiTimeAdapter.h"
|
||||||
|
@ -29,30 +29,30 @@ MidiDocument* MidiReader::GetDocument() const
|
||||||
|
|
||||||
bool MidiReader::ProcessHeader()
|
bool MidiReader::ProcessHeader()
|
||||||
{
|
{
|
||||||
if(!BinaryFile::CheckNextDWord(mFile->GetInHandle(), HeaderLabel))
|
if(!BinaryStream::checkNextDWord(mFile->GetInHandle(), HeaderLabel))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int length = 0;
|
const auto length = BinaryStream::getNextDWord(mFile->GetInHandle());
|
||||||
if(!BinaryFile::GetNextDWord(mFile->GetInHandle(), length))
|
if(!length)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int formatType { 0 };
|
const auto formatType = BinaryStream::getNextWord(mFile->GetInHandle());
|
||||||
if(!BinaryFile::GetNextWord(mFile->GetInHandle(), formatType))
|
if(!formatType)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
mDocument->SetFormatType(formatType);
|
mDocument->SetFormatType(*formatType);
|
||||||
|
|
||||||
int expectedTracks { 0 };
|
const auto expectedTracks = BinaryStream::getNextWord(mFile->GetInHandle());
|
||||||
if(!BinaryFile::GetNextWord(mFile->GetInHandle(), expectedTracks))
|
if(!expectedTracks)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
mDocument->SetExpectedTracks(expectedTracks);
|
mDocument->SetExpectedTracks(*expectedTracks);
|
||||||
|
|
||||||
MidiTimeDivision timeDivision;
|
MidiTimeDivision timeDivision;
|
||||||
MidiTimeAdapter::ReadTimeDivision(mFile->GetInHandle(), timeDivision);
|
MidiTimeAdapter::ReadTimeDivision(mFile->GetInHandle(), timeDivision);
|
||||||
|
@ -95,13 +95,13 @@ int MidiReader::ProcessEvent(MidiTrack* track)
|
||||||
|
|
||||||
bool MidiReader::ProcessTrackChunk(bool debug)
|
bool MidiReader::ProcessTrackChunk(bool debug)
|
||||||
{
|
{
|
||||||
if(!BinaryFile::CheckNextDWord(mFile->GetInHandle(), TrackChunkLabel))
|
if(!BinaryStream::checkNextDWord(mFile->GetInHandle(), TrackChunkLabel))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int chunkSize = 0;
|
const auto chunkSize = BinaryStream::getNextDWord(mFile->GetInHandle());
|
||||||
if(!BinaryFile::GetNextDWord(mFile->GetInHandle(), chunkSize))
|
if(!chunkSize)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -109,11 +109,11 @@ bool MidiReader::ProcessTrackChunk(bool debug)
|
||||||
unsigned byteCount = 0;
|
unsigned byteCount = 0;
|
||||||
auto track = std::make_unique<MidiTrack>();
|
auto track = std::make_unique<MidiTrack>();
|
||||||
unsigned iter_count = 0;
|
unsigned iter_count = 0;
|
||||||
while(byteCount < unsigned(chunkSize))
|
while(byteCount < static_cast<unsigned>(*chunkSize))
|
||||||
{
|
{
|
||||||
std::cout << "-------------" << std::endl;
|
std::cout << "-------------" << std::endl;
|
||||||
byteCount += ProcessEvent(track.get());
|
byteCount += ProcessEvent(track.get());
|
||||||
std::cout << "Track byte count: " << byteCount << " of " << chunkSize << std::endl;
|
std::cout << "Track byte count: " << byteCount << " of " << *chunkSize << std::endl;
|
||||||
if(debug && iter_count == 40)
|
if(debug && iter_count == 40)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "MidiTimeAdapter.h"
|
#include "MidiTimeAdapter.h"
|
||||||
|
|
||||||
#include "BinaryFile.h"
|
#include "BinaryStream.h"
|
||||||
#include "ByteUtils.h"
|
#include "ByteUtils.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
@ -13,7 +13,7 @@ int MidiTimeAdapter::ReadEventTimeDelta(std::ifstream* file, int& delta)
|
||||||
file->get(c);
|
file->get(c);
|
||||||
byteCount++;
|
byteCount++;
|
||||||
|
|
||||||
if(!ByteUtils::MSBIsOne(c))
|
if(!ByteUtils::MostSignificantBitIsOne(c))
|
||||||
{
|
{
|
||||||
delta = int(c);
|
delta = int(c);
|
||||||
std::cout << "Time delta final: " << delta << std::endl;
|
std::cout << "Time delta final: " << delta << std::endl;
|
||||||
|
@ -48,19 +48,19 @@ int MidiTimeAdapter::ReadEventTimeDelta(std::ifstream* file, int& delta)
|
||||||
|
|
||||||
int MidiTimeAdapter::ReadTimeDivision(std::ifstream* file, MidiTimeDivision& division)
|
int MidiTimeAdapter::ReadTimeDivision(std::ifstream* file, MidiTimeDivision& division)
|
||||||
{
|
{
|
||||||
int time_division;
|
const auto time_division = BinaryStream::getNextWord(file, false);
|
||||||
if(!BinaryFile::GetNextWord(file, time_division, false))
|
if(!time_division)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
division.mUseFps = ByteUtils::GetWordFirstBit(time_division);
|
division.mUseFps = ByteUtils::GetWordFirstBit(*time_division);
|
||||||
if (division.mUseFps)
|
if (division.mUseFps)
|
||||||
{
|
{
|
||||||
const int TOP_7_BITS = 0x7F00; // 0111 1111 - 0000 0000
|
const int TOP_7_BITS = 0x7F00; // 0111 1111 - 0000 0000
|
||||||
division.mFps = ((~time_division & TOP_7_BITS) >> 8) - 1; // Reverse 2complement of next 7 bits
|
division.mFps = ((~(*time_division) & TOP_7_BITS) >> 8) - 1; // Reverse 2complement of next 7 bits
|
||||||
}
|
}
|
||||||
|
|
||||||
division.mTicks = ByteUtils::GetWordLastByte(time_division);
|
division.mTicks = ByteUtils::GetWordLastByte(*time_division);
|
||||||
return 2; // Bytes advanced
|
return 2; // Bytes advanced
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,7 +84,7 @@ void GuiApplication::Run()
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
mDesktopManager->SetKeyboard(XcbKeyboard::Create());
|
mDesktopManager->SetKeyboard(XcbKeyboard::Create());
|
||||||
|
|
||||||
bool useOpenGl = true;
|
bool useOpenGl = false;
|
||||||
XcbInterface window_interface;
|
XcbInterface window_interface;
|
||||||
window_interface.SetUseOpenGl(useOpenGl);
|
window_interface.SetUseOpenGl(useOpenGl);
|
||||||
window_interface.Initialize(mDesktopManager.get());
|
window_interface.Initialize(mDesktopManager.get());
|
||||||
|
|
|
@ -1,24 +1,26 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <stdint.h>
|
||||||
|
|
||||||
class ByteUtils
|
class ByteUtils
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using Word = int;
|
using Word = int16_t;
|
||||||
using DWord = int;
|
using DWord = int32_t;
|
||||||
|
using QWord = int64_t;
|
||||||
|
|
||||||
static bool MSBIsOne(char c)
|
static bool MostSignificantBitIsOne(char c)
|
||||||
{
|
{
|
||||||
return c & (1 << 7);
|
return c & (1 << 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int GetWordFirstBit(const Word word)
|
static Word GetWordFirstBit(const Word word)
|
||||||
{
|
{
|
||||||
return word & ByteUtils::WORD_FIRST_BIT;
|
return word & ByteUtils::WORD_FIRST_BIT;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int GetWordLastByte(const Word word)
|
static Word GetWordLastByte(const Word word)
|
||||||
{
|
{
|
||||||
return word & ByteUtils::WORD_LAST_BYTE;
|
return word & ByteUtils::WORD_LAST_BYTE;
|
||||||
}
|
}
|
||||||
|
@ -38,30 +40,36 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ToInt(char* buffer, const unsigned size, bool reverse = true)
|
template<typename T>
|
||||||
|
static T ToType(char* buffer, bool reverse = true)
|
||||||
{
|
{
|
||||||
int result {0};
|
T result {0};
|
||||||
if(reverse)
|
if(reverse)
|
||||||
{
|
{
|
||||||
char reversed[sizeof(int)];
|
char reversed[sizeof(T)];
|
||||||
ReverseBuffer(buffer, reversed, size, sizeof(int));
|
ReverseBuffer(buffer, reversed, sizeof(T), sizeof(T));
|
||||||
std::memcpy(&result, reversed, sizeof(int));
|
std::memcpy(&result, reversed, sizeof(T));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::memcpy(&result, buffer, sizeof(int));
|
std::memcpy(&result, buffer, sizeof(T));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Word ToWord(char* buffer, bool reverse = true)
|
static Word ToWord(char* buffer, bool reverse = true)
|
||||||
{
|
{
|
||||||
return ToInt(buffer, BYTES_PER_WORD, reverse);
|
return ToType<Word>(buffer, reverse);
|
||||||
}
|
}
|
||||||
|
|
||||||
static DWord ToDWord(char* buffer, bool reverse = true)
|
static DWord ToDWord(char* buffer, bool reverse = true)
|
||||||
{
|
{
|
||||||
return ToInt(buffer, BYTES_PER_DWORD, reverse);
|
return ToType<DWord>(buffer, reverse);
|
||||||
|
}
|
||||||
|
|
||||||
|
static QWord ToQWord(char* buffer, bool reverse = true)
|
||||||
|
{
|
||||||
|
return ToType<QWord>(buffer, reverse);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool Compare(char* buffer, const char* tag, unsigned size)
|
static bool Compare(char* buffer, const char* tag, unsigned size)
|
||||||
|
@ -78,17 +86,15 @@ public:
|
||||||
|
|
||||||
static bool CompareDWords(char* buffer, const char* tag)
|
static bool CompareDWords(char* buffer, const char* tag)
|
||||||
{
|
{
|
||||||
return Compare(buffer, tag, BYTES_PER_DWORD);
|
return Compare(buffer, tag, sizeof(DWord));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool CompareWords(char* buffer, const char* tag)
|
static bool CompareWords(char* buffer, const char* tag)
|
||||||
{
|
{
|
||||||
return Compare(buffer, tag, BYTES_PER_WORD);
|
return Compare(buffer, tag, sizeof(Word));
|
||||||
}
|
}
|
||||||
|
|
||||||
static const int BYTES_PER_WORD = 2;
|
|
||||||
static const int BYTES_PER_DWORD = 4;
|
|
||||||
static const int BYTE_FIRST_BIT = 0x40; // 1000 0000
|
static const int BYTE_FIRST_BIT = 0x40; // 1000 0000
|
||||||
static const int WORD_FIRST_BIT = 0x8000; // 1000 0000 - 0000 0000
|
static const Word WORD_FIRST_BIT = 0x8000; // 1000 0000 - 0000 0000
|
||||||
static const int WORD_LAST_BYTE = 0x00FF; // 0000 0000 - 1111 1111
|
static const Word WORD_LAST_BYTE = 0x00FF; // 0000 0000 - 1111 1111
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,7 +5,6 @@ list(APPEND core_HEADERS
|
||||||
Color.h
|
Color.h
|
||||||
CommandLineArgs.h
|
CommandLineArgs.h
|
||||||
loggers/FileLogger.h
|
loggers/FileLogger.h
|
||||||
file_utilities/BinaryFile.h
|
|
||||||
file_utilities/File.h
|
file_utilities/File.h
|
||||||
file_utilities/FileFormats.h
|
file_utilities/FileFormats.h
|
||||||
StringUtils.h
|
StringUtils.h
|
||||||
|
@ -17,12 +16,12 @@ list(APPEND core_LIB_INCLUDES
|
||||||
Color.cpp
|
Color.cpp
|
||||||
CommandLineArgs.cpp
|
CommandLineArgs.cpp
|
||||||
loggers/FileLogger.cpp
|
loggers/FileLogger.cpp
|
||||||
file_utilities/BinaryFile.cpp
|
|
||||||
file_utilities/File.cpp
|
file_utilities/File.cpp
|
||||||
file_utilities/FileFormats.cpp
|
file_utilities/FileFormats.cpp
|
||||||
memory/SharedMemory.cpp
|
memory/SharedMemory.cpp
|
||||||
RandomUtils.cpp
|
RandomUtils.cpp
|
||||||
StringUtils.cpp
|
StringUtils.cpp
|
||||||
|
streams/BinaryStream.cpp
|
||||||
http/HttpResponse.cpp
|
http/HttpResponse.cpp
|
||||||
http/HttpHeader.cpp
|
http/HttpHeader.cpp
|
||||||
http/HttpRequest.cpp)
|
http/HttpRequest.cpp)
|
||||||
|
@ -35,6 +34,7 @@ target_include_directories(core PUBLIC
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/file_utilities"
|
"${CMAKE_CURRENT_SOURCE_DIR}/file_utilities"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/loggers"
|
"${CMAKE_CURRENT_SOURCE_DIR}/loggers"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/memory"
|
"${CMAKE_CURRENT_SOURCE_DIR}/memory"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/streams"
|
||||||
)
|
)
|
||||||
set_target_properties( core PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON )
|
set_target_properties( core PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON )
|
||||||
set_property(TARGET core PROPERTY FOLDER src)
|
set_property(TARGET core PROPERTY FOLDER src)
|
|
@ -1,88 +0,0 @@
|
||||||
#include "BinaryFile.h"
|
|
||||||
#include "ByteUtils.h"
|
|
||||||
|
|
||||||
bool BinaryFile::GetNextByteAsInt(std::ifstream* file, int& target)
|
|
||||||
{
|
|
||||||
char c;
|
|
||||||
file->get(c);
|
|
||||||
target = int(c);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BinaryFile::GetNextNBytes(std::ifstream* file, char* buffer, unsigned number)
|
|
||||||
{
|
|
||||||
char c;
|
|
||||||
for(unsigned idx=0; idx<number; idx++)
|
|
||||||
{
|
|
||||||
if(file->get(c))
|
|
||||||
{
|
|
||||||
buffer[idx] = c;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BinaryFile::GetNextWord(std::ifstream* file, char* buffer)
|
|
||||||
{
|
|
||||||
return GetNextNBytes(file, buffer, ByteUtils::BYTES_PER_WORD);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BinaryFile::GetNextDWord(std::ifstream* file, char* buffer)
|
|
||||||
{
|
|
||||||
return GetNextNBytes(file, buffer, ByteUtils::BYTES_PER_DWORD);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BinaryFile::GetNextWord(std::ifstream* file, int& target, bool reverse)
|
|
||||||
{
|
|
||||||
char buffer[ByteUtils::BYTES_PER_WORD];
|
|
||||||
if(!BinaryFile::GetNextWord(file, buffer))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
target = ByteUtils::ToWord(buffer, reverse);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BinaryFile::GetNextDWord(std::ifstream* file, int& target)
|
|
||||||
{
|
|
||||||
char buffer[ByteUtils::BYTES_PER_DWORD];
|
|
||||||
if(!BinaryFile::GetNextDWord(file, buffer))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
target = ByteUtils::ToDWord(buffer);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BinaryFile::CheckNextDWord(std::ifstream* file, const char* target)
|
|
||||||
{
|
|
||||||
char buffer[ByteUtils::BYTES_PER_DWORD];
|
|
||||||
if(!BinaryFile::GetNextDWord(file, buffer))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!ByteUtils::CompareDWords(buffer, target))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BinaryFile::GetNextString(std::ifstream* file, std::string& target, unsigned numBytes)
|
|
||||||
{
|
|
||||||
char c;
|
|
||||||
for(unsigned idx=0; idx<numBytes; idx++)
|
|
||||||
{
|
|
||||||
if(!file->get(c))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
target += c;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
class BinaryFile
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
static bool Write(std::ofstream* file, T data)
|
|
||||||
{
|
|
||||||
file->write(reinterpret_cast<char*>(&data), sizeof(data));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool GetNextByteAsInt(std::ifstream* file, int& target);
|
|
||||||
|
|
||||||
static bool GetNextNBytes(std::ifstream* file, char* buffer, unsigned numBytes);
|
|
||||||
|
|
||||||
static bool GetNextWord(std::ifstream* file, char* buffer);
|
|
||||||
|
|
||||||
static bool GetNextDWord(std::ifstream* file, char* buffer);
|
|
||||||
|
|
||||||
static bool GetNextWord(std::ifstream* file, int& target, bool reverse = true);
|
|
||||||
|
|
||||||
static bool GetNextDWord(std::ifstream* file, int& target);
|
|
||||||
|
|
||||||
static bool CheckNextDWord(std::ifstream* file, const char* target);
|
|
||||||
|
|
||||||
static bool GetNextString(std::ifstream* file, std::string& target, unsigned numBytes);
|
|
||||||
};
|
|
97
src/core/streams/BinaryStream.cpp
Normal file
97
src/core/streams/BinaryStream.cpp
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
#include "BinaryStream.h"
|
||||||
|
|
||||||
|
std::optional<int> BinaryStream::getNextByteAsInt(std::basic_istream<char>* stream)
|
||||||
|
{
|
||||||
|
return stream->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BinaryStream::getNextNBytes(std::basic_istream<char>* stream, char* buffer, unsigned number)
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
for(unsigned idx=0; idx<number; idx++)
|
||||||
|
{
|
||||||
|
if(stream->get(c))
|
||||||
|
{
|
||||||
|
buffer[idx] = c;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BinaryStream::getNextWord(std::basic_istream<char>* stream, char* buffer)
|
||||||
|
{
|
||||||
|
return getNextNBytes(stream, buffer, sizeof(ByteUtils::Word));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BinaryStream::getNextDWord(std::basic_istream<char>* stream, char* buffer)
|
||||||
|
{
|
||||||
|
return getNextNBytes(stream, buffer, sizeof(ByteUtils::DWord));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BinaryStream::getNextQWord(std::basic_istream<char>* stream, char* buffer)
|
||||||
|
{
|
||||||
|
return getNextNBytes(stream, buffer, sizeof(ByteUtils::QWord));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<ByteUtils::Word> BinaryStream::getNextWord(std::basic_istream<char>* stream, bool reverse)
|
||||||
|
{
|
||||||
|
char buffer[sizeof(ByteUtils::Word)];
|
||||||
|
if(!BinaryStream::getNextWord(stream, buffer))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return ByteUtils::ToWord(buffer, reverse);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<ByteUtils::DWord> BinaryStream::getNextDWord(std::basic_istream<char>* stream)
|
||||||
|
{
|
||||||
|
char buffer[sizeof(ByteUtils::DWord)];
|
||||||
|
if(!BinaryStream::getNextDWord(stream, buffer))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return ByteUtils::ToDWord(buffer);;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<ByteUtils::QWord> BinaryStream::getNextQWord(std::basic_istream<char>* stream)
|
||||||
|
{
|
||||||
|
char buffer[sizeof(ByteUtils::QWord)];
|
||||||
|
if(!BinaryStream::getNextQWord(stream, buffer))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return ByteUtils::ToQWord(buffer);;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BinaryStream::checkNextDWord(std::basic_istream<char>* stream, const char* target)
|
||||||
|
{
|
||||||
|
char buffer[sizeof(ByteUtils::DWord)];
|
||||||
|
if(!BinaryStream::getNextDWord(stream, buffer))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!ByteUtils::CompareDWords(buffer, target))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BinaryStream::getNextString(std::basic_istream<char>* stream, std::string& target, unsigned numBytes)
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
for(unsigned idx=0; idx<numBytes; idx++)
|
||||||
|
{
|
||||||
|
if(!stream->get(c))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
target += c;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
40
src/core/streams/BinaryStream.h
Normal file
40
src/core/streams/BinaryStream.h
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <istream>
|
||||||
|
#include <ostream>
|
||||||
|
#include <string>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
#include "ByteUtils.h"
|
||||||
|
|
||||||
|
class BinaryStream
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static bool write(std::basic_ostream<char>* stream, T data)
|
||||||
|
{
|
||||||
|
stream->write(reinterpret_cast<char*>(&data), sizeof(data));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::optional<int> getNextByteAsInt(std::basic_istream<char>* stream);
|
||||||
|
|
||||||
|
static bool getNextNBytes(std::basic_istream<char>* stream, char* buffer, unsigned numBytes);
|
||||||
|
|
||||||
|
static bool getNextWord(std::basic_istream<char>* stream, char* buffer);
|
||||||
|
|
||||||
|
static bool getNextDWord(std::basic_istream<char>* stream, char* buffer);
|
||||||
|
|
||||||
|
static bool getNextQWord(std::basic_istream<char>* stream, char* buffer);
|
||||||
|
|
||||||
|
static std::optional<ByteUtils::Word> getNextWord(std::basic_istream<char>* stream, bool reverse = true);
|
||||||
|
|
||||||
|
static std::optional<ByteUtils::DWord> getNextDWord(std::basic_istream<char>* stream);
|
||||||
|
|
||||||
|
static std::optional<ByteUtils::QWord> getNextQWord(std::basic_istream<char>* stream);
|
||||||
|
|
||||||
|
static bool checkNextDWord(std::basic_istream<char>* stream, const char* target);
|
||||||
|
|
||||||
|
static bool getNextString(std::basic_istream<char>* stream, std::string& target, unsigned numBytes);
|
||||||
|
};
|
15
src/fonts/CMakeLists.txt
Normal file
15
src/fonts/CMakeLists.txt
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
|
||||||
|
list(APPEND fonts_LIB_INCLUDES
|
||||||
|
FontReader.cpp
|
||||||
|
TrueTypeFont.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(fonts SHARED ${fonts_LIB_INCLUDES})
|
||||||
|
|
||||||
|
target_include_directories(fonts PUBLIC
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(fonts PUBLIC core)
|
||||||
|
set_property(TARGET fonts PROPERTY FOLDER src)
|
||||||
|
set_target_properties( fonts PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON )
|
181
src/fonts/FontReader.cpp
Normal file
181
src/fonts/FontReader.cpp
Normal file
|
@ -0,0 +1,181 @@
|
||||||
|
#include "FontReader.h"
|
||||||
|
#include "TrueTypeFont.h"
|
||||||
|
|
||||||
|
#include "File.h"
|
||||||
|
#include "BinaryStream.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
FontReader::~FontReader()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void FontReader::setPath(const std::string& path)
|
||||||
|
{
|
||||||
|
mPath = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FontReader::readOffsetSubtable()
|
||||||
|
{
|
||||||
|
mOffsetSubtable.scaler_type = *BinaryStream::getNextDWord(mFile->GetInHandle());
|
||||||
|
mCurrentOffset += 4;
|
||||||
|
|
||||||
|
mOffsetSubtable.num_tables = *BinaryStream::getNextWord(mFile->GetInHandle());
|
||||||
|
mCurrentOffset += 2;
|
||||||
|
|
||||||
|
mOffsetSubtable.search_range = *BinaryStream::getNextWord(mFile->GetInHandle());
|
||||||
|
mCurrentOffset += 2;
|
||||||
|
|
||||||
|
mOffsetSubtable.entry_selector = *BinaryStream::getNextWord(mFile->GetInHandle());
|
||||||
|
mCurrentOffset += 2;
|
||||||
|
|
||||||
|
mOffsetSubtable.range_shift = *BinaryStream::getNextWord(mFile->GetInHandle());
|
||||||
|
mCurrentOffset += 2;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FontReader::logOffsetSubtable()
|
||||||
|
{
|
||||||
|
std::stringstream sstr;
|
||||||
|
sstr << "Offset Subtable\n";
|
||||||
|
sstr << "scaler_type: " << mOffsetSubtable.scaler_type << "\n";
|
||||||
|
|
||||||
|
sstr << "num_tables: " << mOffsetSubtable.num_tables << "\n";
|
||||||
|
|
||||||
|
sstr << "search_range: " << mOffsetSubtable.search_range << "\n";
|
||||||
|
|
||||||
|
sstr << "entry_selector: " << mOffsetSubtable.entry_selector << "\n";
|
||||||
|
|
||||||
|
sstr << "range_shift: " << mOffsetSubtable.range_shift << "\n";
|
||||||
|
sstr << "************\n";
|
||||||
|
std::cout << sstr.str() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FontReader::readTableDirectory()
|
||||||
|
{
|
||||||
|
mTables.clear();
|
||||||
|
for (unsigned idx=0; idx<mOffsetSubtable.num_tables; idx++)
|
||||||
|
{
|
||||||
|
Table table;
|
||||||
|
BinaryStream::getNextString(mFile->GetInHandle(), table.name, 4);
|
||||||
|
mCurrentOffset += 4;
|
||||||
|
|
||||||
|
table.checksum = *BinaryStream::getNextDWord(mFile->GetInHandle());
|
||||||
|
mCurrentOffset += 4;
|
||||||
|
|
||||||
|
table.offset = *BinaryStream::getNextDWord(mFile->GetInHandle());
|
||||||
|
mCurrentOffset += 4;
|
||||||
|
|
||||||
|
table.length = *BinaryStream::getNextDWord(mFile->GetInHandle());
|
||||||
|
mCurrentOffset += 4;
|
||||||
|
|
||||||
|
logTable(table);
|
||||||
|
mTables.push_back(table);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FontReader::logTable(const Table& table)
|
||||||
|
{
|
||||||
|
std::stringstream sstr;
|
||||||
|
sstr << "Table\n";
|
||||||
|
sstr << "name: " << table.name << "\n";
|
||||||
|
|
||||||
|
sstr << "checksum: " << table.checksum << "\n";
|
||||||
|
|
||||||
|
sstr << "offset: " << table.offset << "\n";
|
||||||
|
|
||||||
|
sstr << "length: " << table.length << "\n";
|
||||||
|
sstr << "************\n";
|
||||||
|
std::cout << sstr.str() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FontReader::readTable()
|
||||||
|
{
|
||||||
|
std::string working_table_name;
|
||||||
|
for (const auto& table : mTables)
|
||||||
|
{
|
||||||
|
if (mCurrentOffset == table.offset)
|
||||||
|
{
|
||||||
|
working_table_name = table.name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (working_table_name == "head")
|
||||||
|
{
|
||||||
|
readHeadTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void FontReader::readHeadTable()
|
||||||
|
{
|
||||||
|
std::cout << "Reading head table" << std::endl;
|
||||||
|
|
||||||
|
TrueTypeFont::HeadTable table;
|
||||||
|
|
||||||
|
table.version = *BinaryStream::getNextDWord(mFile->GetInHandle());
|
||||||
|
table.fontRevision = *BinaryStream::getNextDWord(mFile->GetInHandle());
|
||||||
|
table.checksumAdjustment = *BinaryStream::getNextDWord(mFile->GetInHandle());
|
||||||
|
table.magicNumber = *BinaryStream::getNextDWord(mFile->GetInHandle());
|
||||||
|
mCurrentOffset += 16;
|
||||||
|
|
||||||
|
table.flags = *BinaryStream::getNextWord(mFile->GetInHandle());
|
||||||
|
table.unitsPerEm = *BinaryStream::getNextWord(mFile->GetInHandle());
|
||||||
|
mCurrentOffset += 4;
|
||||||
|
|
||||||
|
table.created = *BinaryStream::getNextQWord(mFile->GetInHandle());
|
||||||
|
table.modified = *BinaryStream::getNextQWord(mFile->GetInHandle());
|
||||||
|
mCurrentOffset += 16;
|
||||||
|
|
||||||
|
table.xMin = *BinaryStream::getNextWord(mFile->GetInHandle());
|
||||||
|
table.yMin = *BinaryStream::getNextWord(mFile->GetInHandle());
|
||||||
|
table.xMax = *BinaryStream::getNextWord(mFile->GetInHandle());
|
||||||
|
table.yMax = *BinaryStream::getNextWord(mFile->GetInHandle());
|
||||||
|
table.macStyle = *BinaryStream::getNextWord(mFile->GetInHandle());
|
||||||
|
table.lowestRecPPEM = *BinaryStream::getNextWord(mFile->GetInHandle());
|
||||||
|
table.fontDirectionHint = *BinaryStream::getNextWord(mFile->GetInHandle());
|
||||||
|
table.indexToLocFormat = *BinaryStream::getNextWord(mFile->GetInHandle());
|
||||||
|
table.glyphDataFormat = *BinaryStream::getNextWord(mFile->GetInHandle());
|
||||||
|
|
||||||
|
mCurrentOffset += 18;
|
||||||
|
|
||||||
|
auto working_ttf_font = dynamic_cast<TrueTypeFont*>(mWorkingFont.get());
|
||||||
|
working_ttf_font->setHeadTable(table);
|
||||||
|
std::cout << working_ttf_font->logHeadTable() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::unique_ptr<IFont> FontReader::read()
|
||||||
|
{
|
||||||
|
mWorkingFont = std::make_unique<TrueTypeFont>();
|
||||||
|
|
||||||
|
mFile = std::make_unique<File>(mPath);
|
||||||
|
mFile->Open(true);
|
||||||
|
|
||||||
|
readOffsetSubtable();
|
||||||
|
std::cout << "Current offset: " << mCurrentOffset << std::endl;
|
||||||
|
|
||||||
|
logOffsetSubtable();
|
||||||
|
|
||||||
|
readTableDirectory();
|
||||||
|
std::cout << "Current offset: " << mCurrentOffset << std::endl;
|
||||||
|
|
||||||
|
for (unsigned idx=0; idx<mOffsetSubtable.num_tables; idx++)
|
||||||
|
{
|
||||||
|
readTable();
|
||||||
|
std::cout << "Current offset: " << mCurrentOffset << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mFile->Close();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return std::move(mWorkingFont);
|
||||||
|
}
|
||||||
|
|
54
src/fonts/FontReader.h
Normal file
54
src/fonts/FontReader.h
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
#include "IFont.h"
|
||||||
|
#include "File.h"
|
||||||
|
|
||||||
|
class File;
|
||||||
|
|
||||||
|
class FontReader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
~FontReader();
|
||||||
|
void setPath(const std::string& path);
|
||||||
|
|
||||||
|
std::unique_ptr<IFont> read();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
struct OffsetSubtable
|
||||||
|
{
|
||||||
|
uint32_t scaler_type{0};
|
||||||
|
uint16_t num_tables{0};
|
||||||
|
uint16_t search_range{0};
|
||||||
|
uint16_t entry_selector{0};
|
||||||
|
uint16_t range_shift{0};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Table
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
unsigned checksum{0};
|
||||||
|
unsigned offset{0};
|
||||||
|
unsigned length{0};
|
||||||
|
};
|
||||||
|
|
||||||
|
bool readOffsetSubtable();
|
||||||
|
void logOffsetSubtable();
|
||||||
|
void logTable(const Table& table);
|
||||||
|
|
||||||
|
void readTableDirectory();
|
||||||
|
|
||||||
|
void readTable();
|
||||||
|
void readHeadTable();
|
||||||
|
|
||||||
|
unsigned mCurrentOffset{0};
|
||||||
|
OffsetSubtable mOffsetSubtable;
|
||||||
|
std::vector<Table> mTables;
|
||||||
|
|
||||||
|
std::unique_ptr<IFont> mWorkingFont;
|
||||||
|
std::unique_ptr<File> mFile;
|
||||||
|
std::string mPath;
|
||||||
|
};
|
8
src/fonts/IFont.h
Normal file
8
src/fonts/IFont.h
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
class IFont
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~IFont() = default;
|
||||||
|
virtual void dumpInfo() = 0;
|
||||||
|
};
|
31
src/fonts/TrueTypeFont.cpp
Normal file
31
src/fonts/TrueTypeFont.cpp
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#include "TrueTypeFont.h"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
std::string TrueTypeFont::logHeadTable() const
|
||||||
|
{
|
||||||
|
std::stringstream sstr;
|
||||||
|
sstr << "Head Table\n";
|
||||||
|
sstr << "version: " << mHeadTable.version << "\n";
|
||||||
|
sstr << "fontRevision: " << mHeadTable.fontRevision << "\n";
|
||||||
|
sstr << "checksumAdjustment: " << mHeadTable.checksumAdjustment << "\n";
|
||||||
|
sstr << "magicNumber: " << mHeadTable.magicNumber << "\n";
|
||||||
|
sstr << "flags: " << mHeadTable.flags << "\n";
|
||||||
|
sstr << "unitsPerEm: " << mHeadTable.unitsPerEm << "\n";
|
||||||
|
sstr << "created: " << mHeadTable.created << "\n";
|
||||||
|
sstr << "modified: " << mHeadTable.modified << "\n";
|
||||||
|
sstr << "xMin: " << mHeadTable.xMin << "\n";
|
||||||
|
sstr << "yMin: " << mHeadTable.yMin << "\n";
|
||||||
|
sstr << "xMax: " << mHeadTable.xMax << "\n";
|
||||||
|
sstr << "yMax: " << mHeadTable.yMax << "\n";
|
||||||
|
sstr << "macStyle: " << mHeadTable.macStyle << "\n";
|
||||||
|
sstr << "lowestRecPPEM: " << mHeadTable.lowestRecPPEM << "\n";
|
||||||
|
sstr << "fontDirectionHint: " << mHeadTable.fontDirectionHint << "\n";
|
||||||
|
sstr << "indexToLocFormat: " << mHeadTable.indexToLocFormat << "\n";
|
||||||
|
sstr << "glyphDataFormat: " << mHeadTable.glyphDataFormat << "\n";
|
||||||
|
return sstr.str();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
53
src/fonts/TrueTypeFont.h
Normal file
53
src/fonts/TrueTypeFont.h
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "IFont.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
class TrueTypeFont : public IFont
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
using Fixed = int32_t;
|
||||||
|
using LongDateTime = int64_t;
|
||||||
|
using FWord = int16_t;
|
||||||
|
|
||||||
|
// https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6head.html
|
||||||
|
struct HeadTable
|
||||||
|
{
|
||||||
|
Fixed version{0};
|
||||||
|
Fixed fontRevision{0};
|
||||||
|
uint32_t checksumAdjustment{0};
|
||||||
|
uint32_t magicNumber{0};
|
||||||
|
uint16_t flags{0};
|
||||||
|
uint16_t unitsPerEm{0};
|
||||||
|
LongDateTime created{0};
|
||||||
|
LongDateTime modified{0};
|
||||||
|
FWord xMin{0};
|
||||||
|
FWord yMin{0};
|
||||||
|
FWord xMax{0};
|
||||||
|
FWord yMax{0};
|
||||||
|
uint16_t macStyle{0};
|
||||||
|
uint16_t lowestRecPPEM{0};
|
||||||
|
int16_t fontDirectionHint{0};
|
||||||
|
int16_t indexToLocFormat{0};
|
||||||
|
int16_t glyphDataFormat{0};
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string logHeadTable() const;
|
||||||
|
|
||||||
|
void setHeadTable(const HeadTable& table)
|
||||||
|
{
|
||||||
|
mHeadTable = table;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dumpInfo() override
|
||||||
|
{
|
||||||
|
std::cout << "Got ttf" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
HeadTable mHeadTable;
|
||||||
|
};
|
|
@ -10,7 +10,9 @@ target_include_directories(test_utils PUBLIC
|
||||||
list(APPEND TestFiles
|
list(APPEND TestFiles
|
||||||
audio/TestAudioWriter.cpp
|
audio/TestAudioWriter.cpp
|
||||||
audio/TestMidiReader.cpp
|
audio/TestMidiReader.cpp
|
||||||
|
core/TestBinaryStream.cpp
|
||||||
database/TestDatabase.cpp
|
database/TestDatabase.cpp
|
||||||
|
fonts/TestFontReader.cpp
|
||||||
graphics/TestOpenGlRendering.cpp
|
graphics/TestOpenGlRendering.cpp
|
||||||
graphics/TestRasterizer.cpp
|
graphics/TestRasterizer.cpp
|
||||||
ipc/TestDbus.cpp
|
ipc/TestDbus.cpp
|
||||||
|
@ -26,7 +28,9 @@ list(APPEND TestFiles
|
||||||
list(APPEND TestNames
|
list(APPEND TestNames
|
||||||
TestAudioWriter
|
TestAudioWriter
|
||||||
TestMidiReader
|
TestMidiReader
|
||||||
|
TestBinaryStream
|
||||||
TestDatabase
|
TestDatabase
|
||||||
|
TestFontReader
|
||||||
TestOpenGlRendering
|
TestOpenGlRendering
|
||||||
TestRasterizer
|
TestRasterizer
|
||||||
TestDbus
|
TestDbus
|
||||||
|
@ -46,9 +50,9 @@ link_directories(${DBUS_LIBRARY_DIRS})
|
||||||
|
|
||||||
foreach(TestFile TestName IN ZIP_LISTS TestFiles TestNames)
|
foreach(TestFile TestName IN ZIP_LISTS TestFiles TestNames)
|
||||||
add_executable(${TestName} ${TestFile})
|
add_executable(${TestName} ${TestFile})
|
||||||
target_link_libraries(${TestName} PUBLIC core network image publishing video database geometry audio graphics web client test_utils ${DBUS_LIBRARIES})
|
target_link_libraries(${TestName} PUBLIC core fonts network image publishing video database geometry audio graphics web client test_utils ${DBUS_LIBRARIES})
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
|
|
||||||
add_executable(test_runner test_runner.cpp)
|
add_executable(test_runner test_runner.cpp)
|
||||||
target_link_libraries(test_runner PUBLIC core network database geometry audio graphics web client)
|
target_link_libraries(test_runner PUBLIC core fonts network database geometry audio graphics web client)
|
4
test/core/TestBinaryStream.cpp
Normal file
4
test/core/TestBinaryStream.cpp
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
17
test/fonts/TestFontReader.cpp
Normal file
17
test/fonts/TestFontReader.cpp
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#include "TrueTypeFont.h"
|
||||||
|
#include "FontReader.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
const auto font_path = "/usr/share/fonts/truetype/tlwg/TlwgTypo-Bold.ttf";
|
||||||
|
|
||||||
|
FontReader reader;
|
||||||
|
reader.setPath(font_path);
|
||||||
|
auto font = reader.read();
|
||||||
|
|
||||||
|
font->dumpInfo();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in a new issue