@@ -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; | |||
} | |||