| @@ -254,7 +254,7 @@ | |||
| actually show it to the user in a list (why??)... Anyway, this macro lets you | |||
| provide a sensible name for that class to make it clear what plugin it refers to. | |||
| Obviously this has to be a valid obj-C class name. | |||
| Just to make things a little more complicated, this name must also be unique to this | |||
| precise version of your software. Otherwise, if the host loads two plugins that use the | |||
| same class name, the obj-C linker will almost certainly connect the wrong modules together | |||
| @@ -553,7 +553,6 @@ | |||
| }; | |||
| C0E91ACA08A95435008D54AB /* Debug */ = { | |||
| isa = XCBuildConfiguration; | |||
| baseConfigurationReference = 846929130A49DB9C00314975 /* juce.xcconfig */; | |||
| buildSettings = { | |||
| GCC_VERSION = 4.0; | |||
| GCC_WARN_ABOUT_RETURN_TYPE = YES; | |||
| @@ -565,7 +564,6 @@ | |||
| }; | |||
| C0E91ACB08A95435008D54AB /* Release */ = { | |||
| isa = XCBuildConfiguration; | |||
| baseConfigurationReference = 846929130A49DB9C00314975 /* juce.xcconfig */; | |||
| buildSettings = { | |||
| GCC_VERSION = 4.0; | |||
| GCC_WARN_ABOUT_RETURN_TYPE = YES; | |||
| @@ -86677,7 +86677,7 @@ void GlyphArrangement::addCurtailedLineOfText (const Font& font, | |||
| { | |||
| // curtail the string if it's too wide.. | |||
| if (useEllipsis && textLen > 3 && glyphs.size() >= 3) | |||
| appendEllipsis (font, xOffset + maxWidthPixels); | |||
| insertEllipsis (font, xOffset + maxWidthPixels, 0, glyphs.size()); | |||
| break; | |||
| } | |||
| @@ -86697,8 +86697,11 @@ void GlyphArrangement::addCurtailedLineOfText (const Font& font, | |||
| } | |||
| } | |||
| void GlyphArrangement::appendEllipsis (const Font& font, const float maxXPixels) throw() | |||
| int GlyphArrangement::insertEllipsis (const Font& font, const float maxXPos, | |||
| const int startIndex, int endIndex) throw() | |||
| { | |||
| int numDeleted = 0; | |||
| if (glyphs.size() > 0) | |||
| { | |||
| Array<int> dotGlyphs; | |||
| @@ -86708,15 +86711,16 @@ void GlyphArrangement::appendEllipsis (const Font& font, const float maxXPixels) | |||
| const float dx = dotXs[1]; | |||
| float xOffset = 0.0f, yOffset = 0.0f; | |||
| for (int dotPos = 3; --dotPos >= 0 && glyphs.size() > 0;) | |||
| while (endIndex > startIndex) | |||
| { | |||
| const PositionedGlyph* pg = glyphs.getUnchecked (glyphs.size() - 1); | |||
| const PositionedGlyph* pg = glyphs.getUnchecked (--endIndex); | |||
| xOffset = pg->x; | |||
| yOffset = pg->y; | |||
| glyphs.removeLast(); | |||
| glyphs.remove (endIndex); | |||
| ++numDeleted; | |||
| if (xOffset + dx * 3 <= maxXPixels) | |||
| if (xOffset + dx * 3 <= maxXPos) | |||
| break; | |||
| } | |||
| @@ -86729,11 +86733,17 @@ void GlyphArrangement::appendEllipsis (const Font& font, const float maxXPixels) | |||
| pg->font = font; | |||
| pg->character = '.'; | |||
| pg->glyph = dotGlyphs.getFirst(); | |||
| glyphs.add (pg); | |||
| glyphs.insert (endIndex++, pg); | |||
| --numDeleted; | |||
| xOffset += dx; | |||
| if (xOffset > maxXPos) | |||
| break; | |||
| } | |||
| } | |||
| return numDeleted; | |||
| } | |||
| void GlyphArrangement::addJustifiedText (const Font& font, | |||
| @@ -86820,8 +86830,8 @@ void GlyphArrangement::addJustifiedText (const Font& font, | |||
| void GlyphArrangement::addFittedText (const Font& f, | |||
| const String& text, | |||
| float x, float y, | |||
| float width, float height, | |||
| const float x, const float y, | |||
| const float width, const float height, | |||
| const Justification& layout, | |||
| int maximumLines, | |||
| const float minimumHorizontalScale) throw() | |||
| @@ -86869,37 +86879,24 @@ void GlyphArrangement::addFittedText (const Font& f, | |||
| 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) | |||
| { | |||
| const float ratio = jmax (minimumHorizontalScale, width / lineWidth); | |||
| stretchRangeOfGlyphs (startIndex, glyphs.size() - startIndex, ratio); | |||
| while (glyphs.size() > 0 && glyphs.getUnchecked (glyphs.size() - 1)->getRight() >= x + width) | |||
| glyphs.removeLast(); | |||
| appendEllipsis (f, x + width); | |||
| justifyGlyphs (startIndex, glyphs.size() - startIndex, | |||
| x, y, width, height, layout); | |||
| fitLineIntoSpace (startIndex, glyphs.size() - startIndex, | |||
| x, y, width, height, f, layout, minimumHorizontalScale); | |||
| } | |||
| else | |||
| { | |||
| Font font (f); | |||
| String txt (text.trim()); | |||
| const int length = txt.length(); | |||
| int numLines = 1; | |||
| const int originalStartIndex = startIndex; | |||
| int numLines = 1; | |||
| if (length <= 12 && ! txt.containsAnyOf (T(" -\t\r\n"))) | |||
| maximumLines = 1; | |||
| @@ -86912,23 +86909,18 @@ void GlyphArrangement::addFittedText (const Font& f, | |||
| const float newFontHeight = height / (float) numLines; | |||
| if (newFontHeight < 8.0f) | |||
| break; | |||
| if (newFontHeight < font.getHeight()) | |||
| { | |||
| font.setHeight (newFontHeight); | |||
| while (glyphs.size() > startIndex) | |||
| glyphs.removeLast(); | |||
| font.setHeight (jmax (8.0f, newFontHeight)); | |||
| removeRangeOfGlyphs (startIndex, -1); | |||
| addLineOfText (font, txt, x, y); | |||
| lineWidth = glyphs.getUnchecked (glyphs.size() - 1)->getRight() | |||
| - glyphs.getUnchecked (startIndex)->getLeft(); | |||
| } | |||
| if (numLines > lineWidth / width) | |||
| if (numLines > lineWidth / width || newFontHeight < 8.0f) | |||
| break; | |||
| } | |||
| @@ -86945,77 +86937,78 @@ void GlyphArrangement::addFittedText (const Font& f, | |||
| lastLineStartIndex = i; | |||
| float lineStartX = glyphs.getUnchecked (startIndex)->getLeft(); | |||
| while (i < glyphs.size()) | |||
| if (line == numLines - 1) | |||
| { | |||
| lineWidth = (glyphs.getUnchecked (i)->getRight() - lineStartX); | |||
| if (lineWidth > widthPerLine) | |||
| widthPerLine = width; | |||
| i = glyphs.size(); | |||
| } | |||
| else | |||
| { | |||
| while (i < glyphs.size()) | |||
| { | |||
| // 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; | |||
| lineWidth = (glyphs.getUnchecked (i)->getRight() - lineStartX); | |||
| while (i < glyphs.size()) | |||
| if (lineWidth > widthPerLine) | |||
| { | |||
| if ((glyphs.getUnchecked (i)->getRight() - lineStartX) * minimumHorizontalScale < width) | |||
| // 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.getUnchecked (i)->isWhitespace() | |||
| || glyphs.getUnchecked (i)->getCharacter() == T('-')) | |||
| if ((glyphs.getUnchecked (i)->getRight() - lineStartX) * minimumHorizontalScale < width) | |||
| { | |||
| ++i; | |||
| break; | |||
| if (glyphs.getUnchecked (i)->isWhitespace() | |||
| || glyphs.getUnchecked (i)->getCharacter() == T('-')) | |||
| { | |||
| ++i; | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| else | |||
| { | |||
| // can't find a suitable break, so try looking backwards.. | |||
| i = searchStartIndex; | |||
| for (int back = 1; back < jmin (5, i - startIndex - 1); ++back) | |||
| else | |||
| { | |||
| if (glyphs.getUnchecked (i - back)->isWhitespace() | |||
| || glyphs.getUnchecked (i - back)->getCharacter() == T('-')) | |||
| // can't find a suitable break, so try looking backwards.. | |||
| i = searchStartIndex; | |||
| for (int back = 1; back < jmin (5, i - startIndex - 1); ++back) | |||
| { | |||
| i -= back - 1; | |||
| break; | |||
| if (glyphs.getUnchecked (i - back)->isWhitespace() | |||
| || glyphs.getUnchecked (i - back)->getCharacter() == T('-')) | |||
| { | |||
| i -= back - 1; | |||
| break; | |||
| } | |||
| } | |||
| break; | |||
| } | |||
| break; | |||
| ++i; | |||
| } | |||
| ++i; | |||
| break; | |||
| } | |||
| break; | |||
| ++i; | |||
| } | |||
| ++i; | |||
| } | |||
| int wsStart = i; | |||
| while (wsStart > 0 && glyphs.getUnchecked (wsStart - 1)->isWhitespace()) | |||
| --wsStart; | |||
| int wsEnd = i; | |||
| while (wsEnd < glyphs.size() && glyphs.getUnchecked (wsEnd)->isWhitespace()) | |||
| ++wsEnd; | |||
| int wsStart = i; | |||
| while (wsStart > 0 && glyphs.getUnchecked (wsStart - 1)->isWhitespace()) | |||
| --wsStart; | |||
| removeRangeOfGlyphs (wsStart, wsEnd - wsStart); | |||
| i = jmax (wsStart, startIndex + 1); | |||
| int wsEnd = i; | |||
| lineWidth = glyphs.getUnchecked (i - 1)->getRight() - lineStartX; | |||
| while (wsEnd < glyphs.size() && glyphs.getUnchecked (wsEnd)->isWhitespace()) | |||
| ++wsEnd; | |||
| if (lineWidth > width) | |||
| { | |||
| stretchRangeOfGlyphs (startIndex, i - startIndex, | |||
| width / lineWidth); | |||
| removeRangeOfGlyphs (wsStart, wsEnd - wsStart); | |||
| i = jmax (wsStart, startIndex + 1); | |||
| } | |||
| justifyGlyphs (startIndex, i - startIndex, | |||
| x, lineY, width, font.getHeight(), | |||
| layout.getOnlyHorizontalFlags() | Justification::verticallyCentred); | |||
| i -= fitLineIntoSpace (startIndex, i - startIndex, | |||
| x, lineY, width, font.getHeight(), font, | |||
| layout.getOnlyHorizontalFlags() | Justification::verticallyCentred, | |||
| minimumHorizontalScale); | |||
| startIndex = i; | |||
| lineY += font.getHeight(); | |||
| @@ -87024,32 +87017,7 @@ void GlyphArrangement::addFittedText (const Font& f, | |||
| break; | |||
| } | |||
| if (startIndex < glyphs.size()) | |||
| { | |||
| removeRangeOfGlyphs (startIndex, -1); | |||
| if (startIndex - originalStartIndex > 4) | |||
| { | |||
| const float lineStartX = glyphs.getUnchecked (lastLineStartIndex)->getLeft(); | |||
| appendEllipsis (font, lineStartX + width); | |||
| lineWidth = glyphs.getUnchecked (startIndex - 1)->getRight() - lineStartX; | |||
| if (lineWidth > width) | |||
| { | |||
| stretchRangeOfGlyphs (lastLineStartIndex, startIndex - lastLineStartIndex, | |||
| width / lineWidth); | |||
| } | |||
| justifyGlyphs (lastLineStartIndex, startIndex - lastLineStartIndex, | |||
| x, lineY - font.getHeight(), width, font.getHeight(), | |||
| layout.getOnlyHorizontalFlags() | Justification::verticallyCentred); | |||
| } | |||
| startIndex = glyphs.size(); | |||
| } | |||
| justifyGlyphs (originalStartIndex, startIndex - originalStartIndex, | |||
| justifyGlyphs (originalStartIndex, glyphs.size() - originalStartIndex, | |||
| x, y, width, height, layout.getFlags() & ~Justification::horizontallyJustified); | |||
| } | |||
| } | |||
| @@ -87070,6 +87038,32 @@ void GlyphArrangement::moveRangeOfGlyphs (int startIndex, int num, | |||
| } | |||
| } | |||
| int GlyphArrangement::fitLineIntoSpace (int start, int numGlyphs, float x, float y, float w, float h, const Font& font, | |||
| const Justification& justification, float minimumHorizontalScale) throw() | |||
| { | |||
| int numDeleted = 0; | |||
| const float lineStartX = glyphs.getUnchecked (start)->getLeft(); | |||
| float lineWidth = glyphs.getUnchecked (start + numGlyphs - 1)->getRight() - lineStartX; | |||
| if (lineWidth > w) | |||
| { | |||
| if (minimumHorizontalScale < 1.0f) | |||
| { | |||
| stretchRangeOfGlyphs (start, numGlyphs, jmax (minimumHorizontalScale, w / lineWidth)); | |||
| lineWidth = glyphs.getUnchecked (start + numGlyphs - 1)->getRight() - lineStartX - 0.5f; | |||
| } | |||
| if (lineWidth > w) | |||
| { | |||
| numDeleted = insertEllipsis (font, lineStartX + w, start, start + numGlyphs); | |||
| numGlyphs -= numDeleted; | |||
| } | |||
| } | |||
| justifyGlyphs (start, numGlyphs, x, y, w, h, justification); | |||
| return numDeleted; | |||
| } | |||
| void GlyphArrangement::stretchRangeOfGlyphs (int startIndex, int num, | |||
| const float horizontalScaleFactor) throw() | |||
| { | |||
| @@ -262822,6 +262816,7 @@ public: | |||
| { | |||
| CGContextRetain (context); | |||
| CGContextSetShouldSmoothFonts (context, true); | |||
| CGContextSetShouldAntialias (context, true); | |||
| CGContextSetBlendMode (context, kCGBlendModeNormal); | |||
| rgbColourSpace = CGColorSpaceCreateDeviceRGB(); | |||
| greyColourSpace = CGColorSpaceCreateDeviceGray(); | |||
| @@ -267250,6 +267245,7 @@ public: | |||
| { | |||
| CGContextRetain (context); | |||
| CGContextSetShouldSmoothFonts (context, true); | |||
| CGContextSetShouldAntialias (context, true); | |||
| CGContextSetBlendMode (context, kCGBlendModeNormal); | |||
| rgbColourSpace = CGColorSpaceCreateDeviceRGB(); | |||
| greyColourSpace = CGColorSpaceCreateDeviceGray(); | |||
| @@ -271718,7 +271714,13 @@ public: | |||
| { | |||
| StringArray files; | |||
| for (unsigned int i = 0; i < [filenames count]; ++i) | |||
| files.add (nsStringToJuce ((NSString*) [filenames objectAtIndex: i])); | |||
| { | |||
| String filename (nsStringToJuce ((NSString*) [filenames objectAtIndex: i])); | |||
| if (filename.containsChar (T(' '))) | |||
| filename = filename.quoted('"'); | |||
| files.add (filename); | |||
| } | |||
| if (files.size() > 0 && JUCEApplication::getInstance() != 0) | |||
| { | |||
| @@ -39734,8 +39734,8 @@ public: | |||
| */ | |||
| void addFittedText (const Font& font, | |||
| const String& text, | |||
| float x, float y, | |||
| float width, float height, | |||
| const float x, const float y, | |||
| const float width, const float height, | |||
| const Justification& layout, | |||
| int maximumLinesToUse, | |||
| const float minimumHorizontalScale = 0.7f) throw(); | |||
| @@ -39839,7 +39839,9 @@ public: | |||
| private: | |||
| OwnedArray <PositionedGlyph> glyphs; | |||
| void appendEllipsis (const Font& font, const float maxXPixels) throw(); | |||
| int insertEllipsis (const Font& font, const float maxXPos, const int startIndex, int endIndex) throw(); | |||
| int fitLineIntoSpace (int start, int numGlyphs, float x, float y, float w, float h, const Font& font, | |||
| const Justification& justification, float minimumHorizontalScale) throw(); | |||
| void spreadOutLine (const int start, const int numGlyphs, const float targetWidth) throw(); | |||
| }; | |||
| @@ -200,7 +200,7 @@ void GlyphArrangement::addCurtailedLineOfText (const Font& font, | |||
| { | |||
| // curtail the string if it's too wide.. | |||
| if (useEllipsis && textLen > 3 && glyphs.size() >= 3) | |||
| appendEllipsis (font, xOffset + maxWidthPixels); | |||
| insertEllipsis (font, xOffset + maxWidthPixels, 0, glyphs.size()); | |||
| break; | |||
| } | |||
| @@ -220,8 +220,11 @@ void GlyphArrangement::addCurtailedLineOfText (const Font& font, | |||
| } | |||
| } | |||
| void GlyphArrangement::appendEllipsis (const Font& font, const float maxXPixels) throw() | |||
| int GlyphArrangement::insertEllipsis (const Font& font, const float maxXPos, | |||
| const int startIndex, int endIndex) throw() | |||
| { | |||
| int numDeleted = 0; | |||
| if (glyphs.size() > 0) | |||
| { | |||
| Array<int> dotGlyphs; | |||
| @@ -231,15 +234,16 @@ void GlyphArrangement::appendEllipsis (const Font& font, const float maxXPixels) | |||
| const float dx = dotXs[1]; | |||
| float xOffset = 0.0f, yOffset = 0.0f; | |||
| for (int dotPos = 3; --dotPos >= 0 && glyphs.size() > 0;) | |||
| while (endIndex > startIndex) | |||
| { | |||
| const PositionedGlyph* pg = glyphs.getUnchecked (glyphs.size() - 1); | |||
| const PositionedGlyph* pg = glyphs.getUnchecked (--endIndex); | |||
| xOffset = pg->x; | |||
| yOffset = pg->y; | |||
| glyphs.removeLast(); | |||
| glyphs.remove (endIndex); | |||
| ++numDeleted; | |||
| if (xOffset + dx * 3 <= maxXPixels) | |||
| if (xOffset + dx * 3 <= maxXPos) | |||
| break; | |||
| } | |||
| @@ -252,11 +256,17 @@ void GlyphArrangement::appendEllipsis (const Font& font, const float maxXPixels) | |||
| pg->font = font; | |||
| pg->character = '.'; | |||
| pg->glyph = dotGlyphs.getFirst(); | |||
| glyphs.add (pg); | |||
| glyphs.insert (endIndex++, pg); | |||
| --numDeleted; | |||
| xOffset += dx; | |||
| if (xOffset > maxXPos) | |||
| break; | |||
| } | |||
| } | |||
| return numDeleted; | |||
| } | |||
| void GlyphArrangement::addJustifiedText (const Font& font, | |||
| @@ -343,8 +353,8 @@ void GlyphArrangement::addJustifiedText (const Font& font, | |||
| void GlyphArrangement::addFittedText (const Font& f, | |||
| const String& text, | |||
| float x, float y, | |||
| float width, float height, | |||
| const float x, const float y, | |||
| const float width, const float height, | |||
| const Justification& layout, | |||
| int maximumLines, | |||
| const float minimumHorizontalScale) throw() | |||
| @@ -392,37 +402,24 @@ void GlyphArrangement::addFittedText (const Font& f, | |||
| 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) | |||
| { | |||
| const float ratio = jmax (minimumHorizontalScale, width / lineWidth); | |||
| stretchRangeOfGlyphs (startIndex, glyphs.size() - startIndex, ratio); | |||
| while (glyphs.size() > 0 && glyphs.getUnchecked (glyphs.size() - 1)->getRight() >= x + width) | |||
| glyphs.removeLast(); | |||
| appendEllipsis (f, x + width); | |||
| justifyGlyphs (startIndex, glyphs.size() - startIndex, | |||
| x, y, width, height, layout); | |||
| fitLineIntoSpace (startIndex, glyphs.size() - startIndex, | |||
| x, y, width, height, f, layout, minimumHorizontalScale); | |||
| } | |||
| else | |||
| { | |||
| Font font (f); | |||
| String txt (text.trim()); | |||
| const int length = txt.length(); | |||
| int numLines = 1; | |||
| const int originalStartIndex = startIndex; | |||
| int numLines = 1; | |||
| if (length <= 12 && ! txt.containsAnyOf (T(" -\t\r\n"))) | |||
| maximumLines = 1; | |||
| @@ -435,23 +432,18 @@ void GlyphArrangement::addFittedText (const Font& f, | |||
| const float newFontHeight = height / (float) numLines; | |||
| if (newFontHeight < 8.0f) | |||
| break; | |||
| if (newFontHeight < font.getHeight()) | |||
| { | |||
| font.setHeight (newFontHeight); | |||
| while (glyphs.size() > startIndex) | |||
| glyphs.removeLast(); | |||
| font.setHeight (jmax (8.0f, newFontHeight)); | |||
| removeRangeOfGlyphs (startIndex, -1); | |||
| addLineOfText (font, txt, x, y); | |||
| lineWidth = glyphs.getUnchecked (glyphs.size() - 1)->getRight() | |||
| - glyphs.getUnchecked (startIndex)->getLeft(); | |||
| } | |||
| if (numLines > lineWidth / width) | |||
| if (numLines > lineWidth / width || newFontHeight < 8.0f) | |||
| break; | |||
| } | |||
| @@ -468,77 +460,78 @@ void GlyphArrangement::addFittedText (const Font& f, | |||
| lastLineStartIndex = i; | |||
| float lineStartX = glyphs.getUnchecked (startIndex)->getLeft(); | |||
| while (i < glyphs.size()) | |||
| if (line == numLines - 1) | |||
| { | |||
| lineWidth = (glyphs.getUnchecked (i)->getRight() - lineStartX); | |||
| if (lineWidth > widthPerLine) | |||
| widthPerLine = width; | |||
| i = glyphs.size(); | |||
| } | |||
| else | |||
| { | |||
| while (i < glyphs.size()) | |||
| { | |||
| // 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; | |||
| lineWidth = (glyphs.getUnchecked (i)->getRight() - lineStartX); | |||
| while (i < glyphs.size()) | |||
| if (lineWidth > widthPerLine) | |||
| { | |||
| if ((glyphs.getUnchecked (i)->getRight() - lineStartX) * minimumHorizontalScale < width) | |||
| // 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.getUnchecked (i)->isWhitespace() | |||
| || glyphs.getUnchecked (i)->getCharacter() == T('-')) | |||
| if ((glyphs.getUnchecked (i)->getRight() - lineStartX) * minimumHorizontalScale < width) | |||
| { | |||
| ++i; | |||
| break; | |||
| if (glyphs.getUnchecked (i)->isWhitespace() | |||
| || glyphs.getUnchecked (i)->getCharacter() == T('-')) | |||
| { | |||
| ++i; | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| else | |||
| { | |||
| // can't find a suitable break, so try looking backwards.. | |||
| i = searchStartIndex; | |||
| for (int back = 1; back < jmin (5, i - startIndex - 1); ++back) | |||
| else | |||
| { | |||
| if (glyphs.getUnchecked (i - back)->isWhitespace() | |||
| || glyphs.getUnchecked (i - back)->getCharacter() == T('-')) | |||
| // can't find a suitable break, so try looking backwards.. | |||
| i = searchStartIndex; | |||
| for (int back = 1; back < jmin (5, i - startIndex - 1); ++back) | |||
| { | |||
| i -= back - 1; | |||
| break; | |||
| if (glyphs.getUnchecked (i - back)->isWhitespace() | |||
| || glyphs.getUnchecked (i - back)->getCharacter() == T('-')) | |||
| { | |||
| i -= back - 1; | |||
| break; | |||
| } | |||
| } | |||
| break; | |||
| } | |||
| break; | |||
| ++i; | |||
| } | |||
| ++i; | |||
| break; | |||
| } | |||
| break; | |||
| ++i; | |||
| } | |||
| ++i; | |||
| } | |||
| int wsStart = i; | |||
| while (wsStart > 0 && glyphs.getUnchecked (wsStart - 1)->isWhitespace()) | |||
| --wsStart; | |||
| int wsStart = i; | |||
| while (wsStart > 0 && glyphs.getUnchecked (wsStart - 1)->isWhitespace()) | |||
| --wsStart; | |||
| int wsEnd = i; | |||
| int wsEnd = i; | |||
| while (wsEnd < glyphs.size() && glyphs.getUnchecked (wsEnd)->isWhitespace()) | |||
| ++wsEnd; | |||
| while (wsEnd < glyphs.size() && glyphs.getUnchecked (wsEnd)->isWhitespace()) | |||
| ++wsEnd; | |||
| removeRangeOfGlyphs (wsStart, wsEnd - wsStart); | |||
| i = jmax (wsStart, startIndex + 1); | |||
| lineWidth = glyphs.getUnchecked (i - 1)->getRight() - lineStartX; | |||
| if (lineWidth > width) | |||
| { | |||
| stretchRangeOfGlyphs (startIndex, i - startIndex, | |||
| width / lineWidth); | |||
| removeRangeOfGlyphs (wsStart, wsEnd - wsStart); | |||
| i = jmax (wsStart, startIndex + 1); | |||
| } | |||
| justifyGlyphs (startIndex, i - startIndex, | |||
| x, lineY, width, font.getHeight(), | |||
| layout.getOnlyHorizontalFlags() | Justification::verticallyCentred); | |||
| i -= fitLineIntoSpace (startIndex, i - startIndex, | |||
| x, lineY, width, font.getHeight(), font, | |||
| layout.getOnlyHorizontalFlags() | Justification::verticallyCentred, | |||
| minimumHorizontalScale); | |||
| startIndex = i; | |||
| lineY += font.getHeight(); | |||
| @@ -547,32 +540,7 @@ void GlyphArrangement::addFittedText (const Font& f, | |||
| break; | |||
| } | |||
| if (startIndex < glyphs.size()) | |||
| { | |||
| removeRangeOfGlyphs (startIndex, -1); | |||
| if (startIndex - originalStartIndex > 4) | |||
| { | |||
| const float lineStartX = glyphs.getUnchecked (lastLineStartIndex)->getLeft(); | |||
| appendEllipsis (font, lineStartX + width); | |||
| lineWidth = glyphs.getUnchecked (startIndex - 1)->getRight() - lineStartX; | |||
| if (lineWidth > width) | |||
| { | |||
| stretchRangeOfGlyphs (lastLineStartIndex, startIndex - lastLineStartIndex, | |||
| width / lineWidth); | |||
| } | |||
| justifyGlyphs (lastLineStartIndex, startIndex - lastLineStartIndex, | |||
| x, lineY - font.getHeight(), width, font.getHeight(), | |||
| layout.getOnlyHorizontalFlags() | Justification::verticallyCentred); | |||
| } | |||
| startIndex = glyphs.size(); | |||
| } | |||
| justifyGlyphs (originalStartIndex, startIndex - originalStartIndex, | |||
| justifyGlyphs (originalStartIndex, glyphs.size() - originalStartIndex, | |||
| x, y, width, height, layout.getFlags() & ~Justification::horizontallyJustified); | |||
| } | |||
| } | |||
| @@ -594,6 +562,32 @@ void GlyphArrangement::moveRangeOfGlyphs (int startIndex, int num, | |||
| } | |||
| } | |||
| int GlyphArrangement::fitLineIntoSpace (int start, int numGlyphs, float x, float y, float w, float h, const Font& font, | |||
| const Justification& justification, float minimumHorizontalScale) throw() | |||
| { | |||
| int numDeleted = 0; | |||
| const float lineStartX = glyphs.getUnchecked (start)->getLeft(); | |||
| float lineWidth = glyphs.getUnchecked (start + numGlyphs - 1)->getRight() - lineStartX; | |||
| if (lineWidth > w) | |||
| { | |||
| if (minimumHorizontalScale < 1.0f) | |||
| { | |||
| stretchRangeOfGlyphs (start, numGlyphs, jmax (minimumHorizontalScale, w / lineWidth)); | |||
| lineWidth = glyphs.getUnchecked (start + numGlyphs - 1)->getRight() - lineStartX - 0.5f; | |||
| } | |||
| if (lineWidth > w) | |||
| { | |||
| numDeleted = insertEllipsis (font, lineStartX + w, start, start + numGlyphs); | |||
| numGlyphs -= numDeleted; | |||
| } | |||
| } | |||
| justifyGlyphs (start, numGlyphs, x, y, w, h, justification); | |||
| return numDeleted; | |||
| } | |||
| void GlyphArrangement::stretchRangeOfGlyphs (int startIndex, int num, | |||
| const float horizontalScaleFactor) throw() | |||
| { | |||
| @@ -201,8 +201,8 @@ public: | |||
| */ | |||
| void addFittedText (const Font& font, | |||
| const String& text, | |||
| float x, float y, | |||
| float width, float height, | |||
| const float x, const float y, | |||
| const float width, const float height, | |||
| const Justification& layout, | |||
| int maximumLinesToUse, | |||
| const float minimumHorizontalScale = 0.7f) throw(); | |||
| @@ -312,7 +312,9 @@ public: | |||
| private: | |||
| OwnedArray <PositionedGlyph> glyphs; | |||
| void appendEllipsis (const Font& font, const float maxXPixels) throw(); | |||
| int insertEllipsis (const Font& font, const float maxXPos, const int startIndex, int endIndex) throw(); | |||
| int fitLineIntoSpace (int start, int numGlyphs, float x, float y, float w, float h, const Font& font, | |||
| const Justification& justification, float minimumHorizontalScale) throw(); | |||
| void spreadOutLine (const int start, const int numGlyphs, const float targetWidth) throw(); | |||
| }; | |||
| @@ -73,6 +73,7 @@ public: | |||
| { | |||
| CGContextRetain (context); | |||
| CGContextSetShouldSmoothFonts (context, true); | |||
| CGContextSetShouldAntialias (context, true); | |||
| CGContextSetBlendMode (context, kCGBlendModeNormal); | |||
| rgbColourSpace = CGColorSpaceCreateDeviceRGB(); | |||
| greyColourSpace = CGColorSpaceCreateDeviceGray(); | |||
| @@ -105,7 +105,13 @@ public: | |||
| { | |||
| StringArray files; | |||
| for (unsigned int i = 0; i < [filenames count]; ++i) | |||
| files.add (nsStringToJuce ((NSString*) [filenames objectAtIndex: i])); | |||
| { | |||
| String filename (nsStringToJuce ((NSString*) [filenames objectAtIndex: i])); | |||
| if (filename.containsChar (T(' '))) | |||
| filename = filename.quoted('"'); | |||
| files.add (filename); | |||
| } | |||
| if (files.size() > 0 && JUCEApplication::getInstance() != 0) | |||
| { | |||