Browse Source

Refactored the linux Freetype font code and native file chooser (via zenity).

tags/2021-05-28
jules 13 years ago
parent
commit
fce514266e
9 changed files with 301 additions and 383 deletions
  1. +14
    -41
      modules/juce_events/native/juce_linux_Messaging.cpp
  2. +235
    -294
      modules/juce_graphics/native/juce_linux_Fonts.cpp
  3. +7
    -4
      modules/juce_gui_basics/filebrowser/juce_FileChooser.cpp
  4. +1
    -0
      modules/juce_gui_basics/filebrowser/juce_FileChooser.h
  5. +5
    -0
      modules/juce_gui_basics/native/juce_android_FileChooser.cpp
  6. +3
    -3
      modules/juce_gui_basics/native/juce_linux_Clipboard.cpp
  7. +21
    -41
      modules/juce_gui_basics/native/juce_linux_FileChooser.cpp
  8. +10
    -0
      modules/juce_gui_basics/native/juce_mac_FileChooser.mm
  9. +5
    -0
      modules/juce_gui_basics/native/juce_win32_FileChooser.cpp

+ 14
- 41
modules/juce_events/native/juce_linux_Messaging.cpp View File

@@ -48,9 +48,6 @@ public:
{
int ret = ::socketpair (AF_LOCAL, SOCK_STREAM, 0, fd);
(void) ret; jassert (ret == 0);
//setNonBlocking (fd[0]);
//setNonBlocking (fd[1]);
}
~InternalMessageQueue()
@@ -131,18 +128,6 @@ public:
return (ret > 0); // ret <= 0 if error or timeout
}
//==============================================================================
struct MessageThreadFuncCall
{
enum { uniqueID = 0x73774623 };
MessageCallbackFunction* func;
void* parameter;
void* result;
CriticalSection lock;
WaitableEvent event;
};
//==============================================================================
juce_DeclareSingleton_SingleThreaded_Minimal (InternalMessageQueue);
@@ -212,20 +197,7 @@ private:
if (msg == nullptr)
return false;
if (msg->intParameter1 == MessageThreadFuncCall::uniqueID)
{
// Handle callback message
MessageThreadFuncCall* const call = (MessageThreadFuncCall*) msg->pointerParameter;
call->result = (*(call->func)) (call->parameter);
call->event.signal();
}
else
{
// Handle "normal" messages
MessageManager::getInstance()->deliverMessage (msg);
}
MessageManager::getInstance()->deliverMessage (msg);
return true;
}
};
@@ -236,7 +208,6 @@ juce_ImplementSingleton_SingleThreaded (InternalMessageQueue);
//==============================================================================
namespace LinuxErrorHandling
{
//==============================================================================
static bool errorOccurred = false;
static bool keyboardBreakOccurred = false;
static XErrorHandler oldErrorHandler = (XErrorHandler) 0;
@@ -244,7 +215,7 @@ namespace LinuxErrorHandling
//==============================================================================
// Usually happens when client-server connection is broken
static int ioErrorHandler (Display* display)
int ioErrorHandler (Display* display)
{
DBG ("ERROR: connection to X server broken.. terminating.");
@@ -255,8 +226,7 @@ namespace LinuxErrorHandling
return 0;
}
// A protocol error has occurred
static int juce_XErrorHandler (Display* display, XErrorEvent* event)
int errorHandler (Display* display, XErrorEvent* event)
{
#if JUCE_DEBUG_XERRORS
char errorStr[64] = { 0 };
@@ -270,13 +240,13 @@ namespace LinuxErrorHandling
return 0;
}
static void installXErrorHandlers()
void installXErrorHandlers()
{
oldIOErrorHandler = XSetIOErrorHandler (ioErrorHandler);
oldErrorHandler = XSetErrorHandler (juce_XErrorHandler);
oldErrorHandler = XSetErrorHandler (errorHandler);
}
static void removeXErrorHandlers()
void removeXErrorHandlers()
{
if (JUCEApplicationBase::isStandaloneApp())
{
@@ -289,13 +259,13 @@ namespace LinuxErrorHandling
}
//==============================================================================
static void keyboardBreakSignalHandler (int sig)
void keyboardBreakSignalHandler (int sig)
{
if (sig == SIGINT)
keyboardBreakOccurred = true;
}
static void installKeyboardBreakHandler()
void installKeyboardBreakHandler()
{
struct sigaction saction;
sigset_t maskSet;
@@ -419,7 +389,7 @@ private:
void* volatile result;
AsyncFunctionCaller (MessageCallbackFunction* func_, void* parameter_)
: result (0), func (func_), parameter (parameter_)
: result (nullptr), func (func_), parameter (parameter_)
{}
JUCE_DECLARE_NON_COPYABLE (AsyncFunctionCaller);
@@ -448,13 +418,16 @@ bool MessageManager::dispatchNextMessageOnSystemQueue (bool returnIfNoPendingMes
break;
}
if (InternalMessageQueue::getInstanceWithoutCreating()->dispatchNextEvent())
InternalMessageQueue* const queue = InternalMessageQueue::getInstanceWithoutCreating();
jassert (queue != nullptr);
if (queue->dispatchNextEvent())
return true;
if (returnIfNoPendingMessages)
break;
InternalMessageQueue::getInstanceWithoutCreating()->sleepUntilEvent (2000);
queue->sleepUntilEvent (2000);
}
return false;


+ 235
- 294
modules/juce_graphics/native/juce_linux_Fonts.cpp View File

@@ -23,60 +23,52 @@
==============================================================================
*/
class FreeTypeFontFace
struct FTLibWrapper : public ReferenceCountedObject
{
public:
//==============================================================================
enum FontStyle
FTLibWrapper() : library (0)
{
Plain = 0,
Bold = 1,
Italic = 2
};
//==============================================================================
FreeTypeFontFace (const String& familyName)
: hasSerif (false),
monospaced (false)
{
family = familyName;
}
void setFileName (const String& name, const int faceIndex, FontStyle style)
{
if (names [(int) style].fileName.isEmpty())
if (FT_Init_FreeType (&library) != 0)
{
names [(int) style].fileName = name;
names [(int) style].faceIndex = faceIndex;
library = 0;
DBG ("Failed to initialize FreeType");
}
}
const String& getFamilyName() const noexcept { return family; }
const String& getFileName (const int style, int& faceIndex) const noexcept
~FTLibWrapper()
{
faceIndex = names[style].faceIndex;
return names[style].fileName;
if (library != 0)
FT_Done_FreeType (library);
}
void setMonospaced (bool mono) noexcept { monospaced = mono; }
bool getMonospaced() const noexcept { return monospaced; }
FT_Library library;
void setSerif (const bool serif) noexcept { hasSerif = serif; }
bool getSerif() const noexcept { return hasSerif; }
typedef ReferenceCountedObjectPtr <FTLibWrapper> Ptr;
private:
//==============================================================================
String family;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FTLibWrapper);
};
struct FontNameIndex
//==============================================================================
struct FTFaceWrapper : public ReferenceCountedObject
{
FTFaceWrapper (const FTLibWrapper::Ptr& ftLib, const File& file, int faceIndex)
: face (0), library (ftLib)
{
String fileName;
int faceIndex;
};
if (FT_New_Face (ftLib->library, file.getFullPathName().toUTF8(), faceIndex, &face) != 0)
face = 0;
}
FontNameIndex names[4];
bool hasSerif, monospaced;
~FTFaceWrapper()
{
if (face != 0)
FT_Done_Face (face);
}
FT_Face face;
FTLibWrapper::Ptr library;
typedef ReferenceCountedObjectPtr <FTFaceWrapper> Ptr;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FTFaceWrapper);
};
//==============================================================================
@@ -130,67 +122,35 @@ private:
StringArray fontDirs;
int index;
ScopedPointer<DirectoryIterator> iter;
};
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LinuxFontFileIterator);
};
//==============================================================================
class FreeTypeInterface : public DeletedAtShutdown
class FTTypefaceList : public DeletedAtShutdown
{
public:
//==============================================================================
FreeTypeInterface()
: ftLib (0),
lastFace (0),
lastBold (false),
lastItalic (false)
FTTypefaceList()
: library (new FTLibWrapper())
{
if (FT_Init_FreeType (&ftLib) != 0)
{
ftLib = 0;
DBG ("Failed to initialize FreeType");
}
LinuxFontFileIterator fontFileIterator;
while (fontFileIterator.next())
{
FT_Face face;
int faceIndex = 0;
int numFaces = 0;
do
{
if (FT_New_Face (ftLib, fontFileIterator.getFile().getFullPathName().toUTF8(),
faceIndex, &face) == 0)
FTFaceWrapper face (library, fontFileIterator.getFile(), faceIndex);
if (face.face != 0)
{
if (faceIndex == 0)
numFaces = face->num_faces;
if ((face->face_flags & FT_FACE_FLAG_SCALABLE) != 0)
{
FreeTypeFontFace* const newFace = findOrCreate (face->family_name, true);
int style = (int) FreeTypeFontFace::Plain;
if ((face->style_flags & FT_STYLE_FLAG_BOLD) != 0)
style |= (int) FreeTypeFontFace::Bold;
if ((face->style_flags & FT_STYLE_FLAG_ITALIC) != 0)
style |= (int) FreeTypeFontFace::Italic;
newFace->setFileName (fontFileIterator.getFile().getFullPathName(),
faceIndex, (FreeTypeFontFace::FontStyle) style);
newFace->setMonospaced ((face->face_flags & FT_FACE_FLAG_FIXED_WIDTH) != 0);
// Surely there must be a better way to do this?
const String name (face->family_name);
newFace->setSerif (! (name.containsIgnoreCase ("Sans")
|| name.containsIgnoreCase ("Verdana")
|| name.containsIgnoreCase ("Arial")));
//DBG (fontFileIterator.getFile().getFullPathName() << " - " << name);
}
numFaces = face.face->num_faces;
FT_Done_Face (face);
if ((face.face->face_flags & FT_FACE_FLAG_SCALABLE) != 0)
faces.add (new KnownTypeface (fontFileIterator.getFile(), faceIndex, face));
}
++faceIndex;
@@ -199,129 +159,200 @@ public:
}
}
~FreeTypeInterface()
~FTTypefaceList()
{
if (lastFace != 0)
FT_Done_Face (lastFace);
if (ftLib != 0)
FT_Done_FreeType (ftLib);
clearSingletonInstance();
}
//==============================================================================
FreeTypeFontFace* findOrCreate (const String& familyName, const bool create = false)
struct KnownTypeface
{
for (int i = 0; i < faces.size(); i++)
if (faces[i]->getFamilyName() == familyName)
return faces[i];
if (! create)
return nullptr;
KnownTypeface (const File& file_, const int faceIndex_, const FTFaceWrapper& face)
: file (file_),
family (face.face->family_name),
faceIndex (faceIndex_),
isBold ((face.face->style_flags & FT_STYLE_FLAG_BOLD) != 0),
isItalic ((face.face->style_flags & FT_STYLE_FLAG_ITALIC) != 0),
isMonospaced ((face.face->face_flags & FT_FACE_FLAG_FIXED_WIDTH) != 0),
isSansSerif (isFaceSansSerif (family))
{
}
FreeTypeFontFace* newFace = new FreeTypeFontFace (familyName);
faces.add (newFace);
const File file;
const String family;
const int faceIndex;
const bool isBold, isItalic, isMonospaced, isSansSerif;
return newFace;
}
JUCE_DECLARE_NON_COPYABLE (KnownTypeface);
};
// Create a FreeType face object for a given font
FT_Face createFT_Face (const String& fontName, const bool bold, const bool italic)
//==============================================================================
FTFaceWrapper::Ptr createFace (const String& fontName, const bool bold, const bool italic)
{
FT_Face face = 0;
const KnownTypeface* ftFace = matchTypeface (fontName, bold, italic);
if (fontName == lastFontName && bold == lastBold && italic == lastItalic)
if (ftFace == nullptr)
{
face = lastFace;
ftFace = matchTypeface (fontName, ! bold, italic);
if (ftFace == nullptr)
{
ftFace = matchTypeface (fontName, bold, ! italic);
if (ftFace == nullptr)
ftFace = matchTypeface (fontName, ! bold, ! italic);
}
}
else
if (ftFace != nullptr)
{
if (lastFace != 0)
FTFaceWrapper::Ptr face (new FTFaceWrapper (library, ftFace->file, ftFace->faceIndex));
if (face->face != 0)
{
FT_Done_Face (lastFace);
lastFace = 0;
// If there isn't a unicode charmap then select the first one.
if (FT_Select_Charmap (face->face, ft_encoding_unicode) != 0)
FT_Set_Charmap (face->face, face->face->charmaps[0]);
return face;
}
}
lastFontName = fontName;
lastBold = bold;
lastItalic = italic;
return nullptr;
}
FreeTypeFontFace* const ftFace = findOrCreate (fontName);
//==============================================================================
void getFamilyNames (StringArray& familyNames) const
{
for (int i = 0; i < faces.size(); i++)
familyNames.addIfNotAlreadyThere (faces.getUnchecked(i)->family);
}
if (ftFace != 0)
{
int style = (int) FreeTypeFontFace::Plain;
void getMonospacedNames (StringArray& monoSpaced) const
{
for (int i = 0; i < faces.size(); i++)
if (faces.getUnchecked(i)->isMonospaced)
monoSpaced.addIfNotAlreadyThere (faces.getUnchecked(i)->family);
}
void getSerifNames (StringArray& serif) const
{
for (int i = 0; i < faces.size(); i++)
if (! faces.getUnchecked(i)->isSansSerif)
serif.addIfNotAlreadyThere (faces.getUnchecked(i)->family);
}
void getSansSerifNames (StringArray& sansSerif) const
{
for (int i = 0; i < faces.size(); i++)
if (faces.getUnchecked(i)->isSansSerif)
sansSerif.addIfNotAlreadyThere (faces.getUnchecked(i)->family);
}
if (bold)
style |= (int) FreeTypeFontFace::Bold;
juce_DeclareSingleton_SingleThreaded_Minimal (FTTypefaceList);
if (italic)
style |= (int) FreeTypeFontFace::Italic;
private:
FTLibWrapper::Ptr library;
OwnedArray<KnownTypeface> faces;
int faceIndex;
String fileName (ftFace->getFileName (style, faceIndex));
const KnownTypeface* matchTypeface (const String& familyName, const bool wantBold, const bool wantItalic) const noexcept
{
for (int i = 0; i < faces.size(); ++i)
{
const KnownTypeface* const face = faces.getUnchecked(i);
if (fileName.isEmpty())
{
style ^= (int) FreeTypeFontFace::Bold;
if (face->family == familyName
&& face->isBold == wantBold
&& face->isItalic == wantItalic)
return face;
}
fileName = ftFace->getFileName (style, faceIndex);
return nullptr;
}
if (fileName.isEmpty())
{
style ^= (int) FreeTypeFontFace::Bold;
style ^= (int) FreeTypeFontFace::Italic;
static bool isFaceSansSerif (const String& family)
{
const char* sansNames[] = { "Sans", "Verdana", "Arial", "Ubuntu" };
fileName = ftFace->getFileName (style, faceIndex);
for (int i = 0; i < numElementsInArray (sansNames); ++i)
if (family.containsIgnoreCase (sansNames[i]))
return true;
if (! fileName.length())
{
style ^= (int) FreeTypeFontFace::Bold;
fileName = ftFace->getFileName (style, faceIndex);
}
}
}
return false;
}
JUCE_DECLARE_NON_COPYABLE (FTTypefaceList);
};
juce_ImplementSingleton_SingleThreaded (FTTypefaceList)
//==============================================================================
class FreeTypeTypeface : public CustomTypeface
{
public:
FreeTypeTypeface (const Font& font)
: faceWrapper (FTTypefaceList::getInstance()
->createFace (font.getTypefaceName(), font.isBold(), font.isItalic()))
{
if (faceWrapper != nullptr)
{
setCharacteristics (font.getTypefaceName(),
faceWrapper->face->ascender / (float) (faceWrapper->face->ascender - faceWrapper->face->descender),
font.isBold(), font.isItalic(),
L' ');
}
else
{
DBG ("Failed to create typeface: " << font.getTypefaceName() << " "
<< (font.isBold() ? 'B' : ' ') << (font.isItalic() ? 'I' : ' '));
}
}
bool loadGlyphIfPossible (const juce_wchar character)
{
if (faceWrapper != nullptr)
{
FT_Face face = faceWrapper->face;
const unsigned int glyphIndex = FT_Get_Char_Index (face, character);
if (FT_Load_Glyph (face, glyphIndex, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM) == 0
&& face->glyph->format == ft_glyph_format_outline)
{
const float scale = 1.0f / (float) (face->ascender - face->descender);
Path destShape;
if (! FT_New_Face (ftLib, fileName.toUTF8(), faceIndex, &lastFace))
if (getGlyphShape (destShape, face->glyph->outline, scale))
{
face = lastFace;
addGlyph (character, destShape, face->glyph->metrics.horiAdvance * scale);
// If there isn't a unicode charmap then select the first one.
if (FT_Select_Charmap (face, ft_encoding_unicode))
FT_Set_Charmap (face, face->charmaps[0]);
if ((face->face_flags & FT_FACE_FLAG_KERNING) != 0)
addKerning (face, character, glyphIndex);
return true;
}
}
}
return face;
return false;
}
bool addGlyph (FT_Face face, CustomTypeface& dest, uint32 character)
{
const unsigned int glyphIndex = FT_Get_Char_Index (face, character);
const float height = (float) (face->ascender - face->descender);
const float scaleX = 1.0f / height;
const float scaleY = -1.0f / height;
Path destShape;
if (FT_Load_Glyph (face, glyphIndex, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM) != 0
|| face->glyph->format != ft_glyph_format_outline)
{
return false;
}
private:
FTFaceWrapper::Ptr faceWrapper;
const FT_Outline* const outline = &face->glyph->outline;
const short* const contours = outline->contours;
const char* const tags = outline->tags;
FT_Vector* const points = outline->points;
bool getGlyphShape (Path& destShape, const FT_Outline& outline, const float scaleX)
{
const float scaleY = -scaleX;
const short* const contours = outline.contours;
const char* const tags = outline.tags;
const FT_Vector* const points = outline.points;
for (int c = 0; c < outline->n_contours; c++)
for (int c = 0; c < outline.n_contours; ++c)
{
const int startPoint = (c == 0) ? 0 : contours [c - 1] + 1;
const int endPoint = contours[c];
for (int p = startPoint; p <= endPoint; p++)
for (int p = startPoint; p <= endPoint; ++p)
{
const float x = scaleX * points[p].x;
const float y = scaleY * points[p].y;
@@ -372,21 +403,19 @@ public:
}
else if (FT_CURVE_TAG (tags[p]) == FT_Curve_Tag_Cubic)
{
if (p >= endPoint)
return false;
const int next1 = p + 1;
const int next2 = (p == (endPoint - 1)) ? startPoint : p + 2;
const int next2 = (p == (endPoint - 1)) ? startPoint : (p + 2);
if (p >= endPoint
|| FT_CURVE_TAG (tags[next1]) != FT_Curve_Tag_Cubic
|| FT_CURVE_TAG (tags[next2]) != FT_Curve_Tag_On)
return false;
const float x2 = scaleX * points [next1].x;
const float y2 = scaleY * points [next1].y;
const float x3 = scaleX * points [next2].x;
const float y3 = scaleY * points [next2].y;
if (FT_CURVE_TAG (tags[next1]) != FT_Curve_Tag_Cubic
|| FT_CURVE_TAG (tags[next2]) != FT_Curve_Tag_On)
return false;
destShape.cubicTo (x, y, x2, y2, x3, y3);
p += 2;
}
@@ -395,15 +424,10 @@ public:
destShape.closeSubPath();
}
dest.addGlyph (character, destShape, face->glyph->metrics.horiAdvance / height);
if ((face->face_flags & FT_FACE_FLAG_KERNING) != 0)
addKerning (face, dest, character, glyphIndex);
return true;
}
void addKerning (FT_Face face, CustomTypeface& dest, const uint32 character, const uint32 glyphIndex)
void addKerning (FT_Face face, const uint32 character, const uint32 glyphIndex)
{
const float height = (float) (face->ascender - face->descender);
@@ -414,177 +438,94 @@ public:
{
FT_Vector kerning;
if (FT_Get_Kerning (face, glyphIndex, rightGlyphIndex, ft_kerning_unscaled, &kerning) == 0)
{
if (kerning.x != 0)
dest.addKerningPair (character, rightCharCode, kerning.x / height);
}
if (FT_Get_Kerning (face, glyphIndex, rightGlyphIndex, ft_kerning_unscaled, &kerning) == 0
&& kerning.x != 0)
addKerningPair (character, rightCharCode, kerning.x / height);
rightCharCode = FT_Get_Next_Char (face, rightCharCode, &rightGlyphIndex);
}
}
// Add a glyph to a font
bool addGlyphToFont (const uint32 character, const String& fontName,
bool bold, bool italic, CustomTypeface& dest)
{
FT_Face face = createFT_Face (fontName, bold, italic);
return face != 0 && addGlyph (face, dest, character);
}
//==============================================================================
void getFamilyNames (StringArray& familyNames) const
{
for (int i = 0; i < faces.size(); i++)
familyNames.add (faces[i]->getFamilyName());
}
void getMonospacedNames (StringArray& monoSpaced) const
{
for (int i = 0; i < faces.size(); i++)
if (faces[i]->getMonospaced())
monoSpaced.add (faces[i]->getFamilyName());
}
void getSerifNames (StringArray& serif) const
{
for (int i = 0; i < faces.size(); i++)
if (faces[i]->getSerif())
serif.add (faces[i]->getFamilyName());
}
void getSansSerifNames (StringArray& sansSerif) const
{
for (int i = 0; i < faces.size(); i++)
if (! faces[i]->getSerif())
sansSerif.add (faces[i]->getFamilyName());
}
juce_DeclareSingleton_SingleThreaded_Minimal (FreeTypeInterface);
private:
//==============================================================================
FT_Library ftLib;
FT_Face lastFace;
String lastFontName;
bool lastBold, lastItalic;
OwnedArray<FreeTypeFontFace> faces;
JUCE_DECLARE_NON_COPYABLE (FreeTypeTypeface);
};
juce_ImplementSingleton_SingleThreaded (FreeTypeInterface)
//==============================================================================
class FreetypeTypeface : public CustomTypeface
{
public:
FreetypeTypeface (const Font& font)
{
FT_Face face = FreeTypeInterface::getInstance()
->createFT_Face (font.getTypefaceName(), font.isBold(), font.isItalic());
if (face == 0)
{
#if JUCE_DEBUG
String msg ("Failed to create typeface: ");
msg << font.getTypefaceName() << " " << (font.isBold() ? 'B' : ' ') << (font.isItalic() ? 'I' : ' ');
DBG (msg);
#endif
}
else
{
setCharacteristics (font.getTypefaceName(),
face->ascender / (float) (face->ascender - face->descender),
font.isBold(), font.isItalic(),
L' ');
}
}
bool loadGlyphIfPossible (juce_wchar character)
{
return FreeTypeInterface::getInstance()
->addGlyphToFont (character, name, isBold, isItalic, *this);
}
};
Typeface::Ptr Typeface::createSystemTypefaceFor (const Font& font)
{
return new FreetypeTypeface (font);
return new FreeTypeTypeface (font);
}
//==============================================================================
StringArray Font::findAllTypefaceNames()
{
StringArray s;
FreeTypeInterface::getInstance()->getFamilyNames (s);
FTTypefaceList::getInstance()->getFamilyNames (s);
s.sort (true);
return s;
}
namespace LinuxFontHelpers
//==============================================================================
struct DefaultFontNames
{
String pickBestFont (const StringArray& names,
const char* const* choicesString)
DefaultFontNames()
: defaultSans (getDefaultSansSerifFontName()),
defaultSerif (getDefaultSerifFontName()),
defaultFixed (getDefaultMonospacedFontName())
{
const StringArray choices (choicesString);
}
int i, j;
String defaultSans, defaultSerif, defaultFixed;
private:
static String pickBestFont (const StringArray& names, const char* const* choicesArray)
{
const StringArray choices (choicesArray);
int j;
for (j = 0; j < choices.size(); ++j)
if (names.contains (choices[j], true))
return choices[j];
for (j = 0; j < choices.size(); ++j)
for (i = 0; i < names.size(); i++)
for (int i = 0; i < names.size(); ++i)
if (names[i].startsWithIgnoreCase (choices[j]))
return names[i];
for (j = 0; j < choices.size(); ++j)
for (i = 0; i < names.size(); i++)
for (int i = 0; i < names.size(); ++i)
if (names[i].containsIgnoreCase (choices[j]))
return names[i];
return names[0];
}
String getDefaultSansSerifFontName()
static String getDefaultSansSerifFontName()
{
StringArray allFonts;
FreeTypeInterface::getInstance()->getSansSerifNames (allFonts);
FTTypefaceList::getInstance()->getSansSerifNames (allFonts);
const char* targets[] = { "Verdana", "Bitstream Vera Sans", "Luxi Sans", "Sans", 0 };
return pickBestFont (allFonts, targets);
}
String getDefaultSerifFontName()
static String getDefaultSerifFontName()
{
StringArray allFonts;
FreeTypeInterface::getInstance()->getSerifNames (allFonts);
FTTypefaceList::getInstance()->getSerifNames (allFonts);
const char* targets[] = { "Bitstream Vera Serif", "Times", "Nimbus Roman", "Serif", 0 };
return pickBestFont (allFonts, targets);
}
String getDefaultMonospacedFontName()
static String getDefaultMonospacedFontName()
{
StringArray allFonts;
FreeTypeInterface::getInstance()->getMonospacedNames (allFonts);
FTTypefaceList::getInstance()->getMonospacedNames (allFonts);
const char* targets[] = { "Bitstream Vera Sans Mono", "Courier", "Sans Mono", "Mono", 0 };
return pickBestFont (allFonts, targets);
}
}
struct DefaultFontNames
{
DefaultFontNames()
: defaultSans (LinuxFontHelpers::getDefaultSansSerifFontName()),
defaultSerif (LinuxFontHelpers::getDefaultSerifFontName()),
defaultFixed (LinuxFontHelpers::getDefaultMonospacedFontName())
{
}
String defaultSans, defaultSerif, defaultFixed;
JUCE_DECLARE_NON_COPYABLE (DefaultFontNames);
};
Typeface::Ptr Font::getDefaultTypefaceForFont (const Font& font)
@@ -593,9 +534,9 @@ Typeface::Ptr Font::getDefaultTypefaceForFont (const Font& font)
String faceName (font.getTypefaceName());
if (faceName == Font::getDefaultSansSerifFontName()) faceName = defaultNames.defaultSans;
else if (faceName == Font::getDefaultSerifFontName()) faceName = defaultNames.defaultSerif;
else if (faceName == Font::getDefaultMonospacedFontName()) faceName = defaultNames.defaultFixed;
if (faceName == getDefaultSansSerifFontName()) faceName = defaultNames.defaultSans;
else if (faceName == getDefaultSerifFontName()) faceName = defaultNames.defaultSerif;
else if (faceName == getDefaultMonospacedFontName()) faceName = defaultNames.defaultFixed;
Font f (font);
f.setTypefaceName (faceName);


+ 7
- 4
modules/juce_gui_basics/filebrowser/juce_FileChooser.cpp View File

@@ -35,9 +35,12 @@ FileChooser::FileChooser (const String& chooserBoxTitle,
startingFile (currentFileOrDirectory),
useNativeDialogBox (useNativeDialogBox_)
{
#if JUCE_LINUX
useNativeDialogBox = false;
#endif
if (useNativeDialogBox)
{
static bool canUseNativeBox = isPlatformDialogAvailable();
if (! canUseNativeBox)
useNativeDialogBox = false;
}
if (! fileFilters.containsNonWhitespaceChars())
filters = "*";
@@ -90,7 +93,7 @@ bool FileChooser::showDialog (const bool selectsDirectories,
#if JUCE_WINDOWS
if (useNativeDialogBox && ! (selectsFiles && selectsDirectories))
#elif JUCE_MAC
#elif JUCE_MAC || JUCE_LINUX
if (useNativeDialogBox && (previewComponent == nullptr))
#else
if (false)


+ 1
- 0
modules/juce_gui_basics/filebrowser/juce_FileChooser.h View File

@@ -184,6 +184,7 @@ private:
const String& filters, bool selectsDirectories, bool selectsFiles,
bool isSave, bool warnAboutOverwritingExistingFiles, bool selectMultipleFiles,
FilePreviewComponent* previewComponent);
static bool isPlatformDialogAvailable();
JUCE_LEAK_DETECTOR (FileChooser);
};


+ 5
- 0
modules/juce_gui_basics/native/juce_android_FileChooser.cpp View File

@@ -38,3 +38,8 @@ void FileChooser::showPlatformDialog (Array<File>& results,
}
bool FileChooser::isPlatformDialogAvailable()
{
return false;
}

+ 3
- 3
modules/juce_gui_basics/native/juce_linux_Clipboard.cpp View File

@@ -34,7 +34,7 @@ namespace ClipboardHelpers
static Atom atom_TARGETS;
//==============================================================================
static void initSelectionAtoms()
void initSelectionAtoms()
{
static bool isInitialised = false;
if (! isInitialised)
@@ -48,7 +48,7 @@ namespace ClipboardHelpers
//==============================================================================
// Read the content of a window property as either a locale-dependent string or an utf8 string
// works only for strings shorter than 1000000 bytes
static String readWindowProperty (Window window, Atom prop, Atom fmt)
String readWindowProperty (Window window, Atom prop, Atom fmt)
{
String returnData;
char* clipData;
@@ -79,7 +79,7 @@ namespace ClipboardHelpers
//==============================================================================
// Send a SelectionRequest to the window owning the selection and waits for its answer (with a timeout) */
static bool requestSelectionContent (String& selectionContent, Atom selection, Atom requestedFormat)
bool requestSelectionContent (String& selectionContent, Atom selection, Atom requestedFormat)
{
Atom property_name = XInternAtom (display, "JUCE_SEL", false);


+ 21
- 41
modules/juce_gui_basics/native/juce_linux_FileChooser.cpp View File

@@ -23,6 +23,16 @@
==============================================================================
*/
bool FileChooser::isPlatformDialogAvailable()
{
ChildProcess child;
const bool ok = child.start ("which zenity")
&& child.readAllProcessOutput().trim().isNotEmpty();
child.waitForProcessToFinish (60 * 1000);
return ok;
}
void FileChooser::showPlatformDialog (Array<File>& results,
const String& title,
const File& file,
@@ -37,58 +47,28 @@ void FileChooser::showPlatformDialog (Array<File>& results,
const String separator (":");
String command ("zenity --file-selection");
if (title.isNotEmpty())
command << " --title=\"" << title << "\"";
if (file != File::nonexistent)
command << " --filename=\"" << file.getFullPathName () << "\"";
if (isDirectory)
command << " --directory";
if (isSave)
command << " --save";
if (selectMultipleFiles)
command << " --multiple --separator=\"" << separator << "\"";
if (title.isNotEmpty()) command << " --title=\"" << title << "\"";
if (file != File::nonexistent) command << " --filename=\"" << file.getFullPathName () << "\"";
if (isDirectory) command << " --directory";
if (isSave) command << " --save";
if (selectMultipleFiles) command << " --multiple --separator=" << separator;
command << " 2>&1";
MemoryOutputStream result;
int status = -1;
FILE* stream = popen (command.toUTF8(), "r");
if (stream != 0)
{
for (;;)
{
char buffer [1024];
const int bytesRead = fread (buffer, 1, sizeof (buffer), stream);
if (bytesRead <= 0)
break;
result.write (buffer, bytesRead);
}
status = pclose (stream);
}
if (status == 0)
ChildProcess child;
if (child.start (command))
{
const String result (child.readAllProcessOutput());
StringArray tokens;
if (selectMultipleFiles)
tokens.addTokens (result.toUTF8(), separator, String::empty);
tokens.addTokens (result, separator, "\"");
else
tokens.add (result.toUTF8());
tokens.add (result);
for (int i = 0; i < tokens.size(); i++)
results.add (File (tokens[i]));
return;
child.waitForProcessToFinish (60 * 1000);
}
//xxx ain't got one!
jassertfalse;
}

+ 10
- 0
modules/juce_gui_basics/native/juce_mac_FileChooser.mm View File

@@ -93,6 +93,11 @@ using namespace juce;
BEGIN_JUCE_NAMESPACE
//==============================================================================
bool FileChooser::isPlatformDialogAvailable()
{
return true;
}
void FileChooser::showPlatformDialog (Array<File>& results,
const String& title,
const File& currentFileOrDirectory,
@@ -172,6 +177,11 @@ void FileChooser::showPlatformDialog (Array<File>& results,
#else
//==============================================================================
bool FileChooser::isPlatformDialogAvailable()
{
return false;
}
void FileChooser::showPlatformDialog (Array<File>& results,
const String& title,
const File& currentFileOrDirectory,


+ 5
- 0
modules/juce_gui_basics/native/juce_win32_FileChooser.cpp View File

@@ -134,6 +134,11 @@ namespace FileChooserHelpers
}
//==============================================================================
bool FileChooser::isPlatformDialogAvailable()
{
return true;
}
void FileChooser::showPlatformDialog (Array<File>& results, const String& title_, const File& currentFileOrDirectory,
const String& filter, bool selectsDirectory, bool /*selectsFiles*/,
bool isSaveDialogue, bool warnAboutOverwritingExistingFiles,


Loading…
Cancel
Save