Navigation Menu

Skip to content

Commit

Permalink
Optimize|Refactor|libgui|Font: Faster rich format subranges
Browse files Browse the repository at this point in the history
Profiling showed that majority of the time used by FontLineWrapping
was spent splitting RichFormat instances into subranges. This commit
revises the implementation of RichFormat so that it is efficient
to refer to a subrange of a RichFormat -- no copying or modification
occurs.
  • Loading branch information
skyjake committed Aug 5, 2013
1 parent 0f71cc5 commit abb3ee9
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 88 deletions.
6 changes: 3 additions & 3 deletions doomsday/client/src/ui/widgets/fontlinewrapping.cpp
Expand Up @@ -96,7 +96,7 @@ DENG2_PIMPL_NOREF(FontLineWrapping)

int rangeIndentMarkWidth(Rangei const &range) const
{
Font::RichFormat rich = format.subRange(range);
Font::RichFormatRef rich = format.subRange(range);
Font::RichFormat::Iterator iter(rich);
int markWidth = 0;
while(iter.hasNext())
Expand Down Expand Up @@ -137,7 +137,7 @@ DENG2_PIMPL_NOREF(FontLineWrapping)
// Determine segments in the line.
int pos = range.start;

Font::RichFormat rich = format.subRange(range);
Font::RichFormatRef rich = format.subRange(range);
Font::RichFormat::Iterator iter(rich);

// Divide the line into segments based on tab stops.
Expand Down Expand Up @@ -202,7 +202,7 @@ DENG2_PIMPL_NOREF(FontLineWrapping)

bool containsTabs(Rangei const &range) const
{
Font::RichFormat rich = format.subRange(range);
Font::RichFormatRef rich = format.subRange(range);
Font::RichFormat::Iterator iter(rich);
while(iter.hasNext())
{
Expand Down
2 changes: 1 addition & 1 deletion doomsday/client/src/ui/widgets/gltextcomposer.cpp
Expand Up @@ -179,7 +179,7 @@ DENG2_PIMPL(GLTextComposer)
// The color is white unless a style is defined.
Vector4ub fgColor(255, 255, 255, 255);

if(format.haveStyle())
if(format.hasStyle())
{
fgColor = format.style().richStyleColor(Font::RichFormat::NormalColor);
}
Expand Down
50 changes: 42 additions & 8 deletions doomsday/libgui/include/de/gui/font.h
Expand Up @@ -138,6 +138,34 @@ class LIBGUI_PUBLIC Font
Style &fontStyle, int &colorIndex) const = 0;
};

/**
* Reference to a (portion) of an existing RichFormat instance.
*/
class LIBGUI_PUBLIC Ref
{
public:
Ref(Ref const &ref);
Ref(Ref const &ref, Rangei const &subSpan);
Ref(RichFormat const &richFormat);
Ref(RichFormat const &richFormat, Rangei const &subSpan);

Ref subRef(Rangei const &subSpan) const;

/// Returns the original referred RichFormat instance.
RichFormat const &format() const;

int rangeCount() const;
Rangei range(int index) const;
Rangei rangeIndices() const { return _indices; }

private:
void updateIndices();

RichFormat const &_ref;
Rangei _span;
Rangei _indices; ///< Applicable indices in the referred format's ranges list.
};

public:
RichFormat();
RichFormat(IStyle const &style);
Expand All @@ -147,7 +175,7 @@ class LIBGUI_PUBLIC Font

void clear();

bool haveStyle() const;
bool hasStyle() const;
void setStyle(IStyle const &style);
IStyle const &style() const;

Expand Down Expand Up @@ -179,7 +207,7 @@ class LIBGUI_PUBLIC Font
*
* @return RichFormat with only those ranges covering @a range.
*/
RichFormat subRange(Rangei const &range) const;
Ref subRange(Rangei const &range) const;

TabStops const &tabStops() const;

Expand All @@ -193,15 +221,19 @@ class LIBGUI_PUBLIC Font
*/
struct LIBGUI_PUBLIC Iterator
{
RichFormat const &format;
Ref format;
int index;

public:
Iterator(RichFormat const &f);
Iterator(Ref const &ref);

int size() const;
bool hasNext() const;
void next();

bool isOriginal() const;
/// Determines if all the style parameters are the same as the default ones.
bool isDefault() const;

Rangei range() const;
float sizeFactor() const;
Weight weight() const;
Expand All @@ -217,6 +249,8 @@ class LIBGUI_PUBLIC Font
DENG2_PRIVATE(d)
};

typedef RichFormat::Ref RichFormatRef;

public:
Font();

Expand Down Expand Up @@ -246,7 +280,7 @@ class LIBGUI_PUBLIC Font
*
* @return Rectangle covered by the text.
*/
Rectanglei measure(String const &textLine, RichFormat const &format) const;
Rectanglei measure(String const &textLine, RichFormatRef const &format) const;

/**
* Returns the advance width of a line of text. This may not be the same as
Expand All @@ -259,7 +293,7 @@ class LIBGUI_PUBLIC Font
*/
int advanceWidth(String const &textLine) const;

int advanceWidth(String const &textLine, RichFormat const &format) const;
int advanceWidth(String const &textLine, RichFormatRef const &format) const;

/**
* Rasterizes a line of text onto a 32-bit RGBA image.
Expand All @@ -275,7 +309,7 @@ class LIBGUI_PUBLIC Font
Vector4ub const &background = Vector4ub(255, 255, 255, 0)) const;

QImage rasterize(String const &textLine,
RichFormat const &format,
RichFormatRef const &format,
Vector4ub const &foreground = Vector4ub(255, 255, 255, 255),
Vector4ub const &background = Vector4ub(255, 255, 255, 0)) const;

Expand Down

0 comments on commit abb3ee9

Please sign in to comment.