Go to the documentation of this file.
20 #include <unicode/ustring.h>
49 assert(size < FS_END);
55 le_int32 Font::getUnitsPerEM()
const
57 return this->fc->GetUnitsPerEM();
60 le_int32 Font::getAscent()
const
62 return this->fc->GetAscender();
65 le_int32 Font::getDescent()
const
67 return -this->fc->GetDescender();
70 le_int32 Font::getLeading()
const
72 return this->fc->GetHeight();
75 float Font::getXPixelsPerEm()
const
77 return (
float)this->fc->GetHeight();
80 float Font::getYPixelsPerEm()
const
82 return (
float)this->fc->GetHeight();
85 float Font::getScaleFactorX()
const
90 float Font::getScaleFactorY()
const
95 const void *Font::getFontTable(LETag tableTag)
const
98 return this->getFontTable(tableTag, length);
101 const void *Font::getFontTable(LETag tableTag,
size_t &length)
const
103 return this->fc->GetFontTable(tableTag, length);
106 LEGlyphID Font::mapCharToGlyph(LEUnicode32 ch)
const
109 return this->fc->MapCharToGlyph(ch);
112 void Font::getGlyphAdvance(LEGlyphID glyph, LEPoint &advance)
const
114 advance.fX = glyph == 0xFFFF ? 0 : this->fc->GetGlyphWidth(glyph);
118 le_bool Font::getGlyphPoint(LEGlyphID glyph, le_int32 pointNumber, LEPoint &point)
const
127 icu::ParagraphLayout *
p;
131 const icu::ParagraphLayout::VisualRun *
vr;
136 const Font *GetFont()
const override {
return (
const Font*)
vr->getFont(); }
137 int GetGlyphCount()
const override {
return vr->getGlyphCount(); }
138 const GlyphID *GetGlyphs()
const override {
return vr->getGlyphs(); }
139 const float *GetPositions()
const override {
return vr->getPositions(); }
140 int GetLeading()
const override {
return vr->getLeading(); }
141 const int *GetGlyphToCharMap()
const override {
return vr->getGlyphToCharMap(); }
146 icu::ParagraphLayout::Line *
l;
151 for (
int i = 0; i <
l->countRuns(); i++) {
152 this->emplace_back(
l->getVisualRun(i));
157 int GetLeading()
const override {
return l->getLeading(); }
158 int GetWidth()
const override {
return l->getWidth(); }
159 int CountRuns()
const override {
return l->countRuns(); }
162 int GetInternalCharLength(
WChar c)
const override
171 void Reflow()
override {
p->reflow(); }
173 std::unique_ptr<const Line> NextLine(
int max_width)
override
175 icu::ParagraphLayout::Line *l =
p->nextLine(max_width);
176 return std::unique_ptr<const Line>(l ==
nullptr ?
nullptr :
new ICULine(l));
192 int32 length = buff_end - buff;
198 fontMapping.back().first++;
202 icu::FontRuns runs(fontMapping.size());
203 for (
auto &pair : fontMapping) {
204 runs.add(pair.second, pair.first);
207 LEErrorCode status = LE_NO_ERROR;
210 icu::ParagraphLayout *p =
new icu::ParagraphLayout(buff, length, &runs,
nullptr,
nullptr,
nullptr,
_current_text_dir ==
TD_RTL ? 1 : 0,
false, status);
211 if (status != LE_NO_ERROR) {
219 static size_t AppendToBuffer(UChar *buff,
const UChar *buffer_last,
WChar c)
223 UErrorCode err = U_ZERO_ERROR;
224 u_strFromUTF32(buff, buffer_last - buff, &length, (UChar32*)&c, 1, &err);
263 const Font *
GetFont()
const override;
279 int GetInternalCharLength(
WChar c)
const override {
return 1; }
288 std::unique_ptr<const Line>
NextLine(
int max_width)
override;
335 font(font), glyph_count(char_count)
337 const bool isbuiltin =
font->fc->IsBuiltInFont();
347 this->
glyphs[i] =
font->fc->MapCharToGlyph(chars[i]);
350 }
else if (chars[i] >= SCC_SPRITE_START && chars[i] <= SCC_SPRITE_END) {
363 this->positions = other.positions;
364 this->glyph_to_char = other.glyph_to_char;
365 this->glyphs = other.glyphs;
367 other.positions =
nullptr;
368 other.glyph_to_char =
nullptr;
369 other.glyphs =
nullptr;
375 free(this->positions);
376 free(this->glyph_to_char);
395 return this->glyph_count;
413 return this->positions;
422 return this->glyph_to_char;
431 return this->GetFont()->fc->GetHeight();
441 for (
const auto &run : *
this) {
442 leading = std::max(leading, run.GetLeading());
454 if (this->size() == 0)
return 0;
461 const auto &run = this->GetVisualRun(this->CountRuns() - 1);
462 return (
int)run.GetPositions()[run.GetGlyphCount() * 2];
471 return (uint)this->size();
480 return this->at(run);
491 assert(
runs.End()[-1].first == length);
513 if (this->
buffer ==
nullptr)
return nullptr;
517 if (*this->
buffer ==
'\0') {
520 l->emplace_back(this->
runs.front().second, this->buffer, 0, 0);
525 FontMap::iterator iter = this->
runs.data();
526 while (iter->first <= offset) {
528 assert(iter != this->
runs.End());
532 const WChar *next_run = this->buffer_begin + iter->first;
535 const WChar *last_space =
nullptr;
536 const WChar *last_char;
547 if (this->
buffer == next_run) {
548 int w = l->GetWidth();
549 l->emplace_back(iter->second, begin, this->buffer - begin, w);
551 assert(iter != this->
runs.End());
553 next_run = this->buffer_begin + iter->first;
562 if (width > max_width) {
565 if (width == char_width) {
572 if (last_space ==
nullptr) {
582 this->
buffer = last_space + 1;
583 last_char = last_space;
592 if (l->size() == 0 || last_char - begin > 0) {
593 int w = l->GetWidth();
594 l->emplace_back(iter->second, begin, last_char - begin, w);
608 template <
typename T>
615 typename T::CharType *buff = buff_begin;
627 for (; buff < buffer_last;) {
628 WChar c = Utf8Consume(
const_cast<const char **
>(&str));
629 if (c ==
'\0' || c ==
'\n') {
631 }
else if (c >= SCC_BLUE && c <= SCC_BLACK) {
633 }
else if (c == SCC_PUSH_COLOUR) {
635 }
else if (c == SCC_POP_COLOUR) {
637 }
else if (c >= SCC_FIRST_FONT && c <= SCC_LAST_FONT) {
641 if (!IsPrintable(c))
continue;
646 buff += T::AppendToBuffer(buff, buffer_last, c);
650 if (!fontMapping.
Contains(buff - buff_begin)) {
651 fontMapping.
Insert(buff - buff_begin, f);
659 if (!fontMapping.
Contains(buff - buff_begin)) {
660 fontMapping.
Insert(buff - buff_begin, f);
662 line.
layout = T::GetParagraphLayout(buff_begin, buff, fontMapping);
680 const char *lineend = str;
683 if (c ==
'\0' || c ==
'\n')
break;
688 if (line.
layout !=
nullptr) {
696 #if defined(WITH_ICU_LX) || defined(WITH_UNISCRIBE) || defined(WITH_COCOA)
697 const char *old_str = str;
701 GetLayouter<ICUParagraphLayoutFactory>(line, str, state);
702 if (line.
layout ==
nullptr) {
703 static bool warned =
false;
705 Debug(misc, 0,
"ICU layouter bailed on the font. Falling back to the fallback layouter");
714 #ifdef WITH_UNISCRIBE
715 if (line.
layout ==
nullptr) {
716 GetLayouter<UniscribeParagraphLayoutFactory>(line, str, state);
717 if (line.
layout ==
nullptr) {
725 if (line.
layout ==
nullptr) {
726 GetLayouter<CoreTextParagraphLayoutFactory>(line, str, state);
727 if (line.
layout ==
nullptr) {
734 if (line.
layout ==
nullptr) {
735 GetLayouter<FallbackParagraphLayoutFactory>(line, str, state);
741 auto l = line.
layout->NextLine(maxw);
742 if (l ==
nullptr)
break;
743 this->push_back(std::move(l));
755 for (
const auto &l : *
this) {
756 d.width = std::max<uint>(d.width, l->GetWidth());
757 d.height += l->GetLeading();
773 const char *str = this->
string;
777 if (c ==
'\0' || c ==
'\n')
break;
779 index += this->front()->GetInternalCharLength(c);
784 const auto &line = this->front();
787 if (*ch ==
'\0' || *ch ==
'\n') {
788 Point p = { line->GetWidth(), 0 };
793 for (
int run_index = 0; run_index < line->CountRuns(); run_index++) {
796 for (
int i = 0; i < run.GetGlyphCount(); i++) {
798 if ((
size_t)run.GetGlyphToCharMap()[i] == index) {
799 Point p = { (int)run.GetPositions()[i * 2], (int)run.GetPositions()[i * 2 + 1] };
817 const auto &line = this->front();
819 for (
int run_index = 0; run_index < line->CountRuns(); run_index++) {
822 for (
int i = 0; i < run.GetGlyphCount(); i++) {
824 if (run.GetGlyphs()[i] == 0xFFFF)
continue;
826 int begin_x = (int)run.GetPositions()[i * 2];
827 int end_x = (int)run.GetPositions()[i * 2 + 2];
831 size_t index = run.GetGlyphToCharMap()[i];
834 for (
const char *str = this->
string; *str !=
'\0'; ) {
835 if (cur_idx == index)
return str;
837 WChar c = Utf8Consume(&str);
838 cur_idx += line->GetInternalCharLength(c);
852 FontColourMap::iterator it =
fonts[size].
Find(colour);
853 if (it !=
fonts[size].End())
return it->second;
855 Font *f =
new Font(size, colour);
856 fonts[size].emplace_back(colour, f);
866 for (
auto &pair :
fonts[size]) {
874 #if defined(WITH_UNISCRIBE)
875 UniscribeResetScriptCache(size);
877 #if defined(WITH_COCOA)
898 match != linecache->end()) {
899 return match->second;
904 key.state_before = state;
905 key.str.assign(str, len);
906 return (*linecache)[key];
uint32 GlyphID
Glyphs are characters from a font.
static constexpr bool IsInsideMM(const T x, const size_t min, const size_t max) noexcept
Checks if a value is in an interval.
char32_t WChar
Type for wide characters, i.e.
FontSize GetSize() const
Get the FontSize of the font.
Dimensions (a width and height) of a rectangle in 2D.
const icu::ParagraphLayout::VisualRun * vr
The actual ICU vr.
void PopColour()
Switch to and pop the last saved colour on the stack.
static const bool SUPPORTS_RTL
Helper for GetLayouter, to get whether the layouter supports RTL.
static int8 Utf8CharLen(WChar c)
Return the length of a UTF-8 encoded character.
const char * string
Pointer to the original string.
static LineCache * linecache
Cache of ParagraphLayout lines.
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Point GetCharPosition(const char *ch) const
Get the position of a character in the layout.
static void ResetFontCache(FontSize size)
Reset cached font information.
Helper class to construct a new FallbackParagraphLayout.
FallbackVisualRun(Font *font, const WChar *chars, int glyph_count, int x)
Create the visual run.
bool Insert(const T &key, const U &data)
Adds new item to this map.
FontMap & runs
The fonts we have to use for this paragraph.
Visual run contains data about the bit of text with the same font.
Interface to glue fallback and normal layouter into one.
Implementation of simple mapping class.
ParagraphLayouter * layout
Layout of the line.
const WChar * buffer_begin
Begin of the buffer.
A single line worth of VisualRuns.
UChar CharType
Helper for GetLayouter, to get the right type.
int GetWidth() const override
Get the width of this line.
static const int DRAW_STRING_BUFFER
Size of the buffer used for drawing strings.
static FontColourMap fonts[FS_END]
Cache of Font instances.
const float * GetPositions() const override
Get the positions of this run.
void Reflow() override
Reset the position to the start of the paragraph.
static void GetLayouter(Layouter::LineCacheItem &line, const char *&str, FontState &state)
Helper for getting a ParagraphLayouter of the given type.
FontMap runs
Accessed by our ParagraphLayout::nextLine.
Visual run contains data about the bit of text with the same font.
FontSize fontsize
Current font size.
Dimension GetBounds()
Get the boundaries of this paragraph.
Layouter(const char *str, int maxw=INT32_MAX, TextColour colour=TC_FROMSTRING, FontSize fontsize=FS_NORMAL)
Create a new layouter.
static int ScaleSpriteTrad(int value)
Scale traditional pixel dimensions to GUI zoom level, for drawing sprites.
GlyphID * glyphs
The glyphs we're drawing.
float * positions
The positions of the glyphs.
static Font * GetFont(FontSize size, TextColour colour)
Get a static font instance.
int GetGlyphCount() const override
Get the number of glyphs in this run.
int CountRuns() const override
Get the number of runs in this line.
static const bool SUPPORTS_RTL
Helper for GetLayouter, to get whether the layouter supports RTL.
~FallbackVisualRun() override
Free all data.
int GetLeading() const override
Get the height of this font.
Coordinates of a point in 2D.
const ParagraphLayouter::VisualRun & GetVisualRun(int run) const override
Get a specific visual run.
static size_t AppendToBuffer(WChar *buff, const WChar *buffer_last, WChar c)
Append a wide character to the internal buffer.
Class handling the splitting of a paragraph of text into lines and visual runs.
size_t Utf8Decode(WChar *c, const char *s)
Decode and consume the next UTF-8 encoded character.
static void ReduceLineCache()
Reduce the size of linecache if necessary to prevent infinite growth.
Visual run contains data about the bit of text with the same font.
const int * GetGlyphToCharMap() const override
Get the glyph-to-character map for this visual run.
TextColour cur_colour
Current text colour.
Font cache for basic fonts.
const GlyphID * GetGlyphs() const override
Get the glyphs of this run.
int GetLeading() const override
Get the height of the line.
const char * GetCharAtPosition(int x) const
Get the character that is at a position.
int glyph_count
The number of glyphs.
void SetColour(TextColour c)
Switch to new colour c.
FontState state_after
Font state after the line.
icu::ParagraphLayout * p
The actual ICU paragraph layout.
static ParagraphLayouter * GetParagraphLayout(WChar *buff, WChar *buff_end, FontMap &fontMapping)
Get the actual ParagraphLayout for the given buffer.
static LineCacheItem & GetCachedParagraphLayout(const char *str, size_t len, const FontState &state)
Get reference to cache item.
A single line worth of VisualRuns.
Helper class to construct a new ICUParagraphLayout.
byte GetCharacterWidth(FontSize size, WChar key)
Return width of character glyph.
std::vector< Pair >::const_iterator Find(const T &key) const
Finds given key in this map.
#define Debug(name, level, format_string,...)
Ouptut a line of debugging information.
void SetFontSize(FontSize f)
Switch to using a new font f.
WChar CharType
Helper for GetLayouter, to get the right type.
Text drawing parameters, which can change while drawing a line, but are kept between multiple parts o...
Wrapper for doing layouts with ICU.
static void ResetLineCache()
Clear line cache.
static bool IsWhitespace(WChar c)
Check whether UNICODE character is whitespace or not, i.e.
void MacOSResetScriptCache(FontSize size)
Delete CoreText font reference for a specific font size.
FontSize
Available font sizes.
icu::ParagraphLayout::Line * l
The actual ICU line.
static void free(const void *ptr)
Version of the standard free that accepts const pointers.
A single line worth of VisualRuns.
const WChar * buffer
The current location in the buffer.
void PushColour()
Push the current colour on to the stack.
int * glyph_to_char
The char index of the glyphs.
@ TD_RTL
Text is written right-to-left by default.
TextDirection _current_text_dir
Text direction of the currently selected language.
void * buffer
Accessed by both ICU's and our ParagraphLayout::nextLine.
Font * font
The font used to layout these.
static bool IsTextDirectionChar(WChar c)
Is the given character a text direction character.
std::unique_ptr< const Line > NextLine(int max_width) override
Construct a new line with a maximum width.
FallbackParagraphLayout(WChar *buffer, int length, FontMap &runs)
Create a new paragraph layouter.
const Font * GetFont() const override
Get the font associated with this run.
bool Contains(const T &key) const
Tests whether a key is assigned in this map.