mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Refactored AttributedString so that every part of the string has a single font and colour associated with it, to avoid some problems caused by fonts being undefined.
This commit is contained in:
parent
63df487c86
commit
1a7caaa58f
6 changed files with 263 additions and 214 deletions
|
|
@ -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;
|
||||
}
|
||||
|
||||
AttributedString::Attribute::Attribute (Range<int> range_, const Font& font_)
|
||||
: range (range_), font (new Font (font_))
|
||||
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);
|
||||
}
|
||||
|
||||
AttributedString::Attribute::Attribute (const Attribute& other)
|
||||
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() noexcept : colour (0xff000000) {}
|
||||
AttributedString::Attribute::~Attribute() noexcept {}
|
||||
|
||||
#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
|
||||
AttributedString::Attribute::Attribute (Attribute&& other) noexcept
|
||||
: range (other.range),
|
||||
font (other.font.createCopy()),
|
||||
colour (other.colour.createCopy())
|
||||
font (static_cast<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= (Attribute&& other) noexcept
|
||||
{
|
||||
range = other.range;
|
||||
font = static_cast<Font&&> (other.font);
|
||||
colour = other.colour;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
AttributedString::Attribute::Attribute (const Attribute& other) noexcept
|
||||
: range (other.range),
|
||||
font (other.font),
|
||||
colour (other.colour)
|
||||
{
|
||||
}
|
||||
|
||||
AttributedString::Attribute::~Attribute() {}
|
||||
AttributedString::Attribute& AttributedString::Attribute::operator= (const Attribute& other) noexcept
|
||||
{
|
||||
range = other.range;
|
||||
font = other.font;
|
||||
colour = other.colour;
|
||||
return *this;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
void AttributedString::setColour (Colour colour)
|
||||
{
|
||||
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, nullptr, &colour);
|
||||
}
|
||||
|
||||
void AttributedString::setFont (Range<int> range, const Font& font)
|
||||
{
|
||||
attributes.add (new Attribute (range, font));
|
||||
applyFontAndColour (attributes, range, &font, nullptr);
|
||||
}
|
||||
|
||||
void AttributedString::setColour (Colour colour)
|
||||
{
|
||||
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);
|
||||
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 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; }
|
||||
/** 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;
|
||||
|
||||
/** The font for this range of characters. */
|
||||
Font font;
|
||||
|
||||
/** The colour for this range of characters. */
|
||||
Colour colour;
|
||||
|
||||
private:
|
||||
ScopedPointer<Font> font;
|
||||
ScopedPointer<Colour> colour;
|
||||
|
||||
friend class AttributedString;
|
||||
Attribute (const Attribute&, int);
|
||||
Attribute& operator= (const Attribute&);
|
||||
|
||||
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);
|
||||
const AttributedString::Attribute& attr = text.getAttribute (i);
|
||||
|
||||
// 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);
|
||||
|
||||
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,19 +237,17 @@ 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));
|
||||
ctFontRef = getFontWithPointSize (ctFontRef, attr.font.getHeight() * getHeightToPointsFactor (ctFontRef));
|
||||
|
||||
CFAttributedStringSetAttribute (attribString, range, kCTFontAttributeName, ctFontRef);
|
||||
|
||||
float extraKerning = f->getExtraKerningFactor();
|
||||
float extraKerning = attr.font.getExtraKerningFactor();
|
||||
|
||||
if (extraKerning != 0.0f)
|
||||
{
|
||||
extraKerning *= f->getHeight();
|
||||
extraKerning *= attr.font.getHeight();
|
||||
|
||||
CFNumberRef numberRef = CFNumberCreate (0, kCFNumberFloatType, &extraKerning);
|
||||
CFAttributedStringSetAttribute (attribString, range, kCTKernAttributeName, numberRef);
|
||||
|
|
@ -258,21 +256,21 @@ namespace CoreTextTypeLayout
|
|||
|
||||
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);
|
||||
|
|
@ -1176,19 +1174,18 @@ static bool canAllTypefacesBeUsedInLayout (const AttributedString& text)
|
|||
|
||||
for (int i = 0; i < numCharacterAttributes; ++i)
|
||||
{
|
||||
if (const Font* const f = text.getAttribute (i)->getFont())
|
||||
{
|
||||
if (OSXTypeface* tf = dynamic_cast<OSXTypeface*> (f->getTypeface()))
|
||||
Typeface* t = text.getAttribute(i).font.getTypeface();
|
||||
|
||||
if (OSXTypeface* tf = dynamic_cast<OSXTypeface*> (t))
|
||||
{
|
||||
if (tf->isMemoryFont)
|
||||
return false;
|
||||
}
|
||||
else if (dynamic_cast<CustomTypeface*> (f->getTypeface()) != nullptr)
|
||||
else if (dynamic_cast<CustomTypeface*> (t) != nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
==============================================================================
|
||||
*/
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
#if JUCE_USE_DIRECTWRITE
|
||||
namespace DirectWriteTypeLayout
|
||||
{
|
||||
|
|
@ -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()))
|
||||
{
|
||||
const Font& font = attributedString.getAttribute(i).font;
|
||||
|
||||
if (WindowsDirectWriteTypeface* wt = dynamic_cast<WindowsDirectWriteTypeface*> (font.getTypeface()))
|
||||
if (wt->getIDWriteFontFace() == glyphRun.fontFace)
|
||||
return font->withHeight (fontHeight);
|
||||
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,8 +418,7 @@ 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)
|
||||
if (dynamic_cast<WindowsDirectWriteTypeface*> (text.getAttribute(i).font.getTypeface()) == nullptr)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue