Browse Source

Fix for Win7 full-screen problem. Fix for introjucer absolute paths.

tags/2021-05-28
Julian Storer 14 years ago
parent
commit
b08d3c69fa
7 changed files with 143 additions and 199 deletions
  1. +3
    -1
      extras/Introjucer/Source/Utility/jucer_RelativePath.h
  2. +113
    -181
      juce_amalgamated.cpp
  3. +4
    -5
      juce_amalgamated.h
  4. +1
    -1
      src/gui/components/menus/juce_PopupMenu.cpp
  5. +4
    -5
      src/gui/components/menus/juce_PopupMenu.h
  6. +17
    -5
      src/native/mac/juce_mac_MainMenu.mm
  7. +1
    -1
      src/native/windows/juce_win32_Windowing.cpp

+ 3
- 1
extras/Introjucer/Source/Utility/jucer_RelativePath.h View File

@@ -116,9 +116,11 @@ private:
static bool isAbsolute (const String& path)
{
return File::isAbsolutePath (path)
|| path.startsWithChar ('/') // (needed because File::isAbsolutePath will ignore forward-slashes on win32)
|| path.startsWithChar ('$')
|| path.startsWithChar ('~')
|| (CharacterFunctions::isLetter (path[0]) && path[1] == ':');
|| (CharacterFunctions::isLetter (path[0]) && path[1] == ':')
|| path.startsWithIgnoreCase ("smb:");
}
};


+ 113
- 181
juce_amalgamated.cpp View File

@@ -71803,7 +71803,7 @@ int PopupMenu::getNumItems() const noexcept
int num = 0;

for (int i = items.size(); --i >= 0;)
if (! (items.getUnchecked(i))->isSeparator)
if (! items.getUnchecked(i)->isSeparator)
++num;

return num;
@@ -246395,41 +246395,44 @@ void MessageManager::doPlatformSpecificShutdown()
// compiled on its own).
#if JUCE_INCLUDED_FILE

static int CALLBACK wfontEnum2 (ENUMLOGFONTEXW* lpelfe, NEWTEXTMETRICEXW*, int type, LPARAM lParam)
namespace FontEnumerators
{
if (lpelfe != nullptr && (type & RASTER_FONTTYPE) == 0)
int CALLBACK fontEnum2 (ENUMLOGFONTEXW* lpelfe, NEWTEXTMETRICEXW*, int type, LPARAM lParam)
{
const String fontName (lpelfe->elfLogFont.lfFaceName);
if (lpelfe != nullptr && (type & RASTER_FONTTYPE) == 0)
{
const String fontName (lpelfe->elfLogFont.lfFaceName);

((StringArray*) lParam)->addIfNotAlreadyThere (fontName.removeCharacters ("@"));
}
((StringArray*) lParam)->addIfNotAlreadyThere (fontName.removeCharacters ("@"));
}

return 1;
}
return 1;
}

static int CALLBACK wfontEnum1 (ENUMLOGFONTEXW* lpelfe, NEWTEXTMETRICEXW*, int type, LPARAM lParam)
{
if (lpelfe != nullptr && (type & RASTER_FONTTYPE) == 0)
int CALLBACK fontEnum1 (ENUMLOGFONTEXW* lpelfe, NEWTEXTMETRICEXW*, int type, LPARAM lParam)
{
LOGFONTW lf = { 0 };
lf.lfWeight = FW_DONTCARE;
lf.lfOutPrecision = OUT_OUTLINE_PRECIS;
lf.lfQuality = DEFAULT_QUALITY;
lf.lfCharSet = DEFAULT_CHARSET;
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
lf.lfPitchAndFamily = FF_DONTCARE;
if (lpelfe != nullptr && (type & RASTER_FONTTYPE) == 0)
{
LOGFONTW lf = { 0 };
lf.lfWeight = FW_DONTCARE;
lf.lfOutPrecision = OUT_OUTLINE_PRECIS;
lf.lfQuality = DEFAULT_QUALITY;
lf.lfCharSet = DEFAULT_CHARSET;
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
lf.lfPitchAndFamily = FF_DONTCARE;

const String fontName (lpelfe->elfLogFont.lfFaceName);
fontName.copyToUTF16 (lf.lfFaceName, sizeof (lf.lfFaceName));
const String fontName (lpelfe->elfLogFont.lfFaceName);
fontName.copyToUTF16 (lf.lfFaceName, sizeof (lf.lfFaceName));

HDC dc = CreateCompatibleDC (0);
EnumFontFamiliesEx (dc, &lf,
(FONTENUMPROCW) &wfontEnum2,
lParam, 0);
DeleteDC (dc);
}
HDC dc = CreateCompatibleDC (0);
EnumFontFamiliesEx (dc, &lf,
(FONTENUMPROCW) &fontEnum2,
lParam, 0);
DeleteDC (dc);
}

return 1;
return 1;
}
}

StringArray Font::findAllTypefaceNames()
@@ -246447,7 +246450,7 @@ StringArray Font::findAllTypefaceNames()
lf.lfPitchAndFamily = FF_DONTCARE;

EnumFontFamiliesEx (dc, &lf,
(FONTENUMPROCW) &wfontEnum1,
(FONTENUMPROCW) &FontEnumerators::fontEnum1,
(LPARAM) &results, 0);
}

@@ -246477,123 +246480,21 @@ void Font::getPlatformDefaultFontNames (String& defaultSans, String& defaultSeri
}
}

class FontDCHolder : private DeletedAtShutdown
{
public:

FontDCHolder()
: fontH (0), previousFontH (0), dc (0), numKPs (0), size (0),
bold (false), italic (false)
{
}

~FontDCHolder()
{
deleteDCAndFont();
clearSingletonInstance();
}

juce_DeclareSingleton_SingleThreaded_Minimal (FontDCHolder);

HDC loadFont (const String& fontName_, const bool bold_, const bool italic_, const int size_)
{
if (fontName != fontName_ || bold != bold_ || italic != italic_ || size != size_)
{
fontName = fontName_;
bold = bold_;
italic = italic_;
size = size_;

deleteDCAndFont();

dc = CreateCompatibleDC (0);
SetMapperFlags (dc, 0);
SetMapMode (dc, MM_TEXT);

LOGFONTW lf = { 0 };
lf.lfCharSet = DEFAULT_CHARSET;
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
lf.lfOutPrecision = OUT_OUTLINE_PRECIS;
lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
lf.lfQuality = PROOF_QUALITY;
lf.lfItalic = (BYTE) (italic ? TRUE : FALSE);
lf.lfWeight = bold ? FW_BOLD : FW_NORMAL;
lf.lfHeight = size > 0 ? size : -256;
fontName.copyToUTF16 (lf.lfFaceName, sizeof (lf.lfFaceName));

HFONT standardSizedFont = CreateFontIndirect (&lf);

if (standardSizedFont != 0)
{
if ((previousFontH = SelectObject (dc, standardSizedFont)) != 0)
{
fontH = standardSizedFont;

if (size == 0)
{
OUTLINETEXTMETRIC otm;
if (GetOutlineTextMetrics (dc, sizeof (otm), &otm) != 0)
{
lf.lfHeight = -(int) otm.otmEMSquare;
fontH = CreateFontIndirect (&lf);

SelectObject (dc, fontH);
DeleteObject (standardSizedFont);
}
}
}
}
}

return dc;
}

private:

HFONT fontH;
HGDIOBJ previousFontH;
HDC dc;
String fontName;
HeapBlock <KERNINGPAIR> kps;
int numKPs, size;
bool bold, italic;

void deleteDCAndFont()
{
if (dc != 0)
{
SelectObject (dc, previousFontH); // Replacing the previous font before deleting the DC avoids a warning in BoundsChecker
DeleteDC (dc);
dc = 0;
}

if (fontH != 0)
{
DeleteObject (fontH);
fontH = 0;
}

kps.free();
}

JUCE_DECLARE_NON_COPYABLE (FontDCHolder);
};

juce_ImplementSingleton_SingleThreaded (FontDCHolder);

class WindowsTypeface : public Typeface
{
public:
WindowsTypeface (const Font& font)
: Typeface (font.getTypefaceName()),
fontH (0),
previousFontH (0),
dc (CreateCompatibleDC (0)),
ascent (1.0f),
defaultGlyph (-1),
bold (font.isBold()),
italic (font.isItalic())
{
HDC dc = getDC();
loadFont();

TEXTMETRIC tm;
if (GetTextMetrics (dc, &tm))
{
ascent = tm.tmAscent / (float) tm.tmHeight;
@@ -246602,12 +246503,20 @@ public:
}
}

~WindowsTypeface()
{
SelectObject (dc, previousFontH); // Replacing the previous font before deleting the DC avoids a warning in BoundsChecker
DeleteDC (dc);

if (fontH != 0)
DeleteObject (fontH);
}

float getAscent() const { return ascent; }
float getDescent() const { return 1.0f - ascent; }

float getStringWidth (const String& text)
{
HDC dc = getDC();
const CharPointer_UTF16 utf16 (text.toUTF16());
const int numChars = utf16.length();
HeapBlock<int16> results (numChars + 1);
@@ -246626,7 +246535,6 @@ public:

void getGlyphPositions (const String& text, Array <int>& resultGlyphs, Array <float>& xOffsets)
{
HDC dc = getDC();
const CharPointer_UTF16 utf16 (text.toUTF16());
const int numChars = utf16.length();
HeapBlock<int16> results (numChars + 1);
@@ -246652,12 +246560,6 @@ public:

bool getOutlineForGlyph (int glyphNumber, Path& glyphPath)
{
HDC dc = getDC();

TEXTMETRIC tm;
if (! GetTextMetrics (dc, &tm))
return false;

if (glyphNumber < 0)
glyphNumber = defaultGlyph;

@@ -246673,16 +246575,13 @@ public:

const TTPOLYGONHEADER* pheader = reinterpret_cast<TTPOLYGONHEADER*> (data.getData());

const float height = (float) tm.tmHeight;
const float scaleX = 1.0f / height;
const float scaleY = -1.0f / height;
const float scaleX = 1.0f / tm.tmHeight;
const float scaleY = -scaleX;

while ((char*) pheader < data + bufSize)
{
float x = scaleX * pheader->pfxStart.x.value;
float y = scaleY * pheader->pfxStart.y.value;

glyphPath.startNewSubPath (x, y);
glyphPath.startNewSubPath (scaleX * pheader->pfxStart.x.value,
scaleY * pheader->pfxStart.y.value);

const TTPOLYCURVE* curve = (const TTPOLYCURVE*) ((const char*) pheader + sizeof (TTPOLYGONHEADER));
const char* const curveEnd = ((const char*) pheader) + pheader->cb;
@@ -246692,12 +246591,8 @@ public:
if (curve->wType == TT_PRIM_LINE)
{
for (int i = 0; i < curve->cpfx; ++i)
{
x = scaleX * curve->apfx[i].x.value;
y = scaleY * curve->apfx[i].y.value;

glyphPath.lineTo (x, y);
}
glyphPath.lineTo (scaleX * curve->apfx[i].x.value,
scaleY * curve->apfx[i].y.value);
}
else if (curve->wType == TT_PRIM_QSPLINE)
{
@@ -246705,23 +246600,16 @@ public:
{
const float x2 = scaleX * curve->apfx[i].x.value;
const float y2 = scaleY * curve->apfx[i].y.value;
float x3, y3;
float x3 = scaleX * curve->apfx[i + 1].x.value;
float y3 = scaleY * curve->apfx[i + 1].y.value;

if (i < curve->cpfx - 2)
{
x3 = 0.5f * (x2 + scaleX * curve->apfx[i + 1].x.value);
y3 = 0.5f * (y2 + scaleY * curve->apfx[i + 1].y.value);
}
else
{
x3 = scaleX * curve->apfx[i + 1].x.value;
y3 = scaleY * curve->apfx[i + 1].y.value;
x3 = 0.5f * (x2 + x3);
y3 = 0.5f * (y2 + y3);
}

glyphPath.quadraticTo (x2, y2, x3, y3);

x = x3;
y = y3;
}
}

@@ -246739,6 +246627,10 @@ public:

private:
static const MAT2 identityMatrix;
HFONT fontH;
HGDIOBJ previousFontH;
HDC dc;
TEXTMETRIC tm;
float ascent;
int defaultGlyph;
bool bold, italic;
@@ -246762,6 +246654,43 @@ private:

SortedSet<KerningPair> kerningPairs;

void loadFont()
{
SetMapperFlags (dc, 0);
SetMapMode (dc, MM_TEXT);

LOGFONTW lf = { 0 };
lf.lfCharSet = DEFAULT_CHARSET;
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
lf.lfOutPrecision = OUT_OUTLINE_PRECIS;
lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
lf.lfQuality = PROOF_QUALITY;
lf.lfItalic = (BYTE) (italic ? TRUE : FALSE);
lf.lfWeight = bold ? FW_BOLD : FW_NORMAL;
lf.lfHeight = -256;
name.copyToUTF16 (lf.lfFaceName, sizeof (lf.lfFaceName));

HFONT standardSizedFont = CreateFontIndirect (&lf);

if (standardSizedFont != 0)
{
if ((previousFontH = SelectObject (dc, standardSizedFont)) != 0)
{
fontH = standardSizedFont;

OUTLINETEXTMETRIC otm;
if (GetOutlineTextMetrics (dc, sizeof (otm), &otm) != 0)
{
lf.lfHeight = -(int) otm.otmEMSquare;
fontH = CreateFontIndirect (&lf);

SelectObject (dc, fontH);
DeleteObject (standardSizedFont);
}
}
}
}

void createKerningPairs (HDC dc, const float height)
{
HeapBlock<KERNINGPAIR> rawKerning;
@@ -246821,10 +246750,6 @@ private:

if (index < 0)
{
TEXTMETRIC tm;
if (! GetTextMetrics (dc, &tm))
return 0;

kp.glyph2 = -1;
kp.kerning = getGlyphWidth (dc, kp.glyph1) / (float) tm.tmHeight;
kerningPairs.add (kp);
@@ -246835,11 +246760,6 @@ private:
return kerningPairs.getReference (index).kerning;
}

HDC getDC() const
{
return FontDCHolder::getInstance()->loadFont (name, bold, italic, 0);
}

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WindowsTypeface);
};

@@ -248357,7 +248277,7 @@ public:
{
setMinimised (false);

if (fullScreen != shouldBeFullScreen)
if (isFullScreen() != shouldBeFullScreen)
{
fullScreen = shouldBeFullScreen;
const WeakReference<Component> deletionChecker (component);
@@ -281766,10 +281686,7 @@ public:
[menu setAutoenablesItems: false];
[menu update];
[parentItem setTag: tag];

if (! [[parentItem submenu] equals: menu]) // NB this comparison is needed to avoid a strange
[parentItem setSubmenu: menu]; // crash deep inside Apple code when no windows are focused..

[parentItem setSubmenu: menu];
[menu release];
}

@@ -281817,7 +281734,7 @@ public:
}

if (Time::getMillisecondCounter() > lastUpdateTime + 500)
menuBarItemsChanged (nullptr);
(new AsyncMenuUpdater())->post();
}

void invoke (const int commandId, ApplicationCommandManager* const commandManager, const int topLevelIndex) const
@@ -282003,6 +281920,21 @@ private:
if (mods.isCommandDown()) m |= NSCommandKeyMask;
return m;
}

class AsyncMenuUpdater : public CallbackMessage
{
public:
AsyncMenuUpdater() {}

void messageCallback()
{
if (JuceMainMenuHandler::instance != nullptr)
JuceMainMenuHandler::instance->menuBarItemsChanged (nullptr);
}

private:
JUCE_DECLARE_NON_COPYABLE (AsyncMenuUpdater);
};
};

JuceMainMenuHandler* JuceMainMenuHandler::instance = nullptr;


+ 4
- 5
juce_amalgamated.h View File

@@ -43845,8 +43845,7 @@ public:
zero, because that's used to indicate that the user didn't
select anything.
@param itemText the text to show.
@param isActive if false, the item will be shown 'greyed-out' and can't be
picked
@param isEnabled if false, the item will be shown 'greyed-out' and can't be picked
@param isTicked if true, the item will be shown with a tick next to it
@param iconToUse if this is non-zero, it should be an image that will be
displayed to the left of the item. This method will take its
@@ -43857,7 +43856,7 @@ public:
*/
void addItem (int itemResultId,
const String& itemText,
bool isActive = true,
bool isEnabled = true,
bool isTicked = false,
const Image& iconToUse = Image::null);

@@ -43882,7 +43881,7 @@ public:
void addColouredItem (int itemResultId,
const String& itemText,
const Colour& itemTextColour,
bool isActive = true,
bool isEnabled = true,
bool isTicked = false,
const Image& iconToUse = Image::null);

@@ -43912,7 +43911,7 @@ public:
*/
void addSubMenu (const String& subMenuName,
const PopupMenu& subMenu,
bool isActive = true,
bool isEnabled = true,
const Image& iconToUse = Image::null,
bool isTicked = false);



+ 1
- 1
src/gui/components/menus/juce_PopupMenu.cpp View File

@@ -1608,7 +1608,7 @@ int PopupMenu::getNumItems() const noexcept
int num = 0;
for (int i = items.size(); --i >= 0;)
if (! (items.getUnchecked(i))->isSeparator)
if (! items.getUnchecked(i)->isSeparator)
++num;
return num;


+ 4
- 5
src/gui/components/menus/juce_PopupMenu.h View File

@@ -105,8 +105,7 @@ public:
zero, because that's used to indicate that the user didn't
select anything.
@param itemText the text to show.
@param isActive if false, the item will be shown 'greyed-out' and can't be
picked
@param isEnabled if false, the item will be shown 'greyed-out' and can't be picked
@param isTicked if true, the item will be shown with a tick next to it
@param iconToUse if this is non-zero, it should be an image that will be
displayed to the left of the item. This method will take its
@@ -117,7 +116,7 @@ public:
*/
void addItem (int itemResultId,
const String& itemText,
bool isActive = true,
bool isEnabled = true,
bool isTicked = false,
const Image& iconToUse = Image::null);
@@ -143,7 +142,7 @@ public:
void addColouredItem (int itemResultId,
const String& itemText,
const Colour& itemTextColour,
bool isActive = true,
bool isEnabled = true,
bool isTicked = false,
const Image& iconToUse = Image::null);
@@ -173,7 +172,7 @@ public:
*/
void addSubMenu (const String& subMenuName,
const PopupMenu& subMenu,
bool isActive = true,
bool isEnabled = true,
const Image& iconToUse = Image::null,
bool isTicked = false);


+ 17
- 5
src/native/mac/juce_mac_MainMenu.mm View File

@@ -121,10 +121,7 @@ public:
[menu setAutoenablesItems: false];
[menu update];
[parentItem setTag: tag];
if (! [[parentItem submenu] equals: menu]) // NB this comparison is needed to avoid a strange
[parentItem setSubmenu: menu]; // crash deep inside Apple code when no windows are focused..
[parentItem setSubmenu: menu];
[menu release];
}
@@ -172,7 +169,7 @@ public:
}
if (Time::getMillisecondCounter() > lastUpdateTime + 500)
menuBarItemsChanged (nullptr);
(new AsyncMenuUpdater())->post();
}
void invoke (const int commandId, ApplicationCommandManager* const commandManager, const int topLevelIndex) const
@@ -358,6 +355,21 @@ private:
if (mods.isCommandDown()) m |= NSCommandKeyMask;
return m;
}
class AsyncMenuUpdater : public CallbackMessage
{
public:
AsyncMenuUpdater() {}
void messageCallback()
{
if (JuceMainMenuHandler::instance != nullptr)
JuceMainMenuHandler::instance->menuBarItemsChanged (nullptr);
}
private:
JUCE_DECLARE_NON_COPYABLE (AsyncMenuUpdater);
};
};
JuceMainMenuHandler* JuceMainMenuHandler::instance = nullptr;


+ 1
- 1
src/native/windows/juce_win32_Windowing.cpp View File

@@ -648,7 +648,7 @@ public:
{
setMinimised (false);
if (fullScreen != shouldBeFullScreen)
if (isFullScreen() != shouldBeFullScreen)
{
fullScreen = shouldBeFullScreen;
const WeakReference<Component> deletionChecker (component);


Loading…
Cancel
Save