| @@ -22,31 +22,156 @@ | |||
| ============================================================================== | |||
| */ | |||
| AttributedString::Attribute::Attribute (Range<int> range_, Colour colour_) | |||
| : range (range_), colour (new Colour (colour_)) | |||
| namespace | |||
| { | |||
| int getLength (const Array<AttributedString::Attribute>& atts) noexcept | |||
| { | |||
| return atts.size() != 0 ? atts.getReference (atts.size() - 1).range.getEnd() : 0; | |||
| } | |||
| void splitAttributeRanges (Array<AttributedString::Attribute>& atts, int position) | |||
| { | |||
| for (int i = atts.size(); --i >= 0;) | |||
| { | |||
| const AttributedString::Attribute& att = atts.getReference (i); | |||
| const int offset = position - att.range.getStart(); | |||
| if (offset >= 0) | |||
| { | |||
| if (offset > 0 && position < att.range.getEnd()) | |||
| { | |||
| atts.insert (i + 1, att); | |||
| atts.getReference (i).range.setEnd (position); | |||
| atts.getReference (i + 1).range.setStart (position); | |||
| } | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| Range<int> splitAttributeRanges (Array<AttributedString::Attribute>& atts, Range<int> newRange) | |||
| { | |||
| newRange = newRange.getIntersectionWith (Range<int> (0, getLength (atts))); | |||
| if (! newRange.isEmpty()) | |||
| { | |||
| splitAttributeRanges (atts, newRange.getStart()); | |||
| splitAttributeRanges (atts, newRange.getEnd()); | |||
| } | |||
| return newRange; | |||
| } | |||
| void mergeAdjacentRanges (Array<AttributedString::Attribute>& atts) | |||
| { | |||
| for (int i = atts.size() - 1; --i >= 0;) | |||
| { | |||
| AttributedString::Attribute& a1 = atts.getReference (i); | |||
| AttributedString::Attribute& a2 = atts.getReference (i + 1); | |||
| if (a1.colour == a2.colour && a1.font == a2.font) | |||
| { | |||
| a1.range.setEnd (a2.range.getEnd()); | |||
| atts.remove (i + 1); | |||
| if (i < atts.size() - 1) | |||
| ++i; | |||
| } | |||
| } | |||
| } | |||
| void appendRange (Array<AttributedString::Attribute>& atts, | |||
| int length, const Font* f, const Colour* c) | |||
| { | |||
| if (atts.size() == 0) | |||
| { | |||
| atts.add (AttributedString::Attribute (Range<int> (0, length), | |||
| f != nullptr ? *f : Font(), | |||
| c != nullptr ? *c : Colour (0xff000000))); | |||
| } | |||
| else | |||
| { | |||
| const int start = getLength (atts); | |||
| atts.add (AttributedString::Attribute (Range<int> (start, start + length), | |||
| f != nullptr ? *f : atts.getReference (atts.size() - 1).font, | |||
| c != nullptr ? *c : atts.getReference (atts.size() - 1).colour)); | |||
| mergeAdjacentRanges (atts); | |||
| } | |||
| } | |||
| void applyFontAndColour (Array<AttributedString::Attribute>& atts, | |||
| Range<int> range, const Font* f, const Colour* c) | |||
| { | |||
| range = splitAttributeRanges (atts, range); | |||
| for (int i = 0; i < atts.size(); ++i) | |||
| { | |||
| AttributedString::Attribute& att = atts.getReference (i); | |||
| if (range.getStart() < att.range.getEnd()) | |||
| { | |||
| if (range.getEnd() <= att.range.getStart()) | |||
| break; | |||
| if (c != nullptr) att.colour = *c; | |||
| if (f != nullptr) att.font = *f; | |||
| } | |||
| } | |||
| mergeAdjacentRanges (atts); | |||
| } | |||
| void truncate (Array<AttributedString::Attribute>& atts, int newLength) | |||
| { | |||
| splitAttributeRanges (atts, newLength); | |||
| for (int i = atts.size(); --i >= 0;) | |||
| if (atts.getReference (i).range.getStart() >= newLength) | |||
| atts.remove (i); | |||
| } | |||
| } | |||
| AttributedString::Attribute::Attribute (Range<int> range_, const Font& font_) | |||
| : range (range_), font (new Font (font_)) | |||
| //============================================================================== | |||
| AttributedString::Attribute::Attribute() noexcept : colour (0xff000000) {} | |||
| AttributedString::Attribute::~Attribute() noexcept {} | |||
| #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS | |||
| AttributedString::Attribute::Attribute (Attribute&& other) noexcept | |||
| : range (other.range), | |||
| font (static_cast<Font&&> (other.font)), | |||
| colour (other.colour) | |||
| { | |||
| } | |||
| AttributedString::Attribute& AttributedString::Attribute::operator= (Attribute&& other) noexcept | |||
| { | |||
| range = other.range; | |||
| font = static_cast<Font&&> (other.font); | |||
| colour = other.colour; | |||
| return *this; | |||
| } | |||
| #endif | |||
| AttributedString::Attribute::Attribute (const Attribute& other) | |||
| AttributedString::Attribute::Attribute (const Attribute& other) noexcept | |||
| : range (other.range), | |||
| font (other.font.createCopy()), | |||
| colour (other.colour.createCopy()) | |||
| font (other.font), | |||
| colour (other.colour) | |||
| { | |||
| } | |||
| AttributedString::Attribute::Attribute (const Attribute& other, const int offset) | |||
| : range (other.range + offset), | |||
| font (other.font.createCopy()), | |||
| colour (other.colour.createCopy()) | |||
| AttributedString::Attribute& AttributedString::Attribute::operator= (const Attribute& other) noexcept | |||
| { | |||
| range = other.range; | |||
| font = other.font; | |||
| colour = other.colour; | |||
| return *this; | |||
| } | |||
| AttributedString::Attribute::~Attribute() {} | |||
| AttributedString::Attribute::Attribute (Range<int> r, const Font& f, Colour c) noexcept | |||
| : range (r), font (f), colour (c) | |||
| { | |||
| } | |||
| //============================================================================== | |||
| AttributedString::AttributedString() | |||
| @@ -58,12 +183,12 @@ AttributedString::AttributedString() | |||
| } | |||
| AttributedString::AttributedString (const String& newString) | |||
| : text (newString), | |||
| lineSpacing (0.0f), | |||
| : lineSpacing (0.0f), | |||
| justification (Justification::left), | |||
| wordWrap (AttributedString::byWord), | |||
| readingDirection (AttributedString::natural) | |||
| { | |||
| setText (newString); | |||
| } | |||
| AttributedString::AttributedString (const AttributedString& other) | |||
| @@ -71,9 +196,9 @@ AttributedString::AttributedString (const AttributedString& other) | |||
| lineSpacing (other.lineSpacing), | |||
| justification (other.justification), | |||
| wordWrap (other.wordWrap), | |||
| readingDirection (other.readingDirection) | |||
| readingDirection (other.readingDirection), | |||
| attributes (other.attributes) | |||
| { | |||
| attributes.addCopiesOf (other.attributes); | |||
| } | |||
| AttributedString& AttributedString::operator= (const AttributedString& other) | |||
| @@ -85,8 +210,7 @@ AttributedString& AttributedString::operator= (const AttributedString& other) | |||
| justification = other.justification; | |||
| wordWrap = other.wordWrap; | |||
| readingDirection = other.readingDirection; | |||
| attributes.clear(); | |||
| attributes.addCopiesOf (other.attributes); | |||
| attributes = other.attributes; | |||
| } | |||
| return *this; | |||
| @@ -99,7 +223,7 @@ AttributedString::AttributedString (AttributedString&& other) noexcept | |||
| justification (other.justification), | |||
| wordWrap (other.wordWrap), | |||
| readingDirection (other.readingDirection), | |||
| attributes (static_cast<OwnedArray<Attribute>&&> (other.attributes)) | |||
| attributes (static_cast<Array<Attribute>&&> (other.attributes)) | |||
| { | |||
| } | |||
| @@ -110,58 +234,61 @@ AttributedString& AttributedString::operator= (AttributedString&& other) noexcep | |||
| justification = other.justification; | |||
| wordWrap = other.wordWrap; | |||
| readingDirection = other.readingDirection; | |||
| attributes = static_cast<OwnedArray<Attribute>&&> (other.attributes); | |||
| attributes = static_cast<Array<Attribute>&&> (other.attributes); | |||
| return *this; | |||
| } | |||
| #endif | |||
| AttributedString::~AttributedString() {} | |||
| AttributedString::~AttributedString() noexcept {} | |||
| void AttributedString::setText (const String& other) | |||
| void AttributedString::setText (const String& newText) | |||
| { | |||
| text = other; | |||
| const int newLength = newText.length(); | |||
| const int oldLength = getLength (attributes); | |||
| if (newLength > oldLength) | |||
| appendRange (attributes, newLength - oldLength, nullptr, nullptr); | |||
| else if (newLength < oldLength) | |||
| truncate (attributes, newLength); | |||
| text = newText; | |||
| } | |||
| void AttributedString::append (const String& textToAppend) | |||
| { | |||
| text += textToAppend; | |||
| appendRange (attributes, textToAppend.length(), nullptr, nullptr); | |||
| } | |||
| void AttributedString::append (const String& textToAppend, const Font& font) | |||
| { | |||
| const int oldLength = text.length(); | |||
| const int newLength = textToAppend.length(); | |||
| text += textToAppend; | |||
| setFont (Range<int> (oldLength, oldLength + newLength), font); | |||
| appendRange (attributes, textToAppend.length(), &font, nullptr); | |||
| } | |||
| void AttributedString::append (const String& textToAppend, Colour colour) | |||
| { | |||
| const int oldLength = text.length(); | |||
| const int newLength = textToAppend.length(); | |||
| text += textToAppend; | |||
| setColour (Range<int> (oldLength, oldLength + newLength), colour); | |||
| appendRange (attributes, textToAppend.length(), nullptr, &colour); | |||
| } | |||
| void AttributedString::append (const String& textToAppend, const Font& font, Colour colour) | |||
| { | |||
| const int oldLength = text.length(); | |||
| const int newLength = textToAppend.length(); | |||
| text += textToAppend; | |||
| setFont (Range<int> (oldLength, oldLength + newLength), font); | |||
| setColour (Range<int> (oldLength, oldLength + newLength), colour); | |||
| appendRange (attributes, textToAppend.length(), &font, &colour); | |||
| } | |||
| void AttributedString::append (const AttributedString& other) | |||
| { | |||
| const int originalLength = text.length(); | |||
| const int originalLength = getLength (attributes); | |||
| const int originalNumAtts = attributes.size(); | |||
| text += other.text; | |||
| attributes.addArray (other.attributes); | |||
| for (int i = 0; i < other.attributes.size(); ++i) | |||
| attributes.add (new Attribute (*other.attributes.getUnchecked(i), originalLength)); | |||
| for (int i = originalNumAtts; i < attributes.size(); ++i) | |||
| attributes.getReference (i).range += originalLength; | |||
| mergeAdjacentRanges (attributes); | |||
| } | |||
| void AttributedString::clear() | |||
| @@ -192,36 +319,30 @@ void AttributedString::setLineSpacing (const float newLineSpacing) noexcept | |||
| void AttributedString::setColour (Range<int> range, Colour colour) | |||
| { | |||
| attributes.add (new Attribute (range, colour)); | |||
| applyFontAndColour (attributes, range, nullptr, &colour); | |||
| } | |||
| void AttributedString::setColour (Colour colour) | |||
| void AttributedString::setFont (Range<int> range, const Font& font) | |||
| { | |||
| for (int i = attributes.size(); --i >= 0;) | |||
| if (attributes.getUnchecked(i)->getColour() != nullptr) | |||
| attributes.remove (i); | |||
| setColour (Range<int> (0, text.length()), colour); | |||
| applyFontAndColour (attributes, range, &font, nullptr); | |||
| } | |||
| void AttributedString::setFont (Range<int> range, const Font& font) | |||
| void AttributedString::setColour (Colour colour) | |||
| { | |||
| attributes.add (new Attribute (range, font)); | |||
| setColour (Range<int> (0, getLength (attributes)), colour); | |||
| } | |||
| void AttributedString::setFont (const Font& font) | |||
| { | |||
| for (int i = attributes.size(); --i >= 0;) | |||
| if (attributes.getUnchecked(i)->getFont() != nullptr) | |||
| attributes.remove (i); | |||
| setFont (Range<int> (0, text.length()), font); | |||
| setFont (Range<int> (0, getLength (attributes)), font); | |||
| } | |||
| void AttributedString::draw (Graphics& g, const Rectangle<float>& area) const | |||
| { | |||
| if (text.isNotEmpty() && g.clipRegionIntersects (area.getSmallestIntegerContainer())) | |||
| { | |||
| jassert (text.length() == getLength (attributes)); | |||
| if (! g.getInternalContext().drawTextLayout (*this, area)) | |||
| { | |||
| TextLayout layout; | |||
| @@ -53,7 +53,7 @@ public: | |||
| #endif | |||
| /** Destructor. */ | |||
| ~AttributedString(); | |||
| ~AttributedString() noexcept; | |||
| //============================================================================== | |||
| /** Returns the complete text of this attributed string. */ | |||
| @@ -150,36 +150,28 @@ public: | |||
| class JUCE_API Attribute | |||
| { | |||
| public: | |||
| /** Creates an attribute that changes the colour for a range of characters. | |||
| @see AttributedString::setColour() | |||
| */ | |||
| Attribute (Range<int> range, Colour colour); | |||
| /** Creates an attribute that changes the font for a range of characters. | |||
| @see AttributedString::setFont() | |||
| */ | |||
| Attribute (Range<int> range, const Font& font); | |||
| Attribute (const Attribute&); | |||
| ~Attribute(); | |||
| /** If this attribute specifies a font, this returns it; otherwise it returns nullptr. */ | |||
| const Font* getFont() const noexcept { return font; } | |||
| /** If this attribute specifies a colour, this returns it; otherwise it returns nullptr. */ | |||
| const Colour* getColour() const noexcept { return colour; } | |||
| Attribute() noexcept; | |||
| ~Attribute() noexcept; | |||
| Attribute (const Attribute&) noexcept; | |||
| Attribute& operator= (const Attribute&) noexcept; | |||
| #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS | |||
| Attribute (Attribute&&) noexcept; | |||
| Attribute& operator= (Attribute&&) noexcept; | |||
| #endif | |||
| /** Creates an attribute that specifies the font and colour for a range of characters. */ | |||
| Attribute (Range<int> range, const Font& font, Colour colour) noexcept; | |||
| /** The range of characters to which this attribute will be applied. */ | |||
| const Range<int> range; | |||
| Range<int> range; | |||
| private: | |||
| ScopedPointer<Font> font; | |||
| ScopedPointer<Colour> colour; | |||
| /** The font for this range of characters. */ | |||
| Font font; | |||
| friend class AttributedString; | |||
| Attribute (const Attribute&, int); | |||
| Attribute& operator= (const Attribute&); | |||
| /** The colour for this range of characters. */ | |||
| Colour colour; | |||
| private: | |||
| JUCE_LEAK_DETECTOR (Attribute) | |||
| }; | |||
| @@ -189,7 +181,7 @@ public: | |||
| /** Returns one of the string's attributes. | |||
| The index provided must be less than getNumAttributes(), and >= 0. | |||
| */ | |||
| const Attribute* getAttribute (int index) const noexcept { return attributes.getUnchecked (index); } | |||
| const Attribute& getAttribute (int index) const noexcept { return attributes.getReference (index); } | |||
| //============================================================================== | |||
| /** Adds a colour attribute for the specified range. */ | |||
| @@ -210,7 +202,7 @@ private: | |||
| Justification justification; | |||
| WordWrap wordWrap; | |||
| ReadingDirection readingDirection; | |||
| OwnedArray<Attribute> attributes; | |||
| Array<Attribute> attributes; | |||
| JUCE_LEAK_DETECTOR (AttributedString) | |||
| }; | |||
| @@ -287,29 +287,6 @@ void TextLayout::createLayoutWithBalancedLineLengths (const AttributedString& te | |||
| //============================================================================== | |||
| namespace TextLayoutHelpers | |||
| { | |||
| struct FontAndColour | |||
| { | |||
| FontAndColour (const Font* f) noexcept : font (f), colour (0xff000000) {} | |||
| const Font* font; | |||
| Colour colour; | |||
| bool operator!= (const FontAndColour& other) const noexcept | |||
| { | |||
| return (font != other.font && *font != *other.font) || colour != other.colour; | |||
| } | |||
| }; | |||
| struct RunAttribute | |||
| { | |||
| RunAttribute (const FontAndColour& fc, const Range<int> r) noexcept | |||
| : fontAndColour (fc), range (r) | |||
| {} | |||
| FontAndColour fontAndColour; | |||
| Range<int> range; | |||
| }; | |||
| struct Token | |||
| { | |||
| Token (const String& t, const Font& f, Colour c, const bool whitespace) | |||
| @@ -337,7 +314,6 @@ namespace TextLayoutHelpers | |||
| void createLayout (const AttributedString& text, TextLayout& layout) | |||
| { | |||
| tokens.ensureStorageAllocated (64); | |||
| layout.ensureStorageAllocated (totalLines); | |||
| addTextRuns (text); | |||
| @@ -465,10 +441,8 @@ namespace TextLayoutHelpers | |||
| return CharacterFunctions::isWhitespace (c) ? 2 : 1; | |||
| } | |||
| void appendText (const AttributedString& text, const Range<int> stringRange, | |||
| const Font& font, Colour colour) | |||
| void appendText (const String& stringText, const Font& font, Colour colour) | |||
| { | |||
| const String stringText (text.getText().substring (stringRange.getStart(), stringRange.getEnd())); | |||
| String::CharPointerType t (stringText.getCharPointer()); | |||
| String currentString; | |||
| int lastCharType = 0; | |||
| @@ -551,48 +525,15 @@ namespace TextLayoutHelpers | |||
| void addTextRuns (const AttributedString& text) | |||
| { | |||
| Font defaultFont; | |||
| Array<RunAttribute> runAttributes; | |||
| const int numAttributes = text.getNumAttributes(); | |||
| tokens.ensureStorageAllocated (jmax (64, numAttributes)); | |||
| for (int i = 0; i < numAttributes; ++i) | |||
| { | |||
| const int stringLength = text.getText().length(); | |||
| int rangeStart = 0; | |||
| FontAndColour lastFontAndColour (&defaultFont); | |||
| // Iterate through every character in the string | |||
| for (int i = 0; i < stringLength; ++i) | |||
| { | |||
| FontAndColour newFontAndColour (&defaultFont); | |||
| const int numCharacterAttributes = text.getNumAttributes(); | |||
| for (int j = 0; j < numCharacterAttributes; ++j) | |||
| { | |||
| const AttributedString::Attribute& attr = *text.getAttribute (j); | |||
| const AttributedString::Attribute& attr = text.getAttribute (i); | |||
| if (attr.range.contains (i)) | |||
| { | |||
| if (const Font* f = attr.getFont()) newFontAndColour.font = f; | |||
| if (const Colour* c = attr.getColour()) newFontAndColour.colour = *c; | |||
| } | |||
| } | |||
| if (i > 0 && newFontAndColour != lastFontAndColour) | |||
| { | |||
| runAttributes.add (RunAttribute (lastFontAndColour, Range<int> (rangeStart, i))); | |||
| rangeStart = i; | |||
| } | |||
| lastFontAndColour = newFontAndColour; | |||
| } | |||
| if (rangeStart < stringLength) | |||
| runAttributes.add (RunAttribute (lastFontAndColour, Range<int> (rangeStart, stringLength))); | |||
| } | |||
| for (int i = 0; i < runAttributes.size(); ++i) | |||
| { | |||
| const RunAttribute& r = runAttributes.getReference(i); | |||
| appendText (text, r.range, *(r.fontAndColour.font), r.fontAndColour.colour); | |||
| appendText (text.getText().substring (attr.range.getStart(), attr.range.getEnd()), | |||
| attr.font, attr.colour); | |||
| } | |||
| } | |||
| @@ -91,9 +91,9 @@ class LowLevelGraphicsContext; | |||
| #include "images/juce_ImageCache.h" | |||
| #include "images/juce_ImageConvolutionKernel.h" | |||
| #include "images/juce_ImageFileFormat.h" | |||
| #include "fonts/juce_AttributedString.h" | |||
| #include "fonts/juce_Typeface.h" | |||
| #include "fonts/juce_Font.h" | |||
| #include "fonts/juce_AttributedString.h" | |||
| #include "fonts/juce_GlyphArrangement.h" | |||
| #include "fonts/juce_TextLayout.h" | |||
| #include "fonts/juce_CustomTypeface.h" | |||
| @@ -229,7 +229,7 @@ namespace CoreTextTypeLayout | |||
| for (int i = 0; i < numCharacterAttributes; ++i) | |||
| { | |||
| const AttributedString::Attribute& attr = *text.getAttribute (i); | |||
| const AttributedString::Attribute& attr = text.getAttribute (i); | |||
| const int rangeStart = attr.range.getStart(); | |||
| if (rangeStart >= attribStringLen) | |||
| @@ -237,42 +237,40 @@ namespace CoreTextTypeLayout | |||
| CFRange range = CFRangeMake (rangeStart, jmin (attr.range.getEnd(), (int) attribStringLen) - rangeStart); | |||
| if (const Font* const f = attr.getFont()) | |||
| if (CTFontRef ctFontRef = getOrCreateFont (attr.font)) | |||
| { | |||
| if (CTFontRef ctFontRef = getOrCreateFont (*f)) | |||
| { | |||
| ctFontRef = getFontWithPointSize (ctFontRef, f->getHeight() * getHeightToPointsFactor (ctFontRef)); | |||
| CFAttributedStringSetAttribute (attribString, range, kCTFontAttributeName, ctFontRef); | |||
| ctFontRef = getFontWithPointSize (ctFontRef, attr.font.getHeight() * getHeightToPointsFactor (ctFontRef)); | |||
| float extraKerning = f->getExtraKerningFactor(); | |||
| CFAttributedStringSetAttribute (attribString, range, kCTFontAttributeName, ctFontRef); | |||
| if (extraKerning != 0.0f) | |||
| { | |||
| extraKerning *= f->getHeight(); | |||
| float extraKerning = attr.font.getExtraKerningFactor(); | |||
| CFNumberRef numberRef = CFNumberCreate (0, kCFNumberFloatType, &extraKerning); | |||
| CFAttributedStringSetAttribute (attribString, range, kCTKernAttributeName, numberRef); | |||
| CFRelease (numberRef); | |||
| } | |||
| if (extraKerning != 0.0f) | |||
| { | |||
| extraKerning *= attr.font.getHeight(); | |||
| CFRelease (ctFontRef); | |||
| CFNumberRef numberRef = CFNumberCreate (0, kCFNumberFloatType, &extraKerning); | |||
| CFAttributedStringSetAttribute (attribString, range, kCTKernAttributeName, numberRef); | |||
| CFRelease (numberRef); | |||
| } | |||
| CFRelease (ctFontRef); | |||
| } | |||
| if (const Colour* const col = attr.getColour()) | |||
| { | |||
| const Colour col (attr.colour); | |||
| #if JUCE_IOS | |||
| const CGFloat components[] = { col->getFloatRed(), | |||
| col->getFloatGreen(), | |||
| col->getFloatBlue(), | |||
| col->getFloatAlpha() }; | |||
| const CGFloat components[] = { col.getFloatRed(), | |||
| col.getFloatGreen(), | |||
| col.getFloatBlue(), | |||
| col.getFloatAlpha() }; | |||
| CGColorRef colour = CGColorCreate (rgbColourSpace, components); | |||
| #else | |||
| CGColorRef colour = CGColorCreateGenericRGB (col->getFloatRed(), | |||
| col->getFloatGreen(), | |||
| col->getFloatBlue(), | |||
| col->getFloatAlpha()); | |||
| CGColorRef colour = CGColorCreateGenericRGB (col.getFloatRed(), | |||
| col.getFloatGreen(), | |||
| col.getFloatBlue(), | |||
| col.getFloatAlpha()); | |||
| #endif | |||
| CFAttributedStringSetAttribute (attribString, range, kCTForegroundColorAttributeName, colour); | |||
| @@ -449,7 +447,7 @@ namespace CoreTextTypeLayout | |||
| CFDictionaryRef runAttributes = CTRunGetAttributes (run); | |||
| CTFontRef ctRunFont; | |||
| if (CFDictionaryGetValueIfPresent (runAttributes, kCTFontAttributeName, (const void **) &ctRunFont)) | |||
| if (CFDictionaryGetValueIfPresent (runAttributes, kCTFontAttributeName, (const void**) &ctRunFont)) | |||
| { | |||
| CFStringRef cfsFontName = CTFontCopyPostScriptName (ctRunFont); | |||
| CTFontRef ctFontRef = CTFontCreateWithName (cfsFontName, referenceFontSize, nullptr); | |||
| @@ -1176,17 +1174,16 @@ static bool canAllTypefacesBeUsedInLayout (const AttributedString& text) | |||
| for (int i = 0; i < numCharacterAttributes; ++i) | |||
| { | |||
| if (const Font* const f = text.getAttribute (i)->getFont()) | |||
| Typeface* t = text.getAttribute(i).font.getTypeface(); | |||
| if (OSXTypeface* tf = dynamic_cast<OSXTypeface*> (t)) | |||
| { | |||
| if (OSXTypeface* tf = dynamic_cast<OSXTypeface*> (f->getTypeface())) | |||
| { | |||
| if (tf->isMemoryFont) | |||
| return false; | |||
| } | |||
| else if (dynamic_cast<CustomTypeface*> (f->getTypeface()) != nullptr) | |||
| { | |||
| if (tf->isMemoryFont) | |||
| return false; | |||
| } | |||
| } | |||
| else if (dynamic_cast<CustomTypeface*> (t) != nullptr) | |||
| { | |||
| return false; | |||
| } | |||
| } | |||
| @@ -22,7 +22,7 @@ | |||
| ============================================================================== | |||
| */ | |||
| //================================================================================================== | |||
| #if JUCE_USE_DIRECTWRITE | |||
| namespace DirectWriteTypeLayout | |||
| { | |||
| @@ -41,7 +41,7 @@ namespace DirectWriteTypeLayout | |||
| JUCE_COMRESULT QueryInterface (REFIID refId, void** result) override | |||
| { | |||
| if (refId == __uuidof (IDWritePixelSnapping)) | |||
| return castToType <IDWritePixelSnapping> (result); | |||
| return castToType<IDWritePixelSnapping> (result); | |||
| return ComBaseClassHelper<IDWriteTextRenderer>::QueryInterface (refId, result); | |||
| } | |||
| @@ -54,12 +54,9 @@ namespace DirectWriteTypeLayout | |||
| JUCE_COMRESULT GetCurrentTransform (void*, DWRITE_MATRIX* matrix) override | |||
| { | |||
| matrix->m11 = 1.0f; | |||
| matrix->m12 = 0.0f; | |||
| matrix->m21 = 0.0f; | |||
| matrix->m22 = 1.0f; | |||
| matrix->dx = 0.0f; | |||
| matrix->dy = 0.0f; | |||
| matrix->m11 = 1.0f; matrix->m12 = 0.0f; | |||
| matrix->m21 = 0.0f; matrix->m22 = 1.0f; | |||
| matrix->dx = 0.0f; matrix->dy = 0.0f; | |||
| return S_OK; | |||
| } | |||
| @@ -172,10 +169,13 @@ namespace DirectWriteTypeLayout | |||
| Font getFontForRun (const DWRITE_GLYPH_RUN& 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); | |||
| { | |||
| const Font& font = attributedString.getAttribute(i).font; | |||
| if (WindowsDirectWriteTypeface* wt = dynamic_cast<WindowsDirectWriteTypeface*> (font.getTypeface())) | |||
| if (wt->getIDWriteFontFace() == glyphRun.fontFace) | |||
| return font.withHeight (fontHeight); | |||
| } | |||
| ComSmartPtr<IDWriteFont> dwFont; | |||
| HRESULT hr = fontCollection.GetFontFromFontFace (glyphRun.fontFace, dwFont.resetAndGetPointerAddress()); | |||
| @@ -253,9 +253,8 @@ namespace DirectWriteTypeLayout | |||
| range.startPosition = attr.range.getStart(); | |||
| range.length = jmin (attr.range.getLength(), textLen - attr.range.getStart()); | |||
| if (const Font* const font = attr.getFont()) | |||
| { | |||
| const String familyName (FontStyleHelpers::getConcreteFamilyName (*font)); | |||
| const String familyName (FontStyleHelpers::getConcreteFamilyName (attr.font)); | |||
| BOOL fontFound = false; | |||
| uint32 fontIndex; | |||
| @@ -275,7 +274,7 @@ namespace DirectWriteTypeLayout | |||
| { | |||
| hr = fontFamily->GetFont (i, dwFont.resetAndGetPointerAddress()); | |||
| if (font->getTypefaceStyle() == getFontFaceName (dwFont)) | |||
| if (attr.font.getTypefaceStyle() == getFontFaceName (dwFont)) | |||
| break; | |||
| } | |||
| @@ -285,16 +284,16 @@ namespace DirectWriteTypeLayout | |||
| textLayout.SetFontStyle (dwFont->GetStyle(), range); | |||
| const float fontHeightToEmSizeFactor = getFontHeightToEmSizeFactor (*dwFont); | |||
| textLayout.SetFontSize (font->getHeight() * fontHeightToEmSizeFactor, range); | |||
| textLayout.SetFontSize (attr.font.getHeight() * fontHeightToEmSizeFactor, range); | |||
| } | |||
| if (const Colour* const colour = attr.getColour()) | |||
| { | |||
| const Colour col (attr.colour); | |||
| ComSmartPtr<ID2D1SolidColorBrush> d2dBrush; | |||
| renderTarget.CreateSolidColorBrush (D2D1::ColorF (colour->getFloatRed(), | |||
| colour->getFloatGreen(), | |||
| colour->getFloatBlue(), | |||
| colour->getFloatAlpha()), | |||
| renderTarget.CreateSolidColorBrush (D2D1::ColorF (col.getFloatRed(), | |||
| col.getFloatGreen(), | |||
| col.getFloatBlue(), | |||
| col.getFloatAlpha()), | |||
| d2dBrush.resetAndGetPointerAddress()); | |||
| // We need to call SetDrawingEffect with a legimate brush to get DirectWrite to break text based on colours | |||
| @@ -353,7 +352,7 @@ namespace DirectWriteTypeLayout | |||
| const int numAttributes = text.getNumAttributes(); | |||
| for (int i = 0; i < numAttributes; ++i) | |||
| addAttributedRange (*text.getAttribute (i), *textLayout, textLen, renderTarget, fontCollection); | |||
| addAttributedRange (text.getAttribute (i), *textLayout, textLen, renderTarget, fontCollection); | |||
| return true; | |||
| } | |||
| @@ -419,9 +418,8 @@ 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; | |||
| if (dynamic_cast<WindowsDirectWriteTypeface*> (text.getAttribute(i).font.getTypeface()) == nullptr) | |||
| return false; | |||
| return true; | |||
| } | |||