| @@ -10068,6 +10068,7 @@ private: | |||
| void intersectWithEdgeTableLine (const int y, const int* otherLine) throw(); | |||
| void clipEdgeTableLineToRange (int* line, int x1, int x2) throw(); | |||
| void sanitiseLevels (const bool useNonZeroWinding) throw(); | |||
| static void copyEdgeTableData (int* dest, const int destLineStride, const int* src, const int srcLineStride, int numLines) throw(); | |||
| }; | |||
| #endif // __JUCE_EDGETABLE_JUCEHEADER__ | |||
| @@ -10543,14 +10544,14 @@ public: | |||
| void createStrokedPath (Path& destPath, | |||
| const Path& sourcePath, | |||
| const AffineTransform& transform = AffineTransform::identity, | |||
| const float extraAccuracy = 1.0f) const throw(); | |||
| const float extraAccuracy = 1.0f) const; | |||
| void createDashedStroke (Path& destPath, | |||
| const Path& sourcePath, | |||
| const float* dashLengths, | |||
| int numDashLengths, | |||
| const AffineTransform& transform = AffineTransform::identity, | |||
| const float extraAccuracy = 1.0f) const throw(); | |||
| const float extraAccuracy = 1.0f) const; | |||
| float getStrokeThickness() const throw() { return thickness; } | |||
| @@ -110,19 +110,16 @@ bool AudioFormatReader::read (int** destSamples, | |||
| return true; | |||
| } | |||
| static void findMaxMin (const float* src, const int num, | |||
| float& maxVal, float& minVal) | |||
| static void findAudioBufferMaxMin (const float* const buffer, const int num, float& maxVal, float& minVal) throw() | |||
| { | |||
| float mn = src[0]; | |||
| float mn = buffer[0]; | |||
| float mx = mn; | |||
| for (int i = 1; i < num; ++i) | |||
| { | |||
| const float s = src[i]; | |||
| if (s > mx) | |||
| mx = s; | |||
| if (s < mn) | |||
| mn = s; | |||
| const float s = buffer[i]; | |||
| if (s > mx) mx = s; | |||
| if (s < mn) mn = s; | |||
| } | |||
| maxVal = mx; | |||
| @@ -167,13 +164,13 @@ void AudioFormatReader::readMaxLevels (int64 startSampleInFile, | |||
| startSampleInFile += numToDo; | |||
| float bufmin, bufmax; | |||
| findMaxMin ((float*) tempBuffer[0], numToDo, bufmax, bufmin); | |||
| findAudioBufferMaxMin ((float*) tempBuffer[0], numToDo, bufmax, bufmin); | |||
| lmin = jmin (lmin, bufmin); | |||
| lmax = jmax (lmax, bufmax); | |||
| if (numChannels > 1) | |||
| { | |||
| findMaxMin ((float*) tempBuffer[1], numToDo, bufmax, bufmin); | |||
| findAudioBufferMaxMin ((float*) tempBuffer[1], numToDo, bufmax, bufmin); | |||
| rmin = jmin (rmin, bufmin); | |||
| rmax = jmax (rmax, bufmax); | |||
| } | |||
| @@ -45,26 +45,25 @@ struct AudioThumbnailDataFormat | |||
| int sampleRate; | |||
| char future[16]; | |||
| char data[1]; | |||
| }; | |||
| #if JUCE_BIG_ENDIAN | |||
| static void swap (int& n) { n = (int) ByteOrder::swap ((uint32) n); } | |||
| static void swap (int64& n) { n = (int64) ByteOrder::swap ((uint64) n); } | |||
| #endif | |||
| void swapEndiannessIfNeeded() throw() | |||
| { | |||
| #if JUCE_BIG_ENDIAN | |||
| flip (samplesPerThumbSample); | |||
| flip (totalSamples); | |||
| flip (numFinishedSamples); | |||
| flip (numThumbnailSamples); | |||
| flip (numChannels); | |||
| flip (sampleRate); | |||
| #endif | |||
| } | |||
| static void swapEndiannessIfNeeded (AudioThumbnailDataFormat* const d) | |||
| { | |||
| (void) d; | |||
| #if JUCE_BIG_ENDIAN | |||
| swap (d->samplesPerThumbSample); | |||
| swap (d->totalSamples); | |||
| swap (d->numFinishedSamples); | |||
| swap (d->numThumbnailSamples); | |||
| swap (d->numChannels); | |||
| swap (d->sampleRate); | |||
| #endif | |||
| } | |||
| private: | |||
| #if JUCE_BIG_ENDIAN | |||
| static void flip (int& n) { n = (int) ByteOrder::swap ((uint32) n); } | |||
| static void flip (int64& n) { n = (int64) ByteOrder::swap ((uint64) n); } | |||
| #endif | |||
| }; | |||
| //============================================================================== | |||
| AudioThumbnail::AudioThumbnail (const int orginalSamplesPerThumbnailSample_, | |||
| @@ -197,7 +196,7 @@ void AudioThumbnail::loadFrom (InputStream& input) | |||
| input.readIntoMemoryBlock (data); | |||
| AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData(); | |||
| swapEndiannessIfNeeded (d); | |||
| d->swapEndiannessIfNeeded(); | |||
| if (! (d->thumbnailMagic[0] == 'j' | |||
| && d->thumbnailMagic[1] == 'a' | |||
| @@ -214,9 +213,9 @@ void AudioThumbnail::loadFrom (InputStream& input) | |||
| void AudioThumbnail::saveTo (OutputStream& output) const | |||
| { | |||
| AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData(); | |||
| swapEndiannessIfNeeded (d); | |||
| d->swapEndiannessIfNeeded(); | |||
| output.write (data.getData(), (int) data.getSize()); | |||
| swapEndiannessIfNeeded (d); | |||
| d->swapEndiannessIfNeeded(); | |||
| } | |||
| bool AudioThumbnail::initialiseFromAudioFile (AudioFormatReader& fileReader) | |||
| @@ -32,17 +32,137 @@ BEGIN_JUCE_NAMESPACE | |||
| //============================================================================== | |||
| struct TempoInfo | |||
| namespace MidiFileHelpers | |||
| { | |||
| double bpm, timestamp; | |||
| }; | |||
| static void writeVariableLengthInt (OutputStream& out, unsigned int v) | |||
| { | |||
| unsigned int buffer = v & 0x7F; | |||
| struct TimeSigInfo | |||
| { | |||
| int numerator, denominator; | |||
| double timestamp; | |||
| }; | |||
| while ((v >>= 7) != 0) | |||
| { | |||
| buffer <<= 8; | |||
| buffer |= ((v & 0x7F) | 0x80); | |||
| } | |||
| for (;;) | |||
| { | |||
| out.writeByte ((char) buffer); | |||
| if (buffer & 0x80) | |||
| buffer >>= 8; | |||
| else | |||
| break; | |||
| } | |||
| } | |||
| static bool parseMidiHeader (const char* &data, short& timeFormat, short& fileType, short& numberOfTracks) throw() | |||
| { | |||
| unsigned int ch = (int) ByteOrder::bigEndianInt (data); | |||
| data += 4; | |||
| if (ch != ByteOrder::bigEndianInt ("MThd")) | |||
| { | |||
| bool ok = false; | |||
| if (ch == ByteOrder::bigEndianInt ("RIFF")) | |||
| { | |||
| for (int i = 0; i < 8; ++i) | |||
| { | |||
| ch = ByteOrder::bigEndianInt (data); | |||
| data += 4; | |||
| if (ch == ByteOrder::bigEndianInt ("MThd")) | |||
| { | |||
| ok = true; | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| if (! ok) | |||
| return false; | |||
| } | |||
| unsigned int bytesRemaining = ByteOrder::bigEndianInt (data); | |||
| data += 4; | |||
| fileType = (short) ByteOrder::bigEndianShort (data); | |||
| data += 2; | |||
| numberOfTracks = (short) ByteOrder::bigEndianShort (data); | |||
| data += 2; | |||
| timeFormat = (short) ByteOrder::bigEndianShort (data); | |||
| data += 2; | |||
| bytesRemaining -= 6; | |||
| data += bytesRemaining; | |||
| return true; | |||
| } | |||
| static double convertTicksToSeconds (const double time, | |||
| const MidiMessageSequence& tempoEvents, | |||
| const int timeFormat) | |||
| { | |||
| if (timeFormat > 0) | |||
| { | |||
| int numer = 4, denom = 4; | |||
| double tempoTime = 0.0, correctedTempoTime = 0.0; | |||
| const double tickLen = 1.0 / (timeFormat & 0x7fff); | |||
| double secsPerTick = 0.5 * tickLen; | |||
| const int numEvents = tempoEvents.getNumEvents(); | |||
| for (int i = 0; i < numEvents; ++i) | |||
| { | |||
| const MidiMessage& m = tempoEvents.getEventPointer(i)->message; | |||
| if (time <= m.getTimeStamp()) | |||
| break; | |||
| if (timeFormat > 0) | |||
| { | |||
| correctedTempoTime = correctedTempoTime | |||
| + (m.getTimeStamp() - tempoTime) * secsPerTick; | |||
| } | |||
| else | |||
| { | |||
| correctedTempoTime = tickLen * m.getTimeStamp() / (((timeFormat & 0x7fff) >> 8) * (timeFormat & 0xff)); | |||
| } | |||
| tempoTime = m.getTimeStamp(); | |||
| if (m.isTempoMetaEvent()) | |||
| secsPerTick = tickLen * m.getTempoSecondsPerQuarterNote(); | |||
| else if (m.isTimeSignatureMetaEvent()) | |||
| m.getTimeSignatureInfo (numer, denom); | |||
| while (i + 1 < numEvents) | |||
| { | |||
| const MidiMessage& m2 = tempoEvents.getEventPointer(i + 1)->message; | |||
| if (m2.getTimeStamp() == tempoTime) | |||
| { | |||
| ++i; | |||
| if (m2.isTempoMetaEvent()) | |||
| secsPerTick = tickLen * m2.getTempoSecondsPerQuarterNote(); | |||
| else if (m2.isTimeSignatureMetaEvent()) | |||
| m2.getTimeSignatureInfo (numer, denom); | |||
| } | |||
| else | |||
| { | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| return correctedTempoTime + (time - tempoTime) * secsPerTick; | |||
| } | |||
| else | |||
| { | |||
| return time / (((timeFormat & 0x7fff) >> 8) * (timeFormat & 0xff)); | |||
| } | |||
| } | |||
| } | |||
| //============================================================================== | |||
| MidiFile::MidiFile() throw() | |||
| : timeFormat ((short) (unsigned short) 0xe728) | |||
| { | |||
| @@ -135,51 +255,6 @@ double MidiFile::getLastTimestamp() const | |||
| } | |||
| //============================================================================== | |||
| static bool parseMidiHeader (const char* &data, | |||
| short& timeFormat, | |||
| short& fileType, | |||
| short& numberOfTracks) | |||
| { | |||
| unsigned int ch = (int) ByteOrder::bigEndianInt (data); | |||
| data += 4; | |||
| if (ch != ByteOrder::bigEndianInt ("MThd")) | |||
| { | |||
| bool ok = false; | |||
| if (ch == ByteOrder::bigEndianInt ("RIFF")) | |||
| { | |||
| for (int i = 0; i < 8; ++i) | |||
| { | |||
| ch = ByteOrder::bigEndianInt (data); | |||
| data += 4; | |||
| if (ch == ByteOrder::bigEndianInt ("MThd")) | |||
| { | |||
| ok = true; | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| if (! ok) | |||
| return false; | |||
| } | |||
| unsigned int bytesRemaining = ByteOrder::bigEndianInt (data); | |||
| data += 4; | |||
| fileType = (short) ByteOrder::bigEndianShort (data); | |||
| data += 2; | |||
| numberOfTracks = (short) ByteOrder::bigEndianShort (data); | |||
| data += 2; | |||
| timeFormat = (short) ByteOrder::bigEndianShort (data); | |||
| data += 2; | |||
| bytesRemaining -= 6; | |||
| data += bytesRemaining; | |||
| return true; | |||
| } | |||
| bool MidiFile::readFrom (InputStream& sourceStream) | |||
| { | |||
| clear(); | |||
| @@ -194,7 +269,7 @@ bool MidiFile::readFrom (InputStream& sourceStream) | |||
| const char* d = (char*) data.getData(); | |||
| short fileType, expectedTracks; | |||
| if (size > 16 && parseMidiHeader (d, timeFormat, fileType, expectedTracks)) | |||
| if (size > 16 && MidiFileHelpers::parseMidiHeader (d, timeFormat, fileType, expectedTracks)) | |||
| { | |||
| size -= (int) (d - (char*) data.getData()); | |||
| @@ -291,70 +366,6 @@ void MidiFile::readNextTrack (const char* data, int size) | |||
| } | |||
| //============================================================================== | |||
| static double convertTicksToSeconds (const double time, | |||
| const MidiMessageSequence& tempoEvents, | |||
| const int timeFormat) | |||
| { | |||
| if (timeFormat > 0) | |||
| { | |||
| int numer = 4, denom = 4; | |||
| double tempoTime = 0.0, correctedTempoTime = 0.0; | |||
| const double tickLen = 1.0 / (timeFormat & 0x7fff); | |||
| double secsPerTick = 0.5 * tickLen; | |||
| const int numEvents = tempoEvents.getNumEvents(); | |||
| for (int i = 0; i < numEvents; ++i) | |||
| { | |||
| const MidiMessage& m = tempoEvents.getEventPointer(i)->message; | |||
| if (time <= m.getTimeStamp()) | |||
| break; | |||
| if (timeFormat > 0) | |||
| { | |||
| correctedTempoTime = correctedTempoTime | |||
| + (m.getTimeStamp() - tempoTime) * secsPerTick; | |||
| } | |||
| else | |||
| { | |||
| correctedTempoTime = tickLen * m.getTimeStamp() / (((timeFormat & 0x7fff) >> 8) * (timeFormat & 0xff)); | |||
| } | |||
| tempoTime = m.getTimeStamp(); | |||
| if (m.isTempoMetaEvent()) | |||
| secsPerTick = tickLen * m.getTempoSecondsPerQuarterNote(); | |||
| else if (m.isTimeSignatureMetaEvent()) | |||
| m.getTimeSignatureInfo (numer, denom); | |||
| while (i + 1 < numEvents) | |||
| { | |||
| const MidiMessage& m2 = tempoEvents.getEventPointer(i + 1)->message; | |||
| if (m2.getTimeStamp() == tempoTime) | |||
| { | |||
| ++i; | |||
| if (m2.isTempoMetaEvent()) | |||
| secsPerTick = tickLen * m2.getTempoSecondsPerQuarterNote(); | |||
| else if (m2.isTimeSignatureMetaEvent()) | |||
| m2.getTimeSignatureInfo (numer, denom); | |||
| } | |||
| else | |||
| { | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| return correctedTempoTime + (time - tempoTime) * secsPerTick; | |||
| } | |||
| else | |||
| { | |||
| return time / (((timeFormat & 0x7fff) >> 8) * (timeFormat & 0xff)); | |||
| } | |||
| } | |||
| void MidiFile::convertTimestampTicksToSeconds() | |||
| { | |||
| MidiMessageSequence tempoEvents; | |||
| @@ -369,35 +380,14 @@ void MidiFile::convertTimestampTicksToSeconds() | |||
| { | |||
| MidiMessage& m = ms.getEventPointer(j)->message; | |||
| m.setTimeStamp (convertTicksToSeconds (m.getTimeStamp(), | |||
| tempoEvents, | |||
| timeFormat)); | |||
| m.setTimeStamp (MidiFileHelpers::convertTicksToSeconds (m.getTimeStamp(), | |||
| tempoEvents, | |||
| timeFormat)); | |||
| } | |||
| } | |||
| } | |||
| //============================================================================== | |||
| static void writeVariableLengthInt (OutputStream& out, unsigned int v) | |||
| { | |||
| unsigned int buffer = v & 0x7F; | |||
| while ((v >>= 7) != 0) | |||
| { | |||
| buffer <<= 8; | |||
| buffer |= ((v & 0x7F) | 0x80); | |||
| } | |||
| for (;;) | |||
| { | |||
| out.writeByte ((char) buffer); | |||
| if (buffer & 0x80) | |||
| buffer >>= 8; | |||
| else | |||
| break; | |||
| } | |||
| } | |||
| bool MidiFile::writeTo (OutputStream& out) | |||
| { | |||
| out.writeIntBigEndian ((int) ByteOrder::bigEndianInt ("MThd")); | |||
| @@ -414,8 +404,6 @@ bool MidiFile::writeTo (OutputStream& out) | |||
| return true; | |||
| } | |||
| //============================================================================== | |||
| void MidiFile::writeTrack (OutputStream& mainOut, | |||
| const int trackNum) | |||
| { | |||
| @@ -432,7 +420,7 @@ void MidiFile::writeTrack (OutputStream& mainOut, | |||
| const int tick = roundToInt (mm.getTimeStamp()); | |||
| const int delta = jmax (0, tick - lastTick); | |||
| writeVariableLengthInt (out, delta); | |||
| MidiFileHelpers::writeVariableLengthInt (out, delta); | |||
| lastTick = tick; | |||
| const char statusByte = *(mm.getRawData()); | |||
| @@ -36,7 +36,7 @@ BEGIN_JUCE_NAMESPACE | |||
| //============================================================================== | |||
| MD5::MD5() | |||
| { | |||
| zeromem (result, sizeof (result)); | |||
| zerostruct (result); | |||
| } | |||
| MD5::MD5 (const MD5& other) | |||
| @@ -121,13 +121,62 @@ MD5::MD5 (const File& file) | |||
| if (fin != 0) | |||
| processStream (*fin, -1); | |||
| else | |||
| zeromem (result, sizeof (result)); | |||
| zerostruct (result); | |||
| } | |||
| MD5::~MD5() | |||
| { | |||
| } | |||
| //============================================================================== | |||
| namespace MD5Functions | |||
| { | |||
| static void encode (uint8* const output, const uint32* const input, const int numBytes) throw() | |||
| { | |||
| uint32* const o = (uint32*) output; | |||
| for (int i = 0; i < (numBytes >> 2); ++i) | |||
| o[i] = ByteOrder::swapIfBigEndian (input [i]); | |||
| } | |||
| static void decode (uint32* const output, const uint8* const input, const int numBytes) throw() | |||
| { | |||
| for (int i = 0; i < (numBytes >> 2); ++i) | |||
| output[i] = ByteOrder::littleEndianInt ((const char*) input + (i << 2)); | |||
| } | |||
| static inline uint32 F (const uint32 x, const uint32 y, const uint32 z) throw() { return (x & y) | (~x & z); } | |||
| static inline uint32 G (const uint32 x, const uint32 y, const uint32 z) throw() { return (x & z) | (y & ~z); } | |||
| static inline uint32 H (const uint32 x, const uint32 y, const uint32 z) throw() { return x ^ y ^ z; } | |||
| static inline uint32 I (const uint32 x, const uint32 y, const uint32 z) throw() { return y ^ (x | ~z); } | |||
| static inline uint32 rotateLeft (const uint32 x, const uint32 n) throw() { return (x << n) | (x >> (32 - n)); } | |||
| static void FF (uint32& a, const uint32 b, const uint32 c, const uint32 d, const uint32 x, const uint32 s, const uint32 ac) throw() | |||
| { | |||
| a += F (b, c, d) + x + ac; | |||
| a = rotateLeft (a, s) + b; | |||
| } | |||
| static void GG (uint32& a, const uint32 b, const uint32 c, const uint32 d, const uint32 x, const uint32 s, const uint32 ac) throw() | |||
| { | |||
| a += G (b, c, d) + x + ac; | |||
| a = rotateLeft (a, s) + b; | |||
| } | |||
| static void HH (uint32& a, const uint32 b, const uint32 c, const uint32 d, const uint32 x, const uint32 s, const uint32 ac) throw() | |||
| { | |||
| a += H (b, c, d) + x + ac; | |||
| a = rotateLeft (a, s) + b; | |||
| } | |||
| static void II (uint32& a, const uint32 b, const uint32 c, const uint32 d, const uint32 x, const uint32 s, const uint32 ac) throw() | |||
| { | |||
| a += I (b, c, d) + x + ac; | |||
| a = rotateLeft (a, s) + b; | |||
| } | |||
| } | |||
| //============================================================================== | |||
| MD5::ProcessContext::ProcessContext() | |||
| { | |||
| @@ -175,30 +224,11 @@ void MD5::ProcessContext::processBlock (const uint8* const data, size_t dataSize | |||
| memcpy (buffer + bufferPos, data + i, dataSize - i); | |||
| } | |||
| //============================================================================== | |||
| static void encode (uint8* const output, | |||
| const uint32* const input, | |||
| const int numBytes) | |||
| { | |||
| uint32* const o = (uint32*) output; | |||
| for (int i = 0; i < (numBytes >> 2); ++i) | |||
| o[i] = ByteOrder::swapIfBigEndian (input [i]); | |||
| } | |||
| static void decode (uint32* const output, | |||
| const uint8* const input, | |||
| const int numBytes) | |||
| { | |||
| for (int i = 0; i < (numBytes >> 2); ++i) | |||
| output[i] = ByteOrder::littleEndianInt ((const char*) input + (i << 2)); | |||
| } | |||
| //============================================================================== | |||
| void MD5::ProcessContext::finish (uint8* const result) | |||
| { | |||
| unsigned char encodedLength[8]; | |||
| encode (encodedLength, count, 8); | |||
| MD5Functions::encode (encodedLength, count, 8); | |||
| // Pad out to 56 mod 64. | |||
| const int index = (uint32) ((count[0] >> 3) & 0x3f); | |||
| @@ -213,48 +243,14 @@ void MD5::ProcessContext::finish (uint8* const result) | |||
| processBlock (encodedLength, 8); | |||
| encode (result, state, 16); | |||
| zeromem (buffer, sizeof (buffer)); | |||
| } | |||
| //============================================================================== | |||
| namespace MD5Functions | |||
| { | |||
| static inline uint32 F (const uint32 x, const uint32 y, const uint32 z) throw() { return (x & y) | (~x & z); } | |||
| static inline uint32 G (const uint32 x, const uint32 y, const uint32 z) throw() { return (x & z) | (y & ~z); } | |||
| static inline uint32 H (const uint32 x, const uint32 y, const uint32 z) throw() { return x ^ y ^ z; } | |||
| static inline uint32 I (const uint32 x, const uint32 y, const uint32 z) throw() { return y ^ (x | ~z); } | |||
| static inline uint32 rotateLeft (const uint32 x, const uint32 n) throw() { return (x << n) | (x >> (32 - n)); } | |||
| static void FF (uint32& a, const uint32 b, const uint32 c, const uint32 d, const uint32 x, const uint32 s, const uint32 ac) throw() | |||
| { | |||
| a += F (b, c, d) + x + ac; | |||
| a = rotateLeft (a, s) + b; | |||
| } | |||
| static void GG (uint32& a, const uint32 b, const uint32 c, const uint32 d, const uint32 x, const uint32 s, const uint32 ac) throw() | |||
| { | |||
| a += G (b, c, d) + x + ac; | |||
| a = rotateLeft (a, s) + b; | |||
| } | |||
| static void HH (uint32& a, const uint32 b, const uint32 c, const uint32 d, const uint32 x, const uint32 s, const uint32 ac) throw() | |||
| { | |||
| a += H (b, c, d) + x + ac; | |||
| a = rotateLeft (a, s) + b; | |||
| } | |||
| static void II (uint32& a, const uint32 b, const uint32 c, const uint32 d, const uint32 x, const uint32 s, const uint32 ac) throw() | |||
| { | |||
| a += I (b, c, d) + x + ac; | |||
| a = rotateLeft (a, s) + b; | |||
| } | |||
| MD5Functions::encode (result, state, sizeof (result)); | |||
| zerostruct (buffer); | |||
| } | |||
| void MD5::ProcessContext::transform (const uint8* const bufferToTransform) | |||
| { | |||
| using namespace MD5Functions; | |||
| uint32 a = state[0]; | |||
| uint32 b = state[1]; | |||
| uint32 c = state[2]; | |||
| @@ -269,7 +265,6 @@ void MD5::ProcessContext::transform (const uint8* const bufferToTransform) | |||
| S31 = 4, S32 = 11, S33 = 16, S34 = 23, S41 = 6, S42 = 10, S43 = 15, S44 = 21 | |||
| }; | |||
| using namespace MD5Functions; | |||
| FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ | |||
| FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ | |||
| FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ | |||
| @@ -349,18 +344,18 @@ void MD5::ProcessContext::transform (const uint8* const bufferToTransform) | |||
| //============================================================================== | |||
| const MemoryBlock MD5::getRawChecksumData() const | |||
| { | |||
| return MemoryBlock (result, 16); | |||
| return MemoryBlock (result, sizeof (result)); | |||
| } | |||
| const String MD5::toHexString() const | |||
| { | |||
| return String::toHexString (result, 16, 0); | |||
| return String::toHexString (result, sizeof (result), 0); | |||
| } | |||
| //============================================================================== | |||
| bool MD5::operator== (const MD5& other) const | |||
| { | |||
| return memcmp (result, other.result, 16) == 0; | |||
| return memcmp (result, other.result, sizeof (result)) == 0; | |||
| } | |||
| bool MD5::operator!= (const MD5& other) const | |||
| @@ -33,85 +33,88 @@ BEGIN_JUCE_NAMESPACE | |||
| //============================================================================== | |||
| static void createSmallSieve (const int numBits, BitArray& result) throw() | |||
| namespace PrimesHelpers | |||
| { | |||
| result.setBit (numBits); | |||
| result.clearBit (numBits); // to enlarge the array | |||
| static void createSmallSieve (const int numBits, BitArray& result) throw() | |||
| { | |||
| result.setBit (numBits); | |||
| result.clearBit (numBits); // to enlarge the array | |||
| result.setBit (0); | |||
| int n = 2; | |||
| result.setBit (0); | |||
| int n = 2; | |||
| do | |||
| { | |||
| for (int i = n + n; i < numBits; i += n) | |||
| result.setBit (i); | |||
| do | |||
| { | |||
| for (int i = n + n; i < numBits; i += n) | |||
| result.setBit (i); | |||
| n = result.findNextClearBit (n + 1); | |||
| n = result.findNextClearBit (n + 1); | |||
| } | |||
| while (n <= (numBits >> 1)); | |||
| } | |||
| while (n <= (numBits >> 1)); | |||
| } | |||
| static void bigSieve (const BitArray& base, | |||
| const int numBits, | |||
| BitArray& result, | |||
| const BitArray& smallSieve, | |||
| const int smallSieveSize) throw() | |||
| { | |||
| jassert (! base[0]); // must be even! | |||
| static void bigSieve (const BitArray& base, | |||
| const int numBits, | |||
| BitArray& result, | |||
| const BitArray& smallSieve, | |||
| const int smallSieveSize) throw() | |||
| { | |||
| jassert (! base[0]); // must be even! | |||
| result.setBit (numBits); | |||
| result.clearBit (numBits); // to enlarge the array | |||
| result.setBit (numBits); | |||
| result.clearBit (numBits); // to enlarge the array | |||
| int index = smallSieve.findNextClearBit (0); | |||
| int index = smallSieve.findNextClearBit (0); | |||
| do | |||
| { | |||
| const int prime = (index << 1) + 1; | |||
| do | |||
| { | |||
| const int prime = (index << 1) + 1; | |||
| BitArray r (base); | |||
| BitArray remainder; | |||
| r.divideBy (prime, remainder); | |||
| BitArray r (base); | |||
| BitArray remainder; | |||
| r.divideBy (prime, remainder); | |||
| int i = prime - remainder.getBitRangeAsInt (0, 32); | |||
| int i = prime - remainder.getBitRangeAsInt (0, 32); | |||
| if (r.isEmpty()) | |||
| i += prime; | |||
| if (r.isEmpty()) | |||
| i += prime; | |||
| if ((i & 1) == 0) | |||
| i += prime; | |||
| if ((i & 1) == 0) | |||
| i += prime; | |||
| i = (i - 1) >> 1; | |||
| i = (i - 1) >> 1; | |||
| while (i < numBits) | |||
| { | |||
| result.setBit (i); | |||
| i += prime; | |||
| } | |||
| while (i < numBits) | |||
| { | |||
| result.setBit (i); | |||
| i += prime; | |||
| } | |||
| index = smallSieve.findNextClearBit (index + 1); | |||
| index = smallSieve.findNextClearBit (index + 1); | |||
| } | |||
| while (index < smallSieveSize); | |||
| } | |||
| while (index < smallSieveSize); | |||
| } | |||
| static bool findCandidate (const BitArray& base, | |||
| const BitArray& sieve, | |||
| const int numBits, | |||
| BitArray& result, | |||
| const int certainty) throw() | |||
| { | |||
| for (int i = 0; i < numBits; ++i) | |||
| static bool findCandidate (const BitArray& base, | |||
| const BitArray& sieve, | |||
| const int numBits, | |||
| BitArray& result, | |||
| const int certainty) throw() | |||
| { | |||
| if (! sieve[i]) | |||
| for (int i = 0; i < numBits; ++i) | |||
| { | |||
| result = base; | |||
| result.add (BitArray ((unsigned int) ((i << 1) + 1))); | |||
| if (! sieve[i]) | |||
| { | |||
| result = base; | |||
| result.add (BitArray ((unsigned int) ((i << 1) + 1))); | |||
| if (Primes::isProbablyPrime (result, certainty)) | |||
| return true; | |||
| if (Primes::isProbablyPrime (result, certainty)) | |||
| return true; | |||
| } | |||
| } | |||
| } | |||
| return false; | |||
| return false; | |||
| } | |||
| } | |||
| //============================================================================== | |||
| @@ -120,6 +123,7 @@ const BitArray Primes::createProbablePrime (const int bitLength, | |||
| const int* randomSeeds, | |||
| int numRandomSeeds) throw() | |||
| { | |||
| using namespace PrimesHelpers; | |||
| int defaultSeeds [16]; | |||
| if (numRandomSeeds <= 0) | |||
| @@ -178,6 +182,8 @@ const BitArray Primes::createProbablePrime (const int bitLength, | |||
| static bool passesMillerRabin (const BitArray& n, int iterations) throw() | |||
| { | |||
| using namespace PrimesHelpers; | |||
| const BitArray one (1); | |||
| const BitArray two (2); | |||
| @@ -41,58 +41,61 @@ KeyboardFocusTraverser::~KeyboardFocusTraverser() | |||
| } | |||
| //============================================================================== | |||
| // This will sort a set of components, so that they are ordered in terms of | |||
| // left-to-right and then top-to-bottom. | |||
| class ScreenPositionComparator | |||
| namespace KeyboardFocusHelpers | |||
| { | |||
| public: | |||
| ScreenPositionComparator() {} | |||
| static int compareElements (const Component* const first, const Component* const second) throw() | |||
| // This will sort a set of components, so that they are ordered in terms of | |||
| // left-to-right and then top-to-bottom. | |||
| class ScreenPositionComparator | |||
| { | |||
| int explicitOrder1 = first->getExplicitFocusOrder(); | |||
| if (explicitOrder1 <= 0) | |||
| explicitOrder1 = std::numeric_limits<int>::max() / 2; | |||
| public: | |||
| ScreenPositionComparator() {} | |||
| int explicitOrder2 = second->getExplicitFocusOrder(); | |||
| if (explicitOrder2 <= 0) | |||
| explicitOrder2 = std::numeric_limits<int>::max() / 2; | |||
| static int compareElements (const Component* const first, const Component* const second) throw() | |||
| { | |||
| int explicitOrder1 = first->getExplicitFocusOrder(); | |||
| if (explicitOrder1 <= 0) | |||
| explicitOrder1 = std::numeric_limits<int>::max() / 2; | |||
| if (explicitOrder1 != explicitOrder2) | |||
| return explicitOrder1 - explicitOrder2; | |||
| int explicitOrder2 = second->getExplicitFocusOrder(); | |||
| if (explicitOrder2 <= 0) | |||
| explicitOrder2 = std::numeric_limits<int>::max() / 2; | |||
| const int diff = first->getY() - second->getY(); | |||
| if (explicitOrder1 != explicitOrder2) | |||
| return explicitOrder1 - explicitOrder2; | |||
| return (diff == 0) ? first->getX() - second->getX() | |||
| : diff; | |||
| } | |||
| }; | |||
| const int diff = first->getY() - second->getY(); | |||
| static void findAllFocusableComponents (Component* const parent, Array <Component*>& comps) | |||
| { | |||
| if (parent->getNumChildComponents() > 0) | |||
| { | |||
| Array <Component*> localComps; | |||
| ScreenPositionComparator comparator; | |||
| return (diff == 0) ? first->getX() - second->getX() | |||
| : diff; | |||
| } | |||
| }; | |||
| int i; | |||
| for (i = parent->getNumChildComponents(); --i >= 0;) | |||
| static void findAllFocusableComponents (Component* const parent, Array <Component*>& comps) | |||
| { | |||
| if (parent->getNumChildComponents() > 0) | |||
| { | |||
| Component* const c = parent->getChildComponent (i); | |||
| Array <Component*> localComps; | |||
| ScreenPositionComparator comparator; | |||
| if (c->isVisible() && c->isEnabled()) | |||
| localComps.addSorted (comparator, c); | |||
| } | |||
| int i; | |||
| for (i = parent->getNumChildComponents(); --i >= 0;) | |||
| { | |||
| Component* const c = parent->getChildComponent (i); | |||
| for (i = 0; i < localComps.size(); ++i) | |||
| { | |||
| Component* const c = localComps.getUnchecked (i); | |||
| if (c->isVisible() && c->isEnabled()) | |||
| localComps.addSorted (comparator, c); | |||
| } | |||
| if (c->getWantsKeyboardFocus()) | |||
| comps.add (c); | |||
| for (i = 0; i < localComps.size(); ++i) | |||
| { | |||
| Component* const c = localComps.getUnchecked (i); | |||
| if (c->getWantsKeyboardFocus()) | |||
| comps.add (c); | |||
| if (! c->isFocusContainer()) | |||
| findAllFocusableComponents (c, comps); | |||
| if (! c->isFocusContainer()) | |||
| findAllFocusableComponents (c, comps); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -109,7 +112,7 @@ static Component* getIncrementedComponent (Component* const current, const int d | |||
| if (focusContainer != 0) | |||
| { | |||
| Array <Component*> comps; | |||
| findAllFocusableComponents (focusContainer, comps); | |||
| KeyboardFocusHelpers::findAllFocusableComponents (focusContainer, comps); | |||
| if (comps.size() > 0) | |||
| { | |||
| @@ -137,7 +140,7 @@ Component* KeyboardFocusTraverser::getDefaultComponent (Component* parentCompone | |||
| Array <Component*> comps; | |||
| if (parentComponent != 0) | |||
| findAllFocusableComponents (parentComponent, comps); | |||
| KeyboardFocusHelpers::findAllFocusableComponents (parentComponent, comps); | |||
| return comps.getFirst(); | |||
| } | |||
| @@ -34,17 +34,6 @@ BEGIN_JUCE_NAMESPACE | |||
| const int juce_edgeTableDefaultEdgesPerLine = 32; | |||
| //============================================================================== | |||
| static void copyEdgeTableData (int* dest, const int destLineStride, const int* src, const int srcLineStride, int numLines) throw() | |||
| { | |||
| while (--numLines >= 0) | |||
| { | |||
| memcpy (dest, src, (src[0] * 2 + 1) * sizeof (int)); | |||
| src += srcLineStride; | |||
| dest += destLineStride; | |||
| } | |||
| } | |||
| //============================================================================== | |||
| EdgeTable::EdgeTable (const Rectangle<int>& bounds_, | |||
| const Path& path, const AffineTransform& transform) throw() | |||
| @@ -277,6 +266,16 @@ EdgeTable::~EdgeTable() throw() | |||
| } | |||
| //============================================================================== | |||
| void EdgeTable::copyEdgeTableData (int* dest, const int destLineStride, const int* src, const int srcLineStride, int numLines) throw() | |||
| { | |||
| while (--numLines >= 0) | |||
| { | |||
| memcpy (dest, src, (src[0] * 2 + 1) * sizeof (int)); | |||
| src += srcLineStride; | |||
| dest += destLineStride; | |||
| } | |||
| } | |||
| void EdgeTable::sanitiseLevels (const bool useNonZeroWinding) throw() | |||
| { | |||
| // Convert the table from relative windings to absolute levels.. | |||
| @@ -205,6 +205,7 @@ private: | |||
| void intersectWithEdgeTableLine (const int y, const int* otherLine) throw(); | |||
| void clipEdgeTableLineToRange (int* line, int x1, int x2) throw(); | |||
| void sanitiseLevels (const bool useNonZeroWinding) throw(); | |||
| static void copyEdgeTableData (int* dest, const int destLineStride, const int* src, const int srcLineStride, int numLines) throw(); | |||
| }; | |||
| @@ -191,283 +191,286 @@ static bool lineIntersection (const float x1, const float y1, | |||
| return true; | |||
| } | |||
| // part of stroke drawing stuff | |||
| static void addEdgeAndJoint (Path& destPath, | |||
| const PathStrokeType::JointStyle style, | |||
| const float maxMiterExtensionSquared, const float width, | |||
| const float x1, const float y1, | |||
| const float x2, const float y2, | |||
| const float x3, const float y3, | |||
| const float x4, const float y4, | |||
| const float midX, const float midY) throw() | |||
| namespace PathFunctions | |||
| { | |||
| if (style == PathStrokeType::beveled | |||
| || (x3 == x4 && y3 == y4) | |||
| || (x1 == x2 && y1 == y2)) | |||
| // part of stroke drawing stuff | |||
| static void addEdgeAndJoint (Path& destPath, | |||
| const PathStrokeType::JointStyle style, | |||
| const float maxMiterExtensionSquared, const float width, | |||
| const float x1, const float y1, | |||
| const float x2, const float y2, | |||
| const float x3, const float y3, | |||
| const float x4, const float y4, | |||
| const float midX, const float midY) | |||
| { | |||
| destPath.lineTo (x2, y2); | |||
| destPath.lineTo (x3, y3); | |||
| } | |||
| else | |||
| { | |||
| float jx, jy, distanceBeyondLine1EndSquared; | |||
| // if they intersect, use this point.. | |||
| if (lineIntersection (x1, y1, x2, y2, | |||
| x3, y3, x4, y4, | |||
| jx, jy, distanceBeyondLine1EndSquared)) | |||
| if (style == PathStrokeType::beveled | |||
| || (x3 == x4 && y3 == y4) | |||
| || (x1 == x2 && y1 == y2)) | |||
| { | |||
| destPath.lineTo (jx, jy); | |||
| destPath.lineTo (x2, y2); | |||
| destPath.lineTo (x3, y3); | |||
| } | |||
| else | |||
| { | |||
| if (style == PathStrokeType::mitered) | |||
| float jx, jy, distanceBeyondLine1EndSquared; | |||
| // if they intersect, use this point.. | |||
| if (lineIntersection (x1, y1, x2, y2, | |||
| x3, y3, x4, y4, | |||
| jx, jy, distanceBeyondLine1EndSquared)) | |||
| { | |||
| if (distanceBeyondLine1EndSquared < maxMiterExtensionSquared | |||
| && distanceBeyondLine1EndSquared > 0.0f) | |||
| { | |||
| destPath.lineTo (jx, jy); | |||
| } | |||
| else | |||
| { | |||
| // the end sticks out too far, so just use a blunt joint | |||
| destPath.lineTo (x2, y2); | |||
| destPath.lineTo (x3, y3); | |||
| } | |||
| destPath.lineTo (jx, jy); | |||
| } | |||
| else | |||
| { | |||
| // curved joints | |||
| float angle1 = atan2f (x2 - midX, y2 - midY); | |||
| float angle2 = atan2f (x3 - midX, y3 - midY); | |||
| const float angleIncrement = 0.1f; | |||
| destPath.lineTo (x2, y2); | |||
| if (fabs (angle1 - angle2) > angleIncrement) | |||
| if (style == PathStrokeType::mitered) | |||
| { | |||
| if (angle2 > angle1 + float_Pi | |||
| || (angle2 < angle1 && angle2 >= angle1 - float_Pi)) | |||
| if (distanceBeyondLine1EndSquared < maxMiterExtensionSquared | |||
| && distanceBeyondLine1EndSquared > 0.0f) | |||
| { | |||
| destPath.lineTo (jx, jy); | |||
| } | |||
| else | |||
| { | |||
| if (angle2 > angle1) | |||
| angle2 -= float_Pi * 2.0f; | |||
| // the end sticks out too far, so just use a blunt joint | |||
| destPath.lineTo (x2, y2); | |||
| destPath.lineTo (x3, y3); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| // curved joints | |||
| float angle1 = atan2f (x2 - midX, y2 - midY); | |||
| float angle2 = atan2f (x3 - midX, y3 - midY); | |||
| const float angleIncrement = 0.1f; | |||
| jassert (angle1 <= angle2 + float_Pi); | |||
| destPath.lineTo (x2, y2); | |||
| angle1 -= angleIncrement; | |||
| while (angle1 > angle2) | |||
| if (fabs (angle1 - angle2) > angleIncrement) | |||
| { | |||
| if (angle2 > angle1 + float_Pi | |||
| || (angle2 < angle1 && angle2 >= angle1 - float_Pi)) | |||
| { | |||
| destPath.lineTo (midX + width * sinf (angle1), | |||
| midY + width * cosf (angle1)); | |||
| if (angle2 > angle1) | |||
| angle2 -= float_Pi * 2.0f; | |||
| angle1 -= angleIncrement; | |||
| } | |||
| } | |||
| else | |||
| { | |||
| if (angle1 > angle2) | |||
| angle1 -= float_Pi * 2.0f; | |||
| jassert (angle1 <= angle2 + float_Pi); | |||
| jassert (angle1 >= angle2 - float_Pi); | |||
| angle1 -= angleIncrement; | |||
| while (angle1 > angle2) | |||
| { | |||
| destPath.lineTo (midX + width * sinf (angle1), | |||
| midY + width * cosf (angle1)); | |||
| angle1 += angleIncrement; | |||
| while (angle1 < angle2) | |||
| angle1 -= angleIncrement; | |||
| } | |||
| } | |||
| else | |||
| { | |||
| destPath.lineTo (midX + width * sinf (angle1), | |||
| midY + width * cosf (angle1)); | |||
| if (angle1 > angle2) | |||
| angle1 -= float_Pi * 2.0f; | |||
| jassert (angle1 >= angle2 - float_Pi); | |||
| angle1 += angleIncrement; | |||
| while (angle1 < angle2) | |||
| { | |||
| destPath.lineTo (midX + width * sinf (angle1), | |||
| midY + width * cosf (angle1)); | |||
| angle1 += angleIncrement; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| destPath.lineTo (x3, y3); | |||
| destPath.lineTo (x3, y3); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| static inline void addLineEnd (Path& destPath, | |||
| const PathStrokeType::EndCapStyle style, | |||
| const float x1, const float y1, | |||
| const float x2, const float y2, | |||
| const float width) throw() | |||
| { | |||
| if (style == PathStrokeType::butt) | |||
| static void addLineEnd (Path& destPath, | |||
| const PathStrokeType::EndCapStyle style, | |||
| const float x1, const float y1, | |||
| const float x2, const float y2, | |||
| const float width) | |||
| { | |||
| destPath.lineTo (x2, y2); | |||
| } | |||
| else | |||
| { | |||
| float offx1, offy1, offx2, offy2; | |||
| float dx = x2 - x1; | |||
| float dy = y2 - y1; | |||
| const float len = juce_hypotf (dx, dy); | |||
| if (len == 0) | |||
| if (style == PathStrokeType::butt) | |||
| { | |||
| offx1 = offx2 = x1; | |||
| offy1 = offy2 = y1; | |||
| } | |||
| else | |||
| { | |||
| const float offset = width / len; | |||
| dx *= offset; | |||
| dy *= offset; | |||
| offx1 = x1 + dy; | |||
| offy1 = y1 - dx; | |||
| offx2 = x2 + dy; | |||
| offy2 = y2 - dx; | |||
| } | |||
| if (style == PathStrokeType::square) | |||
| { | |||
| // sqaure ends | |||
| destPath.lineTo (offx1, offy1); | |||
| destPath.lineTo (offx2, offy2); | |||
| destPath.lineTo (x2, y2); | |||
| } | |||
| else | |||
| { | |||
| // rounded ends | |||
| const float midx = (offx1 + offx2) * 0.5f; | |||
| const float midy = (offy1 + offy2) * 0.5f; | |||
| float offx1, offy1, offx2, offy2; | |||
| destPath.cubicTo (x1 + (offx1 - x1) * 0.55f, y1 + (offy1 - y1) * 0.55f, | |||
| offx1 + (midx - offx1) * 0.45f, offy1 + (midy - offy1) * 0.45f, | |||
| midx, midy); | |||
| float dx = x2 - x1; | |||
| float dy = y2 - y1; | |||
| const float len = juce_hypotf (dx, dy); | |||
| destPath.cubicTo (midx + (offx2 - midx) * 0.55f, midy + (offy2 - midy) * 0.55f, | |||
| offx2 + (x2 - offx2) * 0.45f, offy2 + (y2 - offy2) * 0.45f, | |||
| x2, y2); | |||
| } | |||
| } | |||
| } | |||
| if (len == 0) | |||
| { | |||
| offx1 = offx2 = x1; | |||
| offy1 = offy2 = y1; | |||
| } | |||
| else | |||
| { | |||
| const float offset = width / len; | |||
| dx *= offset; | |||
| dy *= offset; | |||
| struct LineSection | |||
| { | |||
| LineSection() {} | |||
| LineSection (int) {} | |||
| float x1, y1, x2, y2; // original line | |||
| float lx1, ly1, lx2, ly2; // the left-hand stroke | |||
| float rx1, ry1, rx2, ry2; // the right-hand stroke | |||
| }; | |||
| static void addSubPath (Path& destPath, const Array <LineSection>& subPath, | |||
| const bool isClosed, | |||
| const float width, const float maxMiterExtensionSquared, | |||
| const PathStrokeType::JointStyle jointStyle, const PathStrokeType::EndCapStyle endStyle) throw() | |||
| { | |||
| jassert (subPath.size() > 0); | |||
| offx1 = x1 + dy; | |||
| offy1 = y1 - dx; | |||
| offx2 = x2 + dy; | |||
| offy2 = y2 - dx; | |||
| } | |||
| const LineSection& firstLine = subPath.getReference (0); | |||
| if (style == PathStrokeType::square) | |||
| { | |||
| // sqaure ends | |||
| destPath.lineTo (offx1, offy1); | |||
| destPath.lineTo (offx2, offy2); | |||
| destPath.lineTo (x2, y2); | |||
| } | |||
| else | |||
| { | |||
| // rounded ends | |||
| const float midx = (offx1 + offx2) * 0.5f; | |||
| const float midy = (offy1 + offy2) * 0.5f; | |||
| float lastX1 = firstLine.lx1; | |||
| float lastY1 = firstLine.ly1; | |||
| float lastX2 = firstLine.lx2; | |||
| float lastY2 = firstLine.ly2; | |||
| destPath.cubicTo (x1 + (offx1 - x1) * 0.55f, y1 + (offy1 - y1) * 0.55f, | |||
| offx1 + (midx - offx1) * 0.45f, offy1 + (midy - offy1) * 0.45f, | |||
| midx, midy); | |||
| if (isClosed) | |||
| { | |||
| destPath.startNewSubPath (lastX1, lastY1); | |||
| destPath.cubicTo (midx + (offx2 - midx) * 0.55f, midy + (offy2 - midy) * 0.55f, | |||
| offx2 + (x2 - offx2) * 0.45f, offy2 + (y2 - offy2) * 0.45f, | |||
| x2, y2); | |||
| } | |||
| } | |||
| } | |||
| else | |||
| struct LineSection | |||
| { | |||
| LineSection() {} | |||
| LineSection (int) {} | |||
| float x1, y1, x2, y2; // original line | |||
| float lx1, ly1, lx2, ly2; // the left-hand stroke | |||
| float rx1, ry1, rx2, ry2; // the right-hand stroke | |||
| }; | |||
| static void addSubPath (Path& destPath, const Array <LineSection>& subPath, | |||
| const bool isClosed, | |||
| const float width, const float maxMiterExtensionSquared, | |||
| const PathStrokeType::JointStyle jointStyle, const PathStrokeType::EndCapStyle endStyle) | |||
| { | |||
| destPath.startNewSubPath (firstLine.rx2, firstLine.ry2); | |||
| jassert (subPath.size() > 0); | |||
| addLineEnd (destPath, endStyle, | |||
| firstLine.rx2, firstLine.ry2, | |||
| lastX1, lastY1, | |||
| width); | |||
| } | |||
| const LineSection& firstLine = subPath.getReference (0); | |||
| int i; | |||
| for (i = 1; i < subPath.size(); ++i) | |||
| { | |||
| const LineSection& l = subPath.getReference (i); | |||
| addEdgeAndJoint (destPath, jointStyle, | |||
| maxMiterExtensionSquared, width, | |||
| lastX1, lastY1, lastX2, lastY2, | |||
| l.lx1, l.ly1, l.lx2, l.ly2, | |||
| l.x1, l.y1); | |||
| lastX1 = l.lx1; | |||
| lastY1 = l.ly1; | |||
| lastX2 = l.lx2; | |||
| lastY2 = l.ly2; | |||
| } | |||
| float lastX1 = firstLine.lx1; | |||
| float lastY1 = firstLine.ly1; | |||
| float lastX2 = firstLine.lx2; | |||
| float lastY2 = firstLine.ly2; | |||
| const LineSection& lastLine = subPath.getReference (subPath.size() - 1); | |||
| if (isClosed) | |||
| { | |||
| destPath.startNewSubPath (lastX1, lastY1); | |||
| } | |||
| else | |||
| { | |||
| destPath.startNewSubPath (firstLine.rx2, firstLine.ry2); | |||
| if (isClosed) | |||
| { | |||
| const LineSection& l = subPath.getReference (0); | |||
| addLineEnd (destPath, endStyle, | |||
| firstLine.rx2, firstLine.ry2, | |||
| lastX1, lastY1, | |||
| width); | |||
| } | |||
| addEdgeAndJoint (destPath, jointStyle, | |||
| maxMiterExtensionSquared, width, | |||
| lastX1, lastY1, lastX2, lastY2, | |||
| l.lx1, l.ly1, l.lx2, l.ly2, | |||
| l.x1, l.y1); | |||
| int i; | |||
| for (i = 1; i < subPath.size(); ++i) | |||
| { | |||
| const LineSection& l = subPath.getReference (i); | |||
| addEdgeAndJoint (destPath, jointStyle, | |||
| maxMiterExtensionSquared, width, | |||
| lastX1, lastY1, lastX2, lastY2, | |||
| l.lx1, l.ly1, l.lx2, l.ly2, | |||
| l.x1, l.y1); | |||
| lastX1 = l.lx1; | |||
| lastY1 = l.ly1; | |||
| lastX2 = l.lx2; | |||
| lastY2 = l.ly2; | |||
| } | |||
| destPath.closeSubPath(); | |||
| destPath.startNewSubPath (lastLine.rx1, lastLine.ry1); | |||
| } | |||
| else | |||
| { | |||
| destPath.lineTo (lastX2, lastY2); | |||
| const LineSection& lastLine = subPath.getReference (subPath.size() - 1); | |||
| addLineEnd (destPath, endStyle, | |||
| lastX2, lastY2, | |||
| lastLine.rx1, lastLine.ry1, | |||
| width); | |||
| } | |||
| if (isClosed) | |||
| { | |||
| const LineSection& l = subPath.getReference (0); | |||
| lastX1 = lastLine.rx1; | |||
| lastY1 = lastLine.ry1; | |||
| lastX2 = lastLine.rx2; | |||
| lastY2 = lastLine.ry2; | |||
| addEdgeAndJoint (destPath, jointStyle, | |||
| maxMiterExtensionSquared, width, | |||
| lastX1, lastY1, lastX2, lastY2, | |||
| l.lx1, l.ly1, l.lx2, l.ly2, | |||
| l.x1, l.y1); | |||
| for (i = subPath.size() - 1; --i >= 0;) | |||
| { | |||
| const LineSection& l = subPath.getReference (i); | |||
| addEdgeAndJoint (destPath, jointStyle, | |||
| maxMiterExtensionSquared, width, | |||
| lastX1, lastY1, lastX2, lastY2, | |||
| l.rx1, l.ry1, l.rx2, l.ry2, | |||
| l.x2, l.y2); | |||
| lastX1 = l.rx1; | |||
| lastY1 = l.ry1; | |||
| lastX2 = l.rx2; | |||
| lastY2 = l.ry2; | |||
| } | |||
| destPath.closeSubPath(); | |||
| destPath.startNewSubPath (lastLine.rx1, lastLine.ry1); | |||
| } | |||
| else | |||
| { | |||
| destPath.lineTo (lastX2, lastY2); | |||
| if (isClosed) | |||
| { | |||
| addEdgeAndJoint (destPath, jointStyle, | |||
| maxMiterExtensionSquared, width, | |||
| lastX1, lastY1, lastX2, lastY2, | |||
| lastLine.rx1, lastLine.ry1, lastLine.rx2, lastLine.ry2, | |||
| lastLine.x2, lastLine.y2); | |||
| } | |||
| else | |||
| { | |||
| // do the last line | |||
| destPath.lineTo (lastX2, lastY2); | |||
| } | |||
| addLineEnd (destPath, endStyle, | |||
| lastX2, lastY2, | |||
| lastLine.rx1, lastLine.ry1, | |||
| width); | |||
| } | |||
| lastX1 = lastLine.rx1; | |||
| lastY1 = lastLine.ry1; | |||
| lastX2 = lastLine.rx2; | |||
| lastY2 = lastLine.ry2; | |||
| for (i = subPath.size() - 1; --i >= 0;) | |||
| { | |||
| const LineSection& l = subPath.getReference (i); | |||
| addEdgeAndJoint (destPath, jointStyle, | |||
| maxMiterExtensionSquared, width, | |||
| lastX1, lastY1, lastX2, lastY2, | |||
| l.rx1, l.ry1, l.rx2, l.ry2, | |||
| l.x2, l.y2); | |||
| lastX1 = l.rx1; | |||
| lastY1 = l.ry1; | |||
| lastX2 = l.rx2; | |||
| lastY2 = l.ry2; | |||
| } | |||
| if (isClosed) | |||
| { | |||
| addEdgeAndJoint (destPath, jointStyle, | |||
| maxMiterExtensionSquared, width, | |||
| lastX1, lastY1, lastX2, lastY2, | |||
| lastLine.rx1, lastLine.ry1, lastLine.rx2, lastLine.ry2, | |||
| lastLine.x2, lastLine.y2); | |||
| } | |||
| else | |||
| { | |||
| // do the last line | |||
| destPath.lineTo (lastX2, lastY2); | |||
| } | |||
| destPath.closeSubPath(); | |||
| destPath.closeSubPath(); | |||
| } | |||
| } | |||
| void PathStrokeType::createStrokedPath (Path& destPath, | |||
| const Path& source, | |||
| const AffineTransform& transform, | |||
| const float extraAccuracy) const throw() | |||
| const float extraAccuracy) const | |||
| { | |||
| if (thickness <= 0) | |||
| { | |||
| @@ -497,6 +500,7 @@ void PathStrokeType::createStrokedPath (Path& destPath, | |||
| // left/right-hand lines along either side of it... | |||
| PathFlatteningIterator it (*sourcePath, transform, 9.0f / extraAccuracy); | |||
| using namespace PathFunctions; | |||
| Array <LineSection> subPath; | |||
| LineSection l; | |||
| l.x1 = 0; | |||
| @@ -576,7 +580,7 @@ void PathStrokeType::createDashedStroke (Path& destPath, | |||
| const float* dashLengths, | |||
| int numDashLengths, | |||
| const AffineTransform& transform, | |||
| const float extraAccuracy) const throw() | |||
| const float extraAccuracy) const | |||
| { | |||
| if (thickness <= 0) | |||
| return; | |||
| @@ -104,7 +104,7 @@ public: | |||
| void createStrokedPath (Path& destPath, | |||
| const Path& sourcePath, | |||
| const AffineTransform& transform = AffineTransform::identity, | |||
| const float extraAccuracy = 1.0f) const throw(); | |||
| const float extraAccuracy = 1.0f) const; | |||
| //============================================================================== | |||
| @@ -135,7 +135,7 @@ public: | |||
| const float* dashLengths, | |||
| int numDashLengths, | |||
| const AffineTransform& transform = AffineTransform::identity, | |||
| const float extraAccuracy = 1.0f) const throw(); | |||
| const float extraAccuracy = 1.0f) const; | |||
| //============================================================================== | |||
| /** Returns the stroke thickness. */ | |||
| @@ -412,68 +412,66 @@ struct MidiPortAndCallback | |||
| int pendingBytes; | |||
| double pendingDataTime; | |||
| bool active; | |||
| }; | |||
| static CriticalSection callbackLock; | |||
| static VoidArray activeCallbacks; | |||
| static void processSysex (MidiPortAndCallback* const mpc, const uint8*& d, int& size, const double time) | |||
| { | |||
| if (*d == 0xf0) | |||
| void processSysex (const uint8*& d, int& size, const double time) | |||
| { | |||
| mpc->pendingBytes = 0; | |||
| mpc->pendingDataTime = time; | |||
| } | |||
| if (*d == 0xf0) | |||
| { | |||
| pendingBytes = 0; | |||
| pendingDataTime = time; | |||
| } | |||
| mpc->pendingData.ensureSize (mpc->pendingBytes + size, false); | |||
| uint8* totalMessage = (uint8*) mpc->pendingData.getData(); | |||
| pendingData.ensureSize (pendingBytes + size, false); | |||
| uint8* totalMessage = (uint8*) pendingData.getData(); | |||
| uint8* dest = totalMessage + mpc->pendingBytes; | |||
| uint8* dest = totalMessage + pendingBytes; | |||
| while (size > 0) | |||
| { | |||
| if (mpc->pendingBytes > 0 && *d >= 0x80) | |||
| while (size > 0) | |||
| { | |||
| if (*d >= 0xfa || *d == 0xf8) | |||
| if (pendingBytes > 0 && *d >= 0x80) | |||
| { | |||
| mpc->callback->handleIncomingMidiMessage (mpc->input, MidiMessage (*d, time)); | |||
| ++d; | |||
| --size; | |||
| } | |||
| else | |||
| { | |||
| if (*d == 0xf7) | |||
| if (*d >= 0xfa || *d == 0xf8) | |||
| { | |||
| *dest++ = *d++; | |||
| mpc->pendingBytes++; | |||
| callback->handleIncomingMidiMessage (input, MidiMessage (*d, time)); | |||
| ++d; | |||
| --size; | |||
| } | |||
| else | |||
| { | |||
| if (*d == 0xf7) | |||
| { | |||
| *dest++ = *d++; | |||
| pendingBytes++; | |||
| --size; | |||
| } | |||
| break; | |||
| break; | |||
| } | |||
| } | |||
| else | |||
| { | |||
| *dest++ = *d++; | |||
| pendingBytes++; | |||
| --size; | |||
| } | |||
| } | |||
| if (totalMessage [pendingBytes - 1] == 0xf7) | |||
| { | |||
| callback->handleIncomingMidiMessage (input, MidiMessage (totalMessage, pendingBytes, pendingDataTime)); | |||
| pendingBytes = 0; | |||
| } | |||
| else | |||
| { | |||
| *dest++ = *d++; | |||
| mpc->pendingBytes++; | |||
| --size; | |||
| callback->handlePartialSysexMessage (input, totalMessage, pendingBytes, pendingDataTime); | |||
| } | |||
| } | |||
| }; | |||
| if (totalMessage [mpc->pendingBytes - 1] == 0xf7) | |||
| { | |||
| mpc->callback->handleIncomingMidiMessage (mpc->input, MidiMessage (totalMessage, | |||
| mpc->pendingBytes, | |||
| mpc->pendingDataTime)); | |||
| mpc->pendingBytes = 0; | |||
| } | |||
| else | |||
| { | |||
| mpc->callback->handlePartialSysexMessage (mpc->input, | |||
| totalMessage, | |||
| mpc->pendingBytes, | |||
| mpc->pendingDataTime); | |||
| } | |||
| namespace CoreMidiCallbacks | |||
| { | |||
| static CriticalSection callbackLock; | |||
| static VoidArray activeCallbacks; | |||
| } | |||
| static void midiInputProc (const MIDIPacketList* pktlist, | |||
| @@ -484,9 +482,9 @@ static void midiInputProc (const MIDIPacketList* pktlist, | |||
| const double originalTime = time; | |||
| MidiPortAndCallback* const mpc = (MidiPortAndCallback*) readProcRefCon; | |||
| const ScopedLock sl (callbackLock); | |||
| const ScopedLock sl (CoreMidiCallbacks::callbackLock); | |||
| if (activeCallbacks.contains (mpc) && mpc->active) | |||
| if (CoreMidiCallbacks::activeCallbacks.contains (mpc) && mpc->active) | |||
| { | |||
| const MIDIPacket* packet = &pktlist->packet[0]; | |||
| @@ -501,7 +499,7 @@ static void midiInputProc (const MIDIPacketList* pktlist, | |||
| if (mpc->pendingBytes > 0 || d[0] == 0xf0) | |||
| { | |||
| processSysex (mpc, d, size, time); | |||
| mpc->processSysex (d, size, time); | |||
| } | |||
| else | |||
| { | |||
| @@ -564,8 +562,8 @@ MidiInput* MidiInput::openDevice (int index, MidiInputCallback* callback) | |||
| mpc->input = mi; | |||
| mi->internal = (void*) mpc; | |||
| const ScopedLock sl (callbackLock); | |||
| activeCallbacks.add (mpc.release()); | |||
| const ScopedLock sl (CoreMidiCallbacks::callbackLock); | |||
| CoreMidiCallbacks::activeCallbacks.add (mpc.release()); | |||
| } | |||
| else | |||
| { | |||
| @@ -604,8 +602,8 @@ MidiInput* MidiInput::createNewDevice (const String& deviceName, MidiInputCallba | |||
| mpc->input = mi; | |||
| mi->internal = (void*) mpc; | |||
| const ScopedLock sl (callbackLock); | |||
| activeCallbacks.add (mpc.release()); | |||
| const ScopedLock sl (CoreMidiCallbacks::callbackLock); | |||
| CoreMidiCallbacks::activeCallbacks.add (mpc.release()); | |||
| } | |||
| CFRelease (name); | |||
| @@ -625,8 +623,8 @@ MidiInput::~MidiInput() | |||
| mpc->active = false; | |||
| { | |||
| const ScopedLock sl (callbackLock); | |||
| activeCallbacks.removeValue (mpc); | |||
| const ScopedLock sl (CoreMidiCallbacks::callbackLock); | |||
| CoreMidiCallbacks::activeCallbacks.removeValue (mpc); | |||
| } | |||
| if (mpc->portAndEndpoint->port != 0) | |||
| @@ -638,13 +636,13 @@ MidiInput::~MidiInput() | |||
| void MidiInput::start() | |||
| { | |||
| const ScopedLock sl (callbackLock); | |||
| const ScopedLock sl (CoreMidiCallbacks::callbackLock); | |||
| ((MidiPortAndCallback*) internal)->active = true; | |||
| } | |||
| void MidiInput::stop() | |||
| { | |||
| const ScopedLock sl (callbackLock); | |||
| const ScopedLock sl (CoreMidiCallbacks::callbackLock); | |||
| ((MidiPortAndCallback*) internal)->active = false; | |||
| } | |||
| @@ -209,6 +209,40 @@ public: | |||
| virtual NSRect constrainRect (NSRect r); | |||
| static void showArrowCursorIfNeeded(); | |||
| static void updateModifiers (NSEvent* e); | |||
| static void updateKeysDown (NSEvent* ev, bool isKeyDown); | |||
| static int getKeyCodeFromEvent (NSEvent* ev) | |||
| { | |||
| const String unmodified (nsStringToJuce ([ev charactersIgnoringModifiers])); | |||
| int keyCode = unmodified[0]; | |||
| if (keyCode == 0x19) // (backwards-tab) | |||
| keyCode = '\t'; | |||
| else if (keyCode == 0x03) // (enter) | |||
| keyCode = '\r'; | |||
| return keyCode; | |||
| } | |||
| static int64 getMouseTime (NSEvent* e) | |||
| { | |||
| return (Time::currentTimeMillis() - Time::getMillisecondCounter()) | |||
| + (int64) ([e timestamp] * 1000.0); | |||
| } | |||
| static const Point<int> getMousePos (NSEvent* e, NSView* view) | |||
| { | |||
| NSPoint p = [view convertPoint: [e locationInWindow] fromView: nil]; | |||
| return Point<int> (roundToInt (p.x), roundToInt ([view frame].size.height - p.y)); | |||
| } | |||
| static int getModifierForButtonNumber (const NSInteger num) | |||
| { | |||
| return num == 0 ? ModifierKeys::leftButtonModifier | |||
| : (num == 1 ? ModifierKeys::rightButtonModifier | |||
| : (num == 2 ? ModifierKeys::middleButtonModifier : 0)); | |||
| } | |||
| //============================================================================== | |||
| virtual void viewFocusGain(); | |||
| @@ -724,22 +758,9 @@ bool KeyPress::isKeyCurrentlyDown (const int keyCode) throw() | |||
| return false; | |||
| } | |||
| static int getKeyCodeFromEvent (NSEvent* ev) | |||
| { | |||
| const String unmodified (nsStringToJuce ([ev charactersIgnoringModifiers])); | |||
| int keyCode = unmodified[0]; | |||
| if (keyCode == 0x19) // (backwards-tab) | |||
| keyCode = '\t'; | |||
| else if (keyCode == 0x03) // (enter) | |||
| keyCode = '\r'; | |||
| return keyCode; | |||
| } | |||
| static int currentModifiers = 0; | |||
| static void updateModifiers (NSEvent* e) | |||
| void NSViewComponentPeer::updateModifiers (NSEvent* e) | |||
| { | |||
| int m = currentModifiers & ~(ModifierKeys::shiftModifier | ModifierKeys::ctrlModifier | |||
| | ModifierKeys::altModifier | ModifierKeys::commandModifier); | |||
| @@ -759,7 +780,7 @@ static void updateModifiers (NSEvent* e) | |||
| currentModifiers = m; | |||
| } | |||
| static void updateKeysDown (NSEvent* ev, bool isKeyDown) | |||
| void NSViewComponentPeer::updateKeysDown (NSEvent* ev, bool isKeyDown) | |||
| { | |||
| updateModifiers (ev); | |||
| int keyCode = getKeyCodeFromEvent (ev); | |||
| @@ -783,25 +804,6 @@ void ModifierKeys::updateCurrentModifiers() throw() | |||
| currentModifierFlags = currentModifiers; | |||
| } | |||
| static int64 getMouseTime (NSEvent* e) | |||
| { | |||
| return (Time::currentTimeMillis() - Time::getMillisecondCounter()) | |||
| + (int64) ([e timestamp] * 1000.0); | |||
| } | |||
| static const Point<int> getMousePos (NSEvent* e, NSView* view) | |||
| { | |||
| NSPoint p = [view convertPoint: [e locationInWindow] fromView: nil]; | |||
| return Point<int> (roundToInt (p.x), roundToInt ([view frame].size.height - p.y)); | |||
| } | |||
| static int getModifierForButtonNumber (const NSInteger num) | |||
| { | |||
| return num == 0 ? ModifierKeys::leftButtonModifier | |||
| : (num == 1 ? ModifierKeys::rightButtonModifier | |||
| : (num == 2 ? ModifierKeys::middleButtonModifier : 0)); | |||
| } | |||
| //============================================================================== | |||
| NSViewComponentPeer::NSViewComponentPeer (Component* const component_, | |||
| const int windowStyleFlags, | |||
| @@ -150,106 +150,114 @@ XmlElement::~XmlElement() throw() | |||
| } | |||
| //============================================================================== | |||
| static bool isLegalXmlChar (const juce_wchar character) | |||
| namespace XmlOutputFunctions | |||
| { | |||
| if ((character >= 'a' && character <= 'z') | |||
| || (character >= 'A' && character <= 'Z') | |||
| || (character >= '0' && character <= '9')) | |||
| return true; | |||
| const char* t = " .,;:-()_+=?!'#@[]/\\*%~{}"; | |||
| do | |||
| /*static bool isLegalXmlCharSlow (const juce_wchar character) throw() | |||
| { | |||
| if (((juce_wchar) (uint8) *t) == character) | |||
| if ((character >= 'a' && character <= 'z') | |||
| || (character >= 'A' && character <= 'Z') | |||
| || (character >= '0' && character <= '9')) | |||
| return true; | |||
| } | |||
| while (*++t != 0); | |||
| return false; | |||
| } | |||
| const char* t = " .,;:-()_+=?!'#@[]/\\*%~{}"; | |||
| static void escapeIllegalXmlChars (OutputStream& outputStream, | |||
| const String& text, | |||
| const bool changeNewLines) throw() | |||
| { | |||
| const juce_wchar* t = (const juce_wchar*) text; | |||
| do | |||
| { | |||
| if (((juce_wchar) (uint8) *t) == character) | |||
| return true; | |||
| } | |||
| while (*++t != 0); | |||
| for (;;) | |||
| return false; | |||
| } | |||
| static void generateLegalCharConstants() | |||
| { | |||
| const juce_wchar character = *t++; | |||
| uint8 n[32]; | |||
| zerostruct (n); | |||
| for (int i = 0; i < 256; ++i) | |||
| if (isLegalXmlCharSlow (i)) | |||
| n[i >> 3] |= (1 << (i & 7)); | |||
| if (character == 0) | |||
| { | |||
| break; | |||
| } | |||
| else if (isLegalXmlChar (character)) | |||
| { | |||
| outputStream.writeByte ((char) character); | |||
| } | |||
| else | |||
| { | |||
| switch (character) | |||
| { | |||
| case '&': | |||
| outputStream.write ("&", 5); | |||
| break; | |||
| String s; | |||
| for (int i = 0; i < 32; ++i) | |||
| s << (int) n[i] << ", "; | |||
| case '"': | |||
| outputStream.write (""", 6); | |||
| break; | |||
| DBG (s); | |||
| }*/ | |||
| case '>': | |||
| outputStream.write (">", 4); | |||
| break; | |||
| static bool isLegalXmlChar (const uint32 c) throw() | |||
| { | |||
| static const unsigned char legalChars[] = { 0, 0, 0, 0, 171, 255, 255, 175, 255, 255, 255, 191, 254, 255, 255, 111 }; | |||
| case '<': | |||
| outputStream.write ("<", 4); | |||
| break; | |||
| return c < sizeof (legalChars) * 8 | |||
| && (legalChars [c >> 3] & (1 << (c & 7))) != 0; | |||
| } | |||
| case '\n': | |||
| if (changeNewLines) | |||
| outputStream.write (" ", 5); | |||
| else | |||
| outputStream.writeByte ((char) character); | |||
| static void escapeIllegalXmlChars (OutputStream& outputStream, const String& text, const bool changeNewLines) | |||
| { | |||
| const juce_wchar* t = (const juce_wchar*) text; | |||
| for (;;) | |||
| { | |||
| const juce_wchar character = *t++; | |||
| if (character == 0) | |||
| { | |||
| break; | |||
| } | |||
| else if (isLegalXmlChar ((uint32) character)) | |||
| { | |||
| outputStream << (char) character; | |||
| } | |||
| else | |||
| { | |||
| switch (character) | |||
| { | |||
| case '&': outputStream << "&"; break; | |||
| case '"': outputStream << """; break; | |||
| case '>': outputStream << ">"; break; | |||
| case '<': outputStream << "<"; break; | |||
| case '\n': | |||
| if (changeNewLines) | |||
| outputStream << " "; | |||
| else | |||
| outputStream << (char) character; | |||
| case '\r': | |||
| if (changeNewLines) | |||
| outputStream.write (" ", 5); | |||
| else | |||
| outputStream.writeByte ((char) character); | |||
| break; | |||
| break; | |||
| case '\r': | |||
| if (changeNewLines) | |||
| outputStream << " "; | |||
| else | |||
| outputStream << (char) character; | |||
| default: | |||
| { | |||
| String encoded (T("&#")); | |||
| encoded << String ((int) (unsigned int) character).trim() | |||
| << T(';'); | |||
| break; | |||
| outputStream.write ((const char*) encoded, encoded.length()); | |||
| default: | |||
| outputStream << "&#" << ((int) (unsigned int) character) << ';'; | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| static void writeSpaces (OutputStream& out, int numSpaces) throw() | |||
| { | |||
| if (numSpaces > 0) | |||
| static void writeSpaces (OutputStream& out, int numSpaces) throw() | |||
| { | |||
| const char* const blanks = " "; | |||
| const int blankSize = (int) sizeof (blanks) - 1; | |||
| while (numSpaces > blankSize) | |||
| if (numSpaces > 0) | |||
| { | |||
| out.write (blanks, blankSize); | |||
| numSpaces -= blankSize; | |||
| } | |||
| const char* const blanks = " "; | |||
| const int blankSize = (int) sizeof (blanks) - 1; | |||
| while (numSpaces > blankSize) | |||
| { | |||
| out.write (blanks, blankSize); | |||
| numSpaces -= blankSize; | |||
| } | |||
| out.write (blanks, numSpaces); | |||
| out.write (blanks, numSpaces); | |||
| } | |||
| } | |||
| } | |||
| @@ -257,6 +265,7 @@ void XmlElement::writeElementAsText (OutputStream& outputStream, | |||
| const int indentationLevel, | |||
| const int lineWrapLength) const throw() | |||
| { | |||
| using namespace XmlOutputFunctions; | |||
| writeSpaces (outputStream, indentationLevel); | |||
| if (! isTextElement()) | |||