Browse Source

Update juce

tags/1.9.4
falkTX 10 years ago
parent
commit
aabe155188
29 changed files with 445 additions and 259 deletions
  1. +2
    -2
      data/copy-juce-carla
  2. +7
    -3
      source/modules/juce_audio_basics/buffers/juce_AudioSampleBuffer.cpp
  3. +5
    -3
      source/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp
  4. +2
    -0
      source/modules/juce_core/AppConfig.h
  5. +10
    -7
      source/modules/juce_core/juce_core.cpp
  6. +4
    -0
      source/modules/juce_core/juce_core.h
  7. +27
    -0
      source/modules/juce_core/native/juce_BasicNativeHeaders.h
  8. +4
    -0
      source/modules/juce_core/native/juce_linux_Files.cpp
  9. +4
    -0
      source/modules/juce_core/native/juce_mac_Files.mm
  10. +26
    -11
      source/modules/juce_core/native/juce_posix_SharedCode.h
  11. +4
    -0
      source/modules/juce_core/network/juce_URL.cpp
  12. +1
    -1
      source/modules/juce_core/system/juce_SystemStats.cpp
  13. +3
    -1
      source/modules/juce_core/system/juce_TargetPlatform.h
  14. +40
    -17
      source/modules/juce_core/time/juce_Time.cpp
  15. +16
    -16
      source/modules/juce_core/time/juce_Time.h
  16. +1
    -2
      source/modules/juce_core/zip/juce_ZipFile.cpp
  17. +1
    -1
      source/modules/juce_data_structures/app_properties/juce_PropertiesFile.cpp
  18. +7
    -2
      source/modules/juce_events/native/juce_linux_Messaging.cpp
  19. +3
    -3
      source/modules/juce_graphics/fonts/juce_Font.cpp
  20. +1
    -1
      source/modules/juce_graphics/fonts/juce_Font.h
  21. +195
    -157
      source/modules/juce_graphics/fonts/juce_GlyphArrangement.cpp
  22. +10
    -1
      source/modules/juce_graphics/fonts/juce_GlyphArrangement.h
  23. +11
    -0
      source/modules/juce_graphics/geometry/juce_RectangleList.h
  24. +32
    -15
      source/modules/juce_graphics/native/juce_win32_DirectWriteTypeLayout.cpp
  25. +15
    -15
      source/modules/juce_graphics/native/juce_win32_DirectWriteTypeface.cpp
  26. +6
    -1
      source/modules/juce_gui_basics/filebrowser/juce_FilenameComponent.cpp
  27. +3
    -0
      source/modules/juce_gui_basics/filebrowser/juce_FilenameComponent.h
  28. +2
    -0
      source/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm
  29. +3
    -0
      source/modules/juce_gui_extra/native/juce_mac_SystemTrayIcon.cpp

+ 2
- 2
data/copy-juce-carla View File

@@ -2,8 +2,8 @@


set -e set -e


JUCE_MODULES_DIR="/home/falktx/Personal/FOSS/GIT/distrho/DISTRHO/libs/juce/source/modules/"
CARLA_MODULES_DIR="/home/falktx/Personal/FOSS/GIT/falktx/Carla/source/modules/"
JUCE_MODULES_DIR="/home/falktx/FOSS/GIT-mine/DISTRHO/DISTRHO/libs/juce/source/modules/"
CARLA_MODULES_DIR="/home/falktx/FOSS/GIT-mine/Carla/source/modules/"


MODULES=("juce_audio_basics juce_audio_devices juce_audio_formats juce_audio_processors juce_core juce_data_structures juce_events juce_graphics juce_gui_basics juce_gui_extra") MODULES=("juce_audio_basics juce_audio_devices juce_audio_formats juce_audio_processors juce_core juce_data_structures juce_events juce_graphics juce_gui_basics juce_gui_extra")




+ 7
- 3
source/modules/juce_audio_basics/buffers/juce_AudioSampleBuffer.cpp View File

@@ -91,7 +91,7 @@ AudioSampleBuffer::AudioSampleBuffer (float* const* dataToReferTo,
allocatedBytes (0) allocatedBytes (0)
{ {
jassert (dataToReferTo != nullptr); jassert (dataToReferTo != nullptr);
jassert (numChans >= 0);
jassert (numChans >= 0 && numSamples >= 0);
allocateChannels (dataToReferTo, 0); allocateChannels (dataToReferTo, 0);
} }
@@ -105,7 +105,7 @@ AudioSampleBuffer::AudioSampleBuffer (float* const* dataToReferTo,
isClear (false) isClear (false)
{ {
jassert (dataToReferTo != nullptr); jassert (dataToReferTo != nullptr);
jassert (numChans >= 0);
jassert (numChans >= 0 && startSample >= 0 && numSamples >= 0);
allocateChannels (dataToReferTo, startSample); allocateChannels (dataToReferTo, startSample);
} }
@@ -114,7 +114,7 @@ void AudioSampleBuffer::setDataToReferTo (float** dataToReferTo,
const int newNumSamples) noexcept const int newNumSamples) noexcept
{ {
jassert (dataToReferTo != nullptr); jassert (dataToReferTo != nullptr);
jassert (newNumChannels >= 0);
jassert (newNumChannels >= 0 && newNumSamples >= 0);
allocatedBytes = 0; allocatedBytes = 0;
allocatedData.free(); allocatedData.free();
@@ -128,6 +128,8 @@ void AudioSampleBuffer::setDataToReferTo (float** dataToReferTo,
void AudioSampleBuffer::allocateChannels (float* const* const dataToReferTo, int offset) void AudioSampleBuffer::allocateChannels (float* const* const dataToReferTo, int offset)
{ {
jassert (offset >= 0);
// (try to avoid doing a malloc here, as that'll blow up things like Pro-Tools) // (try to avoid doing a malloc here, as that'll blow up things like Pro-Tools)
if (numChannels < (int) numElementsInArray (preallocatedChannelSpace)) if (numChannels < (int) numElementsInArray (preallocatedChannelSpace))
{ {
@@ -163,6 +165,8 @@ AudioSampleBuffer& AudioSampleBuffer::operator= (const AudioSampleBuffer& other)
} }
else else
{ {
isClear = false;
for (int i = 0; i < numChannels; ++i) for (int i = 0; i < numChannels; ++i)
FloatVectorOperations::copy (channels[i], other.channels[i], size); FloatVectorOperations::copy (channels[i], other.channels[i], size);
} }


+ 5
- 3
source/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp View File

@@ -2233,10 +2233,11 @@ private:
#pragma warning (push) #pragma warning (push)
#pragma warning (disable: 4244) #pragma warning (disable: 4244)
originalWndProc = (void*) GetWindowLongPtr (pluginHWND, GWLP_WNDPROC);
if (! pluginWantsKeys) if (! pluginWantsKeys)
{
originalWndProc = (void*) GetWindowLongPtr (pluginHWND, GWLP_WNDPROC);
SetWindowLongPtr (pluginHWND, GWLP_WNDPROC, (LONG_PTR) vstHookWndProc); SetWindowLongPtr (pluginHWND, GWLP_WNDPROC, (LONG_PTR) vstHookWndProc);
}
#pragma warning (pop) #pragma warning (pop)
@@ -2326,10 +2327,11 @@ private:
#if JUCE_WINDOWS #if JUCE_WINDOWS
#pragma warning (push) #pragma warning (push)
#pragma warning (disable: 4244) #pragma warning (disable: 4244)
if (pluginHWND != 0 && IsWindow (pluginHWND))
if (originalWndProc != 0 && pluginHWND != 0 && IsWindow (pluginHWND))
SetWindowLongPtr (pluginHWND, GWLP_WNDPROC, (LONG_PTR) originalWndProc); SetWindowLongPtr (pluginHWND, GWLP_WNDPROC, (LONG_PTR) originalWndProc);
#pragma warning (pop) #pragma warning (pop)
originalWndProc = 0;
pluginHWND = 0; pluginHWND = 0;
#elif JUCE_LINUX #elif JUCE_LINUX
pluginWindow = 0; pluginWindow = 0;


+ 2
- 0
source/modules/juce_core/AppConfig.h View File

@@ -67,6 +67,8 @@
#define JUCE_DISABLE_JUCE_VERSION_PRINTING 1 #define JUCE_DISABLE_JUCE_VERSION_PRINTING 1
#define JUCE_USE_VFORK 1
#define JUCE_MODULE_AVAILABLE_juce_audio_basics 1 #define JUCE_MODULE_AVAILABLE_juce_audio_basics 1
#define JUCE_MODULE_AVAILABLE_juce_audio_devices 1 #define JUCE_MODULE_AVAILABLE_juce_audio_devices 1
#define JUCE_MODULE_AVAILABLE_juce_audio_formats 1 #define JUCE_MODULE_AVAILABLE_juce_audio_formats 1


+ 10
- 7
source/modules/juce_core/juce_core.cpp View File

@@ -69,18 +69,16 @@
#endif #endif
#else #else
#if JUCE_LINUX || JUCE_ANDROID
#if JUCE_LINUX || JUCE_ANDROID || JUCE_HAIKU
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/errno.h>
#if ! JUCE_HAIKU
#include <sys/errno.h>
#endif
#include <unistd.h> #include <unistd.h>
#include <netinet/in.h> #include <netinet/in.h>
#endif #endif
#if JUCE_LINUX
#include <langinfo.h>
#endif
#include <pwd.h> #include <pwd.h>
#include <fcntl.h> #include <fcntl.h>
#include <netdb.h> #include <netdb.h>
@@ -90,8 +88,9 @@
#include <net/if.h> #include <net/if.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#if ! JUCE_ANDROID
#if JUCE_LINUX
#include <execinfo.h> #include <execinfo.h>
#include <langinfo.h>
#endif #endif
#endif #endif
@@ -214,6 +213,10 @@ namespace juce
#include "native/juce_android_SystemStats.cpp" #include "native/juce_android_SystemStats.cpp"
#include "native/juce_android_Threads.cpp" #include "native/juce_android_Threads.cpp"
//==============================================================================
#elif JUCE_HAIKU
// TODO
#endif #endif
#include "threads/juce_ChildProcess.cpp" #include "threads/juce_ChildProcess.cpp"


+ 4
- 0
source/modules/juce_core/juce_core.h View File

@@ -129,6 +129,10 @@
#define JUCE_STRING_UTF_TYPE 8 #define JUCE_STRING_UTF_TYPE 8
#endif #endif
#ifndef JUCE_USE_VFORK
#define JUCE_USE_VFORK 0
#endif
//============================================================================= //=============================================================================
//============================================================================= //=============================================================================
#if JUCE_MSVC #if JUCE_MSVC


+ 27
- 0
source/modules/juce_core/native/juce_BasicNativeHeaders.h View File

@@ -212,6 +212,33 @@
#include <dirent.h> #include <dirent.h>
#include <fnmatch.h> #include <fnmatch.h>
#include <sys/wait.h> #include <sys/wait.h>
//==============================================================================
#elif JUCE_HAIKU
#include <sched.h>
#include <pthread.h>
#include <sys/time.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <fnmatch.h>
#include <utime.h>
#include <pwd.h>
#include <fcntl.h>
#include <dlfcn.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <net/if.h>
#include <sys/file.h>
#include <signal.h>
#include <stddef.h>
#endif #endif
// Need to clear various moronic redefinitions made by system headers.. // Need to clear various moronic redefinitions made by system headers..


+ 4
- 0
source/modules/juce_core/native/juce_linux_Files.cpp View File

@@ -218,7 +218,11 @@ bool Process::openDocument (const String& fileName, const String& parameters)
const char* const argv[4] = { "/bin/sh", "-c", cmdString.toUTF8(), 0 }; const char* const argv[4] = { "/bin/sh", "-c", cmdString.toUTF8(), 0 };
#if JUCE_USE_VFORK
const int cpid = vfork(); const int cpid = vfork();
#else
const int cpid = fork();
#endif
if (cpid == 0) if (cpid == 0)
{ {


+ 4
- 0
source/modules/juce_core/native/juce_mac_Files.mm View File

@@ -112,7 +112,11 @@ namespace FileHelpers
{ {
const char* const argv[4] = { "/bin/sh", "-c", pathAndArguments.toUTF8(), 0 }; const char* const argv[4] = { "/bin/sh", "-c", pathAndArguments.toUTF8(), 0 };
#if JUCE_USE_VFORK
const int cpid = vfork(); const int cpid = vfork();
#else
const int cpid = fork();
#endif
if (cpid == 0) if (cpid == 0)
{ {


+ 26
- 11
source/modules/juce_core/native/juce_posix_SharedCode.h View File

@@ -142,7 +142,7 @@ void JUCE_CALLTYPE Thread::sleep (int millisecs)
void JUCE_CALLTYPE Process::terminate() void JUCE_CALLTYPE Process::terminate()
{ {
#if JUCE_ANDROID
#if JUCE_ANDROID || JUCE_HAIKU
_exit (EXIT_FAILURE); _exit (EXIT_FAILURE);
#else #else
std::_Exit (EXIT_FAILURE); std::_Exit (EXIT_FAILURE);
@@ -203,6 +203,10 @@ namespace
#define JUCE_STAT stat #define JUCE_STAT stat
#endif #endif
#if JUCE_HAIKU
#define statfs statvfs
#endif
bool juce_stat (const String& fileName, juce_statStruct& info) bool juce_stat (const String& fileName, juce_statStruct& info)
{ {
return fileName.isNotEmpty() return fileName.isNotEmpty()
@@ -542,7 +546,11 @@ void MemoryMappedFile::openInternal (const File& file, AccessMode mode)
if (m != MAP_FAILED) if (m != MAP_FAILED)
{ {
address = m; address = m;
madvise (m, (size_t) range.getLength(), MADV_SEQUENTIAL);
#if JUCE_HAIKU
posix_madvise (m, (size_t) range.getLength(), POSIX_MADV_SEQUENTIAL);
#else
madvise (m, (size_t) range.getLength(), MADV_SEQUENTIAL);
#endif
} }
else else
{ {
@@ -663,6 +671,10 @@ int File::getVolumeSerialNumber() const
return result; return result;
} }
#if JUCE_HAIKU
#undef statvfs
#endif
//============================================================================== //==============================================================================
void juce_runSystemCommand (const String&); void juce_runSystemCommand (const String&);
void juce_runSystemCommand (const String& command) void juce_runSystemCommand (const String& command)
@@ -1006,16 +1018,20 @@ public:
int pipeHandles[2] = { 0 }; int pipeHandles[2] = { 0 };
if (pipe (pipeHandles) == 0)
{
Array<char*> argv;
for (int i = 0; i < arguments.size(); ++i)
if (arguments[i].isNotEmpty())
argv.add (const_cast<char*> (arguments[i].toUTF8().getAddress()));
Array<char*> argv;
for (int i = 0; i < arguments.size(); ++i)
if (arguments[i].isNotEmpty())
argv.add (const_cast<char*> (arguments[i].toUTF8().getAddress()));
argv.add (nullptr);
argv.add (nullptr);
if (pipe (pipeHandles) == 0)
{
#if JUCE_USE_VFORK
const pid_t result = vfork(); const pid_t result = vfork();
#else
const pid_t result = fork();
#endif
if (result < 0) if (result < 0)
{ {
@@ -1024,7 +1040,7 @@ public:
} }
else if (result == 0) else if (result == 0)
{ {
#if 0
#if ! JUCE_USE_VFORK
// we're the child process.. // we're the child process..
close (pipeHandles[0]); // close the read handle close (pipeHandles[0]); // close the read handle
@@ -1040,7 +1056,6 @@ public:
close (pipeHandles[1]); close (pipeHandles[1]);
#endif #endif
execvp (argv[0], argv.getRawDataPointer()); execvp (argv[0], argv.getRawDataPointer());
exit (-1); exit (-1);
} }


+ 4
- 0
source/modules/juce_core/network/juce_URL.cpp View File

@@ -342,6 +342,7 @@ InputStream* URL::createInputStream (const bool usePostCommand,
if (! headers.endsWithChar ('\n')) if (! headers.endsWithChar ('\n'))
headers << "\r\n"; headers << "\r\n";
#if ! JUCE_HAIKU
ScopedPointer<WebInputStream> wi (new WebInputStream (toString (! usePostCommand), ScopedPointer<WebInputStream> wi (new WebInputStream (toString (! usePostCommand),
usePostCommand, headersAndPostData, usePostCommand, headersAndPostData,
progressCallback, progressCallbackContext, progressCallback, progressCallbackContext,
@@ -351,6 +352,9 @@ InputStream* URL::createInputStream (const bool usePostCommand,
*statusCode = wi->statusCode; *statusCode = wi->statusCode;
return wi->isError() ? nullptr : wi.release(); return wi->isError() ? nullptr : wi.release();
#else
return nullptr; // TODO
#endif
} }
//============================================================================== //==============================================================================


+ 1
- 1
source/modules/juce_core/system/juce_SystemStats.cpp View File

@@ -97,7 +97,7 @@ String SystemStats::getStackBacktrace()
{ {
String result; String result;
#if JUCE_ANDROID || JUCE_MINGW
#if JUCE_ANDROID || JUCE_MINGW || JUCE_HAIKU
jassertfalse; // sorry, not implemented yet! jassertfalse; // sorry, not implemented yet!
#elif JUCE_WINDOWS #elif JUCE_WINDOWS


+ 3
- 1
source/modules/juce_core/system/juce_TargetPlatform.h View File

@@ -51,6 +51,8 @@
#define JUCE_ANDROID 1 #define JUCE_ANDROID 1
#elif defined (LINUX) || defined (__linux__) #elif defined (LINUX) || defined (__linux__)
#define JUCE_LINUX 1 #define JUCE_LINUX 1
#elif defined (__HAIKU__)
#define JUCE_HAIKU 1
#elif defined (__APPLE_CPP__) || defined(__APPLE_CC__) #elif defined (__APPLE_CPP__) || defined(__APPLE_CC__)
#define Point CarbonDummyPointName // (workaround to avoid definition of "Point" by old Carbon headers) #define Point CarbonDummyPointName // (workaround to avoid definition of "Point" by old Carbon headers)
#define Component CarbonDummyCompName #define Component CarbonDummyCompName
@@ -140,7 +142,7 @@
#endif #endif
//============================================================================== //==============================================================================
#if JUCE_LINUX || JUCE_ANDROID
#if JUCE_LINUX || JUCE_ANDROID || JUCE_HAIKU
#ifdef _DEBUG #ifdef _DEBUG
#define JUCE_DEBUG 1 #define JUCE_DEBUG 1


+ 40
- 17
source/modules/juce_core/time/juce_Time.cpp View File

@@ -407,11 +407,11 @@ String Time::getWeekdayName (const bool threeLetterVersion) const
return getWeekdayName (getDayOfWeek(), threeLetterVersion); return getWeekdayName (getDayOfWeek(), threeLetterVersion);
} }
static const char* const shortMonthNames[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
static const char* const longMonthNames[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" };
String Time::getMonthName (int monthNumber, const bool threeLetterVersion) String Time::getMonthName (int monthNumber, const bool threeLetterVersion)
{ {
static const char* const shortMonthNames[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
static const char* const longMonthNames[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" };
monthNumber %= 12; monthNumber %= 12;
return TRANS (threeLetterVersion ? shortMonthNames [monthNumber] return TRANS (threeLetterVersion ? shortMonthNames [monthNumber]
@@ -430,17 +430,40 @@ String Time::getWeekdayName (int day, const bool threeLetterVersion)
} }
//============================================================================== //==============================================================================
Time& Time::operator+= (RelativeTime delta) { millisSinceEpoch += delta.inMilliseconds(); return *this; }
Time& Time::operator-= (RelativeTime delta) { millisSinceEpoch -= delta.inMilliseconds(); return *this; }
Time operator+ (Time time, RelativeTime delta) { Time t (time); return t += delta; }
Time operator- (Time time, RelativeTime delta) { Time t (time); return t -= delta; }
Time operator+ (RelativeTime delta, Time time) { Time t (time); return t += delta; }
const RelativeTime operator- (Time time1, Time time2) { return RelativeTime::milliseconds (time1.toMilliseconds() - time2.toMilliseconds()); }
bool operator== (Time time1, Time time2) { return time1.toMilliseconds() == time2.toMilliseconds(); }
bool operator!= (Time time1, Time time2) { return time1.toMilliseconds() != time2.toMilliseconds(); }
bool operator< (Time time1, Time time2) { return time1.toMilliseconds() < time2.toMilliseconds(); }
bool operator> (Time time1, Time time2) { return time1.toMilliseconds() > time2.toMilliseconds(); }
bool operator<= (Time time1, Time time2) { return time1.toMilliseconds() <= time2.toMilliseconds(); }
bool operator>= (Time time1, Time time2) { return time1.toMilliseconds() >= time2.toMilliseconds(); }
Time& Time::operator+= (RelativeTime delta) noexcept { millisSinceEpoch += delta.inMilliseconds(); return *this; }
Time& Time::operator-= (RelativeTime delta) noexcept { millisSinceEpoch -= delta.inMilliseconds(); return *this; }
Time operator+ (Time time, RelativeTime delta) noexcept { Time t (time); return t += delta; }
Time operator- (Time time, RelativeTime delta) noexcept { Time t (time); return t -= delta; }
Time operator+ (RelativeTime delta, Time time) noexcept { Time t (time); return t += delta; }
const RelativeTime operator- (Time time1, Time time2) noexcept { return RelativeTime::milliseconds (time1.toMilliseconds() - time2.toMilliseconds()); }
bool operator== (Time time1, Time time2) noexcept { return time1.toMilliseconds() == time2.toMilliseconds(); }
bool operator!= (Time time1, Time time2) noexcept { return time1.toMilliseconds() != time2.toMilliseconds(); }
bool operator< (Time time1, Time time2) noexcept { return time1.toMilliseconds() < time2.toMilliseconds(); }
bool operator> (Time time1, Time time2) noexcept { return time1.toMilliseconds() > time2.toMilliseconds(); }
bool operator<= (Time time1, Time time2) noexcept { return time1.toMilliseconds() <= time2.toMilliseconds(); }
bool operator>= (Time time1, Time time2) noexcept { return time1.toMilliseconds() >= time2.toMilliseconds(); }
static int getMonthNumberForCompileDate (const String& m) noexcept
{
for (int i = 0; i < 12; ++i)
if (m.equalsIgnoreCase (shortMonthNames[i]))
return i;
// If you hit this because your compiler has a non-standard __DATE__ format,
// let me know so we can add support for it!
jassertfalse;
return 0;
}
Time Time::getCompilationDate()
{
StringArray dateTokens;
dateTokens.addTokens (__DATE__, true);
dateTokens.removeEmptyStrings (true);
return Time (dateTokens[2].getIntValue(),
getMonthNumberForCompileDate (dateTokens[0]),
dateTokens[1].getIntValue(), 12, 0);
}

+ 16
- 16
source/modules/juce_core/time/juce_Time.h View File

@@ -253,9 +253,9 @@ public:
//============================================================================== //==============================================================================
/** Adds a RelativeTime to this time. */ /** Adds a RelativeTime to this time. */
Time& operator+= (RelativeTime delta);
Time& operator+= (RelativeTime delta) noexcept;
/** Subtracts a RelativeTime from this time. */ /** Subtracts a RelativeTime from this time. */
Time& operator-= (RelativeTime delta);
Time& operator-= (RelativeTime delta) noexcept;
//============================================================================== //==============================================================================
/** Tries to set the computer's clock. /** Tries to set the computer's clock.
@@ -272,8 +272,7 @@ public:
@param threeLetterVersion if true, it'll return a 3-letter abbreviation, e.g. "Tue"; if @param threeLetterVersion if true, it'll return a 3-letter abbreviation, e.g. "Tue"; if
false, it'll return the full version, e.g. "Tuesday". false, it'll return the full version, e.g. "Tuesday".
*/ */
static String getWeekdayName (int dayNumber,
bool threeLetterVersion);
static String getWeekdayName (int dayNumber, bool threeLetterVersion);
/** Returns the name of one of the months. /** Returns the name of one of the months.
@@ -281,8 +280,7 @@ public:
@param threeLetterVersion if true, it'll be a 3-letter abbreviation, e.g. "Jan"; if false @param threeLetterVersion if true, it'll be a 3-letter abbreviation, e.g. "Jan"; if false
it'll return the long form, e.g. "January" it'll return the long form, e.g. "January"
*/ */
static String getMonthName (int monthNumber,
bool threeLetterVersion);
static String getMonthName (int monthNumber, bool threeLetterVersion);
//============================================================================== //==============================================================================
// Static methods for getting system timers directly.. // Static methods for getting system timers directly..
@@ -370,6 +368,8 @@ public:
*/ */
static int64 secondsToHighResolutionTicks (double seconds) noexcept; static int64 secondsToHighResolutionTicks (double seconds) noexcept;
/** Returns a Time based on the value of the __DATE__ macro when this module was compiled */
static Time getCompilationDate();
private: private:
//============================================================================== //==============================================================================
@@ -378,27 +378,27 @@ private:
//============================================================================== //==============================================================================
/** Adds a RelativeTime to a Time. */ /** Adds a RelativeTime to a Time. */
JUCE_API Time operator+ (Time time, RelativeTime delta);
JUCE_API Time operator+ (Time time, RelativeTime delta) noexcept;
/** Adds a RelativeTime to a Time. */ /** Adds a RelativeTime to a Time. */
JUCE_API Time operator+ (RelativeTime delta, Time time);
JUCE_API Time operator+ (RelativeTime delta, Time time) noexcept;
/** Subtracts a RelativeTime from a Time. */ /** Subtracts a RelativeTime from a Time. */
JUCE_API Time operator- (Time time, RelativeTime delta);
JUCE_API Time operator- (Time time, RelativeTime delta) noexcept;
/** Returns the relative time difference between two times. */ /** Returns the relative time difference between two times. */
JUCE_API const RelativeTime operator- (Time time1, Time time2);
JUCE_API const RelativeTime operator- (Time time1, Time time2) noexcept;
/** Compares two Time objects. */ /** Compares two Time objects. */
JUCE_API bool operator== (Time time1, Time time2);
JUCE_API bool operator== (Time time1, Time time2) noexcept;
/** Compares two Time objects. */ /** Compares two Time objects. */
JUCE_API bool operator!= (Time time1, Time time2);
JUCE_API bool operator!= (Time time1, Time time2) noexcept;
/** Compares two Time objects. */ /** Compares two Time objects. */
JUCE_API bool operator< (Time time1, Time time2);
JUCE_API bool operator< (Time time1, Time time2) noexcept;
/** Compares two Time objects. */ /** Compares two Time objects. */
JUCE_API bool operator<= (Time time1, Time time2);
JUCE_API bool operator<= (Time time1, Time time2) noexcept;
/** Compares two Time objects. */ /** Compares two Time objects. */
JUCE_API bool operator> (Time time1, Time time2);
JUCE_API bool operator> (Time time1, Time time2) noexcept;
/** Compares two Time objects. */ /** Compares two Time objects. */
JUCE_API bool operator>= (Time time1, Time time2);
JUCE_API bool operator>= (Time time1, Time time2) noexcept;
#endif // JUCE_TIME_H_INCLUDED #endif // JUCE_TIME_H_INCLUDED

+ 1
- 2
source/modules/juce_core/zip/juce_ZipFile.cpp View File

@@ -298,8 +298,7 @@ InputStream* ZipFile::createStreamForEntry (const int index)
if (zei->compressed) if (zei->compressed)
{ {
stream = new GZIPDecompressorInputStream (stream, true, true,
zei->entry.uncompressedSize);
stream = new GZIPDecompressorInputStream (stream, true, true, (int64) zei->entry.uncompressedSize);
// (much faster to unzip in big blocks using a buffer..) // (much faster to unzip in big blocks using a buffer..)
stream = new BufferedInputStream (stream, 32768, true); stream = new BufferedInputStream (stream, 32768, true);


+ 1
- 1
source/modules/juce_data_structures/app_properties/juce_PropertiesFile.cpp View File

@@ -82,7 +82,7 @@ File PropertiesFile::Options::getDefaultFile() const
if (folderName.isNotEmpty()) if (folderName.isNotEmpty())
dir = dir.getChildFile (folderName); dir = dir.getChildFile (folderName);
#elif JUCE_LINUX || JUCE_ANDROID
#elif JUCE_LINUX || JUCE_ANDROID || JUCE_HAIKU
const File dir (File (commonToAllUsers ? "/var" : "~") const File dir (File (commonToAllUsers ? "/var" : "~")
.getChildFile (folderName.isNotEmpty() ? folderName .getChildFile (folderName.isNotEmpty() ? folderName
: ("." + applicationName))); : ("." + applicationName)));


+ 7
- 2
source/modules/juce_events/native/juce_linux_Messaging.cpp View File

@@ -358,8 +358,13 @@ bool MessageManager::postMessageToSystemQueue (MessageManager::MessageBase* cons
if (LinuxErrorHandling::errorOccurred) if (LinuxErrorHandling::errorOccurred)
return false; return false;
InternalMessageQueue::getInstanceWithoutCreating()->postMessage (message);
return true;
if (InternalMessageQueue* const queue = InternalMessageQueue::getInstanceWithoutCreating())
{
InternalMessageQueue::getInstanceWithoutCreating()->postMessage (message);
return true;
}
return false;
} }
void MessageManager::broadcastMessage (const String& /* value */) void MessageManager::broadcastMessage (const String& /* value */)


+ 3
- 3
source/modules/juce_graphics/fonts/juce_Font.cpp View File

@@ -278,13 +278,13 @@ Font& Font::operator= (const Font& other) noexcept
#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
Font::Font (Font&& other) noexcept Font::Font (Font&& other) noexcept
: font (static_cast <ReferenceCountedObjectPtr <SharedFontInternal>&&> (other.font))
: font (static_cast<ReferenceCountedObjectPtr<SharedFontInternal>&&> (other.font))
{ {
} }
Font& Font::operator= (Font&& other) noexcept Font& Font::operator= (Font&& other) noexcept
{ {
font = static_cast <ReferenceCountedObjectPtr <SharedFontInternal>&&> (other.font);
font = static_cast<ReferenceCountedObjectPtr<SharedFontInternal>&&> (other.font);
return *this; return *this;
} }
#endif #endif
@@ -640,7 +640,7 @@ float Font::getStringWidthFloat (const String& text) const
return w * font->height * font->horizontalScale; return w * font->height * font->horizontalScale;
} }
void Font::getGlyphPositions (const String& text, Array <int>& glyphs, Array <float>& xOffsets) const
void Font::getGlyphPositions (const String& text, Array<int>& glyphs, Array<float>& xOffsets) const
{ {
getTypeface()->getGlyphPositions (text, glyphs, xOffsets); getTypeface()->getGlyphPositions (text, glyphs, xOffsets);


+ 1
- 1
source/modules/juce_graphics/fonts/juce_Font.h View File

@@ -449,7 +449,7 @@ public:
private: private:
//============================================================================== //==============================================================================
class SharedFontInternal; class SharedFontInternal;
ReferenceCountedObjectPtr <SharedFontInternal> font;
ReferenceCountedObjectPtr<SharedFontInternal> font;
void dupeInternalIfShared(); void dupeInternalIfShared();
void checkTypefaceSuitability(); void checkTypefaceSuitability();
float getHeightToPointsFactor() const; float getHeightToPointsFactor() const;


+ 195
- 157
source/modules/juce_graphics/fonts/juce_GlyphArrangement.cpp View File

@@ -40,6 +40,27 @@ PositionedGlyph::PositionedGlyph (const PositionedGlyph& other)
{ {
} }
#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
PositionedGlyph::PositionedGlyph (PositionedGlyph&& other) noexcept
: font (static_cast<Font&&> (other.font)),
character (other.character), glyph (other.glyph),
x (other.x), y (other.y), w (other.w), whitespace (other.whitespace)
{
}
PositionedGlyph& PositionedGlyph::operator= (PositionedGlyph&& other) noexcept
{
font = static_cast<Font&&> (other.font);
character = other.character;
glyph = other.glyph;
x = other.x;
y = other.y;
w = other.w;
whitespace = other.whitespace;
return *this;
}
#endif
PositionedGlyph::~PositionedGlyph() {} PositionedGlyph::~PositionedGlyph() {}
PositionedGlyph& PositionedGlyph::operator= (const PositionedGlyph& other) PositionedGlyph& PositionedGlyph::operator= (const PositionedGlyph& other)
@@ -182,8 +203,8 @@ void GlyphArrangement::addCurtailedLineOfText (const Font& font,
{ {
if (text.isNotEmpty()) if (text.isNotEmpty())
{ {
Array <int> newGlyphs;
Array <float> xOffsets;
Array<int> newGlyphs;
Array<float> xOffsets;
font.getGlyphPositions (text, newGlyphs, xOffsets); font.getGlyphPositions (text, newGlyphs, xOffsets);
const int textLen = newGlyphs.size(); const int textLen = newGlyphs.size();
glyphs.ensureStorageAllocated (glyphs.size() + textLen); glyphs.ensureStorageAllocated (glyphs.size() + textLen);
@@ -353,174 +374,40 @@ void GlyphArrangement::addFittedText (const Font& f,
if (text.containsAnyOf ("\r\n")) if (text.containsAnyOf ("\r\n"))
{ {
GlyphArrangement ga;
ga.addJustifiedText (f, text, x, y, width, layout);
const Rectangle<float> bb (ga.getBoundingBox (0, -1, false));
float dy = y - bb.getY();
if (layout.testFlags (Justification::verticallyCentred)) dy += (height - bb.getHeight()) * 0.5f;
else if (layout.testFlags (Justification::bottom)) dy += (height - bb.getHeight());
ga.moveRangeOfGlyphs (0, -1, 0.0f, dy);
glyphs.addArray (ga.glyphs);
return;
addLinesWithLineBreaks (text, f, x, y, width, height, layout);
} }
int startIndex = glyphs.size();
addLineOfText (f, text.trim(), x, y);
if (glyphs.size() > startIndex)
else
{ {
float lineWidth = glyphs.getReference (glyphs.size() - 1).getRight()
- glyphs.getReference (startIndex).getLeft();
const int startIndex = glyphs.size();
const String trimmed (text.trim());
addLineOfText (f, trimmed, x, y);
const int numGlyphs = glyphs.size() - startIndex;
if (lineWidth <= 0)
return;
if (lineWidth * minimumHorizontalScale < width)
{
if (lineWidth > width)
stretchRangeOfGlyphs (startIndex, glyphs.size() - startIndex,
width / lineWidth);
justifyGlyphs (startIndex, glyphs.size() - startIndex,
x, y, width, height, layout);
}
else if (maximumLines <= 1)
{
fitLineIntoSpace (startIndex, glyphs.size() - startIndex,
x, y, width, height, f, layout, minimumHorizontalScale);
}
else
if (numGlyphs > 0)
{ {
Font font (f);
String txt (text.trim());
const int length = txt.length();
const int originalStartIndex = startIndex;
int numLines = 1;
if (length <= 12 && ! txt.containsAnyOf (" -\t\r\n"))
maximumLines = 1;
maximumLines = jmin (maximumLines, length);
const float lineWidth = glyphs.getReference (glyphs.size() - 1).getRight()
- glyphs.getReference (startIndex).getLeft();
while (numLines < maximumLines)
if (lineWidth > 0)
{ {
++numLines;
const float newFontHeight = height / (float) numLines;
if (newFontHeight < font.getHeight())
if (lineWidth * minimumHorizontalScale < width)
{ {
font.setHeight (jmax (8.0f, newFontHeight));
if (lineWidth > width)
stretchRangeOfGlyphs (startIndex, numGlyphs, width / lineWidth);
removeRangeOfGlyphs (startIndex, -1);
addLineOfText (font, txt, x, y);
lineWidth = glyphs.getReference (glyphs.size() - 1).getRight()
- glyphs.getReference (startIndex).getLeft();
justifyGlyphs (startIndex, numGlyphs, x, y, width, height, layout);
} }
if (numLines > lineWidth / width || newFontHeight < 8.0f)
break;
}
if (numLines < 1)
numLines = 1;
float lineY = y;
float widthPerLine = lineWidth / numLines;
for (int line = 0; line < numLines; ++line)
{
int i = startIndex;
float lineStartX = glyphs.getReference (startIndex).getLeft();
if (line == numLines - 1)
else if (maximumLines <= 1)
{ {
widthPerLine = width;
i = glyphs.size();
fitLineIntoSpace (startIndex, numGlyphs, x, y, width, height,
f, layout, minimumHorizontalScale);
} }
else else
{ {
while (i < glyphs.size())
{
lineWidth = (glyphs.getReference (i).getRight() - lineStartX);
if (lineWidth > widthPerLine)
{
// got to a point where the line's too long, so skip forward to find a
// good place to break it..
const int searchStartIndex = i;
while (i < glyphs.size())
{
if ((glyphs.getReference (i).getRight() - lineStartX) * minimumHorizontalScale < width)
{
if (glyphs.getReference (i).isWhitespace()
|| glyphs.getReference (i).getCharacter() == '-')
{
++i;
break;
}
}
else
{
// can't find a suitable break, so try looking backwards..
i = searchStartIndex;
for (int back = 1; back < jmin (7, i - startIndex - 1); ++back)
{
if (glyphs.getReference (i - back).isWhitespace()
|| glyphs.getReference (i - back).getCharacter() == '-')
{
i -= back - 1;
break;
}
}
break;
}
++i;
}
break;
}
++i;
}
int wsStart = i;
while (wsStart > 0 && glyphs.getReference (wsStart - 1).isWhitespace())
--wsStart;
int wsEnd = i;
while (wsEnd < glyphs.size() && glyphs.getReference (wsEnd).isWhitespace())
++wsEnd;
removeRangeOfGlyphs (wsStart, wsEnd - wsStart);
i = jmax (wsStart, startIndex + 1);
splitLines (trimmed, f, startIndex, x, y, width, height,
maximumLines, lineWidth, layout, minimumHorizontalScale);
} }
i -= fitLineIntoSpace (startIndex, i - startIndex,
x, lineY, width, font.getHeight(), font,
layout.getOnlyHorizontalFlags() | Justification::verticallyCentred,
minimumHorizontalScale);
startIndex = i;
lineY += font.getHeight();
if (startIndex >= glyphs.size())
break;
} }
justifyGlyphs (originalStartIndex, glyphs.size() - originalStartIndex,
x, y, width, height, layout.getFlags() & ~Justification::horizontallyJustified);
} }
} }
} }
@@ -540,6 +427,24 @@ void GlyphArrangement::moveRangeOfGlyphs (int startIndex, int num, const float d
} }
} }
void GlyphArrangement::addLinesWithLineBreaks (const String& text, const Font& f,
int x, int y, int width, int height, Justification layout)
{
GlyphArrangement ga;
ga.addJustifiedText (f, text, x, y, width, layout);
const Rectangle<float> bb (ga.getBoundingBox (0, -1, false));
float dy = y - bb.getY();
if (layout.testFlags (Justification::verticallyCentred)) dy += (height - bb.getHeight()) * 0.5f;
else if (layout.testFlags (Justification::bottom)) dy += (height - bb.getHeight());
ga.moveRangeOfGlyphs (0, -1, 0.0f, dy);
glyphs.addArray (ga.glyphs);
}
int GlyphArrangement::fitLineIntoSpace (int start, int numGlyphs, float x, float y, float w, float h, const Font& font, int GlyphArrangement::fitLineIntoSpace (int start, int numGlyphs, float x, float y, float w, float h, const Font& font,
Justification justification, float minimumHorizontalScale) Justification justification, float minimumHorizontalScale)
{ {
@@ -702,9 +607,142 @@ void GlyphArrangement::spreadOutLine (const int start, const int num, const floa
} }
} }
void GlyphArrangement::splitLines (const String& text, Font font, int startIndex,
int x, int y, int width, int height, int maximumLines,
float lineWidth, Justification layout, float minimumHorizontalScale)
{
const int length = text.length();
const int originalStartIndex = startIndex;
int numLines = 1;
if (length <= 12 && ! text.containsAnyOf (" -\t\r\n"))
maximumLines = 1;
maximumLines = jmin (maximumLines, length);
while (numLines < maximumLines)
{
++numLines;
const float newFontHeight = height / (float) numLines;
if (newFontHeight < font.getHeight())
{
font.setHeight (jmax (8.0f, newFontHeight));
removeRangeOfGlyphs (startIndex, -1);
addLineOfText (font, text, x, y);
lineWidth = glyphs.getReference (glyphs.size() - 1).getRight()
- glyphs.getReference (startIndex).getLeft();
}
// Try to estimate the point at which there are enough lines to fit the text,
// allowing for unevenness in the lengths due to differently sized words.
const float lineLengthUnevennessAllowance = 80.0f;
if (numLines > (lineWidth + lineLengthUnevennessAllowance) / width || newFontHeight < 8.0f)
break;
}
if (numLines < 1)
numLines = 1;
float lineY = y;
float widthPerLine = lineWidth / numLines;
for (int line = 0; line < numLines; ++line)
{
int i = startIndex;
float lineStartX = glyphs.getReference (startIndex).getLeft();
if (line == numLines - 1)
{
widthPerLine = width;
i = glyphs.size();
}
else
{
while (i < glyphs.size())
{
lineWidth = (glyphs.getReference (i).getRight() - lineStartX);
if (lineWidth > widthPerLine)
{
// got to a point where the line's too long, so skip forward to find a
// good place to break it..
const int searchStartIndex = i;
while (i < glyphs.size())
{
if ((glyphs.getReference (i).getRight() - lineStartX) * minimumHorizontalScale < width)
{
if (glyphs.getReference (i).isWhitespace()
|| glyphs.getReference (i).getCharacter() == '-')
{
++i;
break;
}
}
else
{
// can't find a suitable break, so try looking backwards..
i = searchStartIndex;
for (int back = 1; back < jmin (7, i - startIndex - 1); ++back)
{
if (glyphs.getReference (i - back).isWhitespace()
|| glyphs.getReference (i - back).getCharacter() == '-')
{
i -= back - 1;
break;
}
}
break;
}
++i;
}
break;
}
++i;
}
int wsStart = i;
while (wsStart > 0 && glyphs.getReference (wsStart - 1).isWhitespace())
--wsStart;
int wsEnd = i;
while (wsEnd < glyphs.size() && glyphs.getReference (wsEnd).isWhitespace())
++wsEnd;
removeRangeOfGlyphs (wsStart, wsEnd - wsStart);
i = jmax (wsStart, startIndex + 1);
}
i -= fitLineIntoSpace (startIndex, i - startIndex,
x, lineY, width, font.getHeight(), font,
layout.getOnlyHorizontalFlags() | Justification::verticallyCentred,
minimumHorizontalScale);
startIndex = i;
lineY += font.getHeight();
if (startIndex >= glyphs.size())
break;
}
justifyGlyphs (originalStartIndex, glyphs.size() - originalStartIndex,
x, y, width, height, layout.getFlags() & ~Justification::horizontallyJustified);
}
//============================================================================== //==============================================================================
inline void GlyphArrangement::drawGlyphUnderline (const Graphics& g, const PositionedGlyph& pg,
const int i, const AffineTransform& transform) const
void GlyphArrangement::drawGlyphUnderline (const Graphics& g, const PositionedGlyph& pg,
const int i, const AffineTransform& transform) const
{ {
const float lineThickness = (pg.font.getDescent()) * 0.3f; const float lineThickness = (pg.font.getDescent()) * 0.3f;


+ 10
- 1
source/modules/juce_graphics/fonts/juce_GlyphArrangement.h View File

@@ -46,6 +46,12 @@ public:
PositionedGlyph (const PositionedGlyph&); PositionedGlyph (const PositionedGlyph&);
PositionedGlyph& operator= (const PositionedGlyph&); PositionedGlyph& operator= (const PositionedGlyph&);
#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
PositionedGlyph (PositionedGlyph&&) noexcept;
PositionedGlyph& operator= (PositionedGlyph&&) noexcept;
#endif
~PositionedGlyph(); ~PositionedGlyph();
/** Returns the character the glyph represents. */ /** Returns the character the glyph represents. */
@@ -295,12 +301,15 @@ public:
private: private:
//============================================================================== //==============================================================================
Array <PositionedGlyph> glyphs;
Array<PositionedGlyph> glyphs;
int insertEllipsis (const Font&, float maxXPos, int startIndex, int endIndex); int insertEllipsis (const Font&, float maxXPos, int startIndex, int endIndex);
int fitLineIntoSpace (int start, int numGlyphs, float x, float y, float w, float h, const Font&, int fitLineIntoSpace (int start, int numGlyphs, float x, float y, float w, float h, const Font&,
Justification, float minimumHorizontalScale); Justification, float minimumHorizontalScale);
void spreadOutLine (int start, int numGlyphs, float targetWidth); void spreadOutLine (int start, int numGlyphs, float targetWidth);
void splitLines (const String&, Font, int start, int x, int y, int w, int h, int maxLines,
float lineWidth, Justification, float minimumHorizontalScale);
void addLinesWithLineBreaks (const String&, const Font&, int x, int y, int width, int height, Justification);
void drawGlyphUnderline (const Graphics&, const PositionedGlyph&, int, const AffineTransform&) const; void drawGlyphUnderline (const Graphics&, const PositionedGlyph&, int, const AffineTransform&) const;
JUCE_LEAK_DETECTOR (GlyphArrangement) JUCE_LEAK_DETECTOR (GlyphArrangement)


+ 11
- 0
source/modules/juce_graphics/geometry/juce_RectangleList.h View File

@@ -628,6 +628,17 @@ public:
/** Standard method for iterating the rectangles in the list. */ /** Standard method for iterating the rectangles in the list. */
const RectangleType* end() const noexcept { return rects.end(); } const RectangleType* end() const noexcept { return rects.end(); }
/** Increases the internal storage to hold a minimum number of rectangles.
Calling this before adding a large number of rectangles means that
the array won't have to keep dynamically resizing itself as the elements
are added, and it'll therefore be more efficient.
@see Array::ensureStorageAllocated
*/
void ensureStorageAllocated (int minNumRectangles)
{
rects.ensureStorageAllocated (minNumRectangles);
}
private: private:
//============================================================================== //==============================================================================
Array<RectangleType> rects; Array<RectangleType> rects;


+ 32
- 15
source/modules/juce_graphics/native/juce_win32_DirectWriteTypeLayout.cpp View File

@@ -29,8 +29,9 @@ namespace DirectWriteTypeLayout
class CustomDirectWriteTextRenderer : public ComBaseClassHelper<IDWriteTextRenderer> class CustomDirectWriteTextRenderer : public ComBaseClassHelper<IDWriteTextRenderer>
{ {
public: public:
CustomDirectWriteTextRenderer (IDWriteFontCollection* const fonts)
CustomDirectWriteTextRenderer (IDWriteFontCollection* const fonts, const AttributedString& as)
: ComBaseClassHelper<IDWriteTextRenderer> (0), : ComBaseClassHelper<IDWriteTextRenderer> (0),
attributedString (as),
fontCollection (fonts), fontCollection (fonts),
currentLine (-1), currentLine (-1),
lastOriginY (-10000.0f) lastOriginY (-10000.0f)
@@ -89,20 +90,16 @@ namespace DirectWriteTypeLayout
glyphLine.ascent = jmax (glyphLine.ascent, scaledFontSize (dwFontMetrics.ascent, dwFontMetrics, glyphRun)); glyphLine.ascent = jmax (glyphLine.ascent, scaledFontSize (dwFontMetrics.ascent, dwFontMetrics, glyphRun));
glyphLine.descent = jmax (glyphLine.descent, scaledFontSize (dwFontMetrics.descent, dwFontMetrics, glyphRun)); glyphLine.descent = jmax (glyphLine.descent, scaledFontSize (dwFontMetrics.descent, dwFontMetrics, glyphRun));
String fontFamily, fontStyle;
getFontFamilyAndStyle (glyphRun, fontFamily, fontStyle);
TextLayout::Run* const glyphRunLayout = new TextLayout::Run (Range<int> (runDescription->textPosition, TextLayout::Run* const glyphRunLayout = new TextLayout::Run (Range<int> (runDescription->textPosition,
runDescription->textPosition + runDescription->stringLength), runDescription->textPosition + runDescription->stringLength),
glyphRun->glyphCount); glyphRun->glyphCount);
glyphLine.runs.add (glyphRunLayout); glyphLine.runs.add (glyphRunLayout);
glyphRun->fontFace->GetMetrics (&dwFontMetrics); glyphRun->fontFace->GetMetrics (&dwFontMetrics);
const float totalHeight = std::abs ((float) dwFontMetrics.ascent) + std::abs ((float) dwFontMetrics.descent); const float totalHeight = std::abs ((float) dwFontMetrics.ascent) + std::abs ((float) dwFontMetrics.descent);
const float fontHeightToEmSizeFactor = (float) dwFontMetrics.designUnitsPerEm / totalHeight; const float fontHeightToEmSizeFactor = (float) dwFontMetrics.designUnitsPerEm / totalHeight;
glyphRunLayout->font = Font (fontFamily, fontStyle, glyphRun->fontEmSize / fontHeightToEmSizeFactor);
glyphRunLayout->font = getFontForRun (glyphRun, glyphRun->fontEmSize / fontHeightToEmSizeFactor);
glyphRunLayout->colour = getColourOf (static_cast<ID2D1SolidColorBrush*> (clientDrawingEffect)); glyphRunLayout->colour = getColourOf (static_cast<ID2D1SolidColorBrush*> (clientDrawingEffect));
const Point<float> lineOrigin (layout->getLine (currentLine).lineOrigin); const Point<float> lineOrigin (layout->getLine (currentLine).lineOrigin);
@@ -127,6 +124,7 @@ namespace DirectWriteTypeLayout
} }
private: private:
const AttributedString& attributedString;
IDWriteFontCollection* const fontCollection; IDWriteFontCollection* const fontCollection;
int currentLine; int currentLine;
float lastOriginY; float lastOriginY;
@@ -145,19 +143,22 @@ namespace DirectWriteTypeLayout
return Colour::fromFloatRGBA (colour.r, colour.g, colour.b, colour.a); return Colour::fromFloatRGBA (colour.r, colour.g, colour.b, colour.a);
} }
void getFontFamilyAndStyle (DWRITE_GLYPH_RUN const* glyphRun, String& family, String& style) const
Font getFontForRun (DWRITE_GLYPH_RUN const* glyphRun, float fontHeight)
{ {
for (int i = 0; i < attributedString.getNumAttributes(); ++i)
if (const Font* font = attributedString.getAttribute(i)->getFont())
if (WindowsDirectWriteTypeface* wt = dynamic_cast<WindowsDirectWriteTypeface*> (font->getTypeface()))
if (wt->getIDWriteFontFace() == glyphRun->fontFace)
return font->withHeight (fontHeight);
ComSmartPtr<IDWriteFont> dwFont; ComSmartPtr<IDWriteFont> dwFont;
HRESULT hr = fontCollection->GetFontFromFontFace (glyphRun->fontFace, dwFont.resetAndGetPointerAddress()); HRESULT hr = fontCollection->GetFontFromFontFace (glyphRun->fontFace, dwFont.resetAndGetPointerAddress());
jassert (dwFont != nullptr); jassert (dwFont != nullptr);
{
ComSmartPtr<IDWriteFontFamily> dwFontFamily;
hr = dwFont->GetFontFamily (dwFontFamily.resetAndGetPointerAddress());
family = getFontFamilyName (dwFontFamily);
}
ComSmartPtr<IDWriteFontFamily> dwFontFamily;
hr = dwFont->GetFontFamily (dwFontFamily.resetAndGetPointerAddress());
style = getFontFaceName (dwFont);
return Font (getFontFamilyName (dwFontFamily), getFontFaceName (dwFont), fontHeight);
} }
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CustomDirectWriteTextRenderer) JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CustomDirectWriteTextRenderer)
@@ -352,11 +353,11 @@ namespace DirectWriteTypeLayout
layout.ensureStorageAllocated (actualLineCount); layout.ensureStorageAllocated (actualLineCount);
{ {
ComSmartPtr<CustomDirectWriteTextRenderer> textRenderer (new CustomDirectWriteTextRenderer (fontCollection));
ComSmartPtr<CustomDirectWriteTextRenderer> textRenderer (new CustomDirectWriteTextRenderer (fontCollection, text));
hr = dwTextLayout->Draw (&layout, textRenderer, 0, 0); hr = dwTextLayout->Draw (&layout, textRenderer, 0, 0);
} }
HeapBlock <DWRITE_LINE_METRICS> dwLineMetrics (actualLineCount);
HeapBlock<DWRITE_LINE_METRICS> dwLineMetrics (actualLineCount);
hr = dwTextLayout->GetLineMetrics (dwLineMetrics, actualLineCount, &actualLineCount); hr = dwTextLayout->GetLineMetrics (dwLineMetrics, actualLineCount, &actualLineCount);
int lastLocation = 0; int lastLocation = 0;
const int numLines = jmin ((int) actualLineCount, layout.getNumLines()); const int numLines = jmin ((int) actualLineCount, layout.getNumLines());
@@ -384,11 +385,27 @@ namespace DirectWriteTypeLayout
} }
} }
} }
static bool canAllTypefacesBeUsedInLayout (const AttributedString& text)
{
const int numCharacterAttributes = text.getNumAttributes();
for (int i = 0; i < numCharacterAttributes; ++i)
if (const Font* const font = text.getAttribute (i)->getFont())
if (dynamic_cast<WindowsDirectWriteTypeface*> (font->getTypeface()) == nullptr)
return false;
return true;
}
#endif #endif
bool TextLayout::createNativeLayout (const AttributedString& text) bool TextLayout::createNativeLayout (const AttributedString& text)
{ {
#if JUCE_USE_DIRECTWRITE #if JUCE_USE_DIRECTWRITE
if (! canAllTypefacesBeUsedInLayout (text))
return false;
SharedResourcePointer<Direct2DFactories> factories; SharedResourcePointer<Direct2DFactories> factories;
if (factories->d2dFactory != nullptr && factories->systemFonts != nullptr) if (factories->d2dFactory != nullptr && factories->systemFonts != nullptr)


+ 15
- 15
source/modules/juce_graphics/native/juce_win32_DirectWriteTypeface.cpp View File

@@ -139,26 +139,26 @@ public:
hr = fontCollection->GetFontFamily (fontIndex, dwFontFamily.resetAndGetPointerAddress()); hr = fontCollection->GetFontFamily (fontIndex, dwFontFamily.resetAndGetPointerAddress());
// Get a specific font in the font family using typeface style // Get a specific font in the font family using typeface style
ComSmartPtr<IDWriteFont> dwFont;
uint32 fontFacesCount = 0;
fontFacesCount = dwFontFamily->GetFontCount();
for (int i = fontFacesCount; --i >= 0;)
{ {
hr = dwFontFamily->GetFont (i, dwFont.resetAndGetPointerAddress());
ComSmartPtr<IDWriteFont> dwFont;
if (i == 0)
break;
for (int i = (int) dwFontFamily->GetFontCount(); --i >= 0;)
{
hr = dwFontFamily->GetFont (i, dwFont.resetAndGetPointerAddress());
ComSmartPtr<IDWriteLocalizedStrings> faceNames;
hr = dwFont->GetFaceNames (faceNames.resetAndGetPointerAddress());
if (i == 0)
break;
if (font.getTypefaceStyle() == getLocalisedName (faceNames))
break;
}
ComSmartPtr<IDWriteLocalizedStrings> faceNames;
hr = dwFont->GetFaceNames (faceNames.resetAndGetPointerAddress());
jassert (dwFont != nullptr);
hr = dwFont->CreateFontFace (dwFontFace.resetAndGetPointerAddress());
if (font.getTypefaceStyle() == getLocalisedName (faceNames))
break;
}
jassert (dwFont != nullptr);
hr = dwFont->CreateFontFace (dwFontFace.resetAndGetPointerAddress());
}
if (dwFontFace != nullptr) if (dwFontFace != nullptr)
{ {


+ 6
- 1
source/modules/juce_gui_basics/filebrowser/juce_FilenameComponent.cpp View File

@@ -162,9 +162,14 @@ void FilenameComponent::fileDragExit (const StringArray&)
} }
//============================================================================== //==============================================================================
String FilenameComponent::getCurrentFileText() const
{
return filenameBox.getText();
}
File FilenameComponent::getCurrentFile() const File FilenameComponent::getCurrentFile() const
{ {
File f (File::getCurrentWorkingDirectory().getChildFile (filenameBox.getText()));
File f (File::getCurrentWorkingDirectory().getChildFile (getCurrentFileText()));
if (enforcedSuffix.isNotEmpty()) if (enforcedSuffix.isNotEmpty())
f = f.withFileExtension (enforcedSuffix); f = f.withFileExtension (enforcedSuffix);


+ 3
- 0
source/modules/juce_gui_basics/filebrowser/juce_FilenameComponent.h View File

@@ -103,6 +103,9 @@ public:
/** Returns the currently displayed filename. */ /** Returns the currently displayed filename. */
File getCurrentFile() const; File getCurrentFile() const;
/** Returns the raw text that the user has entered. */
String getCurrentFileText() const;
/** Changes the current filename. /** Changes the current filename.
@param newFile the new filename to use @param newFile the new filename to use


+ 2
- 0
source/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm View File

@@ -1222,6 +1222,8 @@ private:
const Rectangle<int> clipBounds (clipW, clipH); const Rectangle<int> clipBounds (clipW, clipH);
const CGFloat viewH = [view frame].size.height; const CGFloat viewH = [view frame].size.height;
clip.ensureStorageAllocated ((int) numRects);
for (int i = 0; i < numRects; ++i) for (int i = 0; i < numRects; ++i)
clip.addWithoutMerging (clipBounds.getIntersection (Rectangle<int> (roundToInt (rects[i].origin.x) + offset.x, clip.addWithoutMerging (clipBounds.getIntersection (Rectangle<int> (roundToInt (rects[i].origin.x) + offset.x,
roundToInt (viewH - (rects[i].origin.y + rects[i].size.height)) + offset.y, roundToInt (viewH - (rects[i].origin.y + rects[i].size.height)) + offset.y,


+ 3
- 0
source/modules/juce_gui_extra/native/juce_mac_SystemTrayIcon.cpp View File

@@ -53,7 +53,10 @@ public:
~Pimpl() ~Pimpl()
{ {
[[NSNotificationCenter defaultCenter] removeObserver: view];
[[NSStatusBar systemStatusBar] removeStatusItem: statusItem]; [[NSStatusBar systemStatusBar] removeStatusItem: statusItem];
SystemTrayViewClass::setOwner (view, nullptr);
SystemTrayViewClass::setImage (view, nil);
[statusItem release]; [statusItem release];
[view release]; [view release];
[statusIcon release]; [statusIcon release];


Loading…
Cancel
Save