|
OpenTTD Source
13.0-beta2
|
Go to the documentation of this file.
19 #include <unicode/ustring.h>
48 assert(size < FS_END);
54 le_int32 Font::getUnitsPerEM()
const
56 return this->fc->GetUnitsPerEM();
59 le_int32 Font::getAscent()
const
61 return this->fc->GetAscender();
64 le_int32 Font::getDescent()
const
66 return -this->fc->GetDescender();
69 le_int32 Font::getLeading()
const
71 return this->fc->GetHeight();
74 float Font::getXPixelsPerEm()
const
76 return (
float)this->fc->GetHeight();
79 float Font::getYPixelsPerEm()
const
81 return (
float)this->fc->GetHeight();
84 float Font::getScaleFactorX()
const
89 float Font::getScaleFactorY()
const
94 const void *Font::getFontTable(LETag tableTag)
const
97 return this->getFontTable(tableTag, length);
100 const void *Font::getFontTable(LETag tableTag,
size_t &length)
const
102 return this->fc->GetFontTable(tableTag, length);
105 LEGlyphID Font::mapCharToGlyph(LEUnicode32 ch)
const
108 return this->fc->MapCharToGlyph(ch);
111 void Font::getGlyphAdvance(LEGlyphID glyph, LEPoint &advance)
const
113 advance.fX = glyph == 0xFFFF ? 0 : this->fc->GetGlyphWidth(glyph);
117 le_bool Font::getGlyphPoint(LEGlyphID glyph, le_int32 pointNumber, LEPoint &point)
const
126 icu::ParagraphLayout *
p;
130 const icu::ParagraphLayout::VisualRun *
vr;
135 const Font *GetFont()
const override {
return (
const Font*)
vr->getFont(); }
136 int GetGlyphCount()
const override {
return vr->getGlyphCount(); }
137 const GlyphID *GetGlyphs()
const override {
return vr->getGlyphs(); }
138 const float *GetPositions()
const override {
return vr->getPositions(); }
139 int GetLeading()
const override {
return vr->getLeading(); }
140 const int *GetGlyphToCharMap()
const override {
return vr->getGlyphToCharMap(); }
145 icu::ParagraphLayout::Line *
l;
150 for (
int i = 0; i <
l->countRuns(); i++) {
151 this->emplace_back(
l->getVisualRun(i));
156 int GetLeading()
const override {
return l->getLeading(); }
157 int GetWidth()
const override {
return l->getWidth(); }
158 int CountRuns()
const override {
return l->countRuns(); }
161 int GetInternalCharLength(
WChar c)
const override
170 void Reflow()
override {
p->reflow(); }
172 std::unique_ptr<const Line> NextLine(
int max_width)
override
174 icu::ParagraphLayout::Line *l =
p->nextLine(max_width);
175 return std::unique_ptr<const Line>(l ==
nullptr ?
nullptr :
new ICULine(l));
191 int32 length = buff_end - buff;
197 fontMapping.back().first++;
201 icu::FontRuns runs(fontMapping.size());
202 for (
auto &pair : fontMapping) {
203 runs.add(pair.second, pair.first);
206 LEErrorCode status = LE_NO_ERROR;
209 icu::ParagraphLayout *p =
new icu::ParagraphLayout(buff, length, &runs,
nullptr,
nullptr,
nullptr,
_current_text_dir ==
TD_RTL ? 1 : 0,
false, status);
210 if (status != LE_NO_ERROR) {
218 static size_t AppendToBuffer(UChar *buff,
const UChar *buffer_last,
WChar c)
222 UErrorCode err = U_ZERO_ERROR;
223 u_strFromUTF32(buff, buffer_last - buff, &length, (UChar32*)&c, 1, &err);
262 const Font *
GetFont()
const override;
278 int GetInternalCharLength(
WChar c)
const override {
return 1; }
287 std::unique_ptr<const Line>
NextLine(
int max_width)
override;
334 font(font), glyph_count(char_count)
336 const bool isbuiltin =
font->fc->IsBuiltInFont();
346 this->
glyphs[i] =
font->fc->MapCharToGlyph(chars[i]);
349 }
else if (chars[i] >= SCC_SPRITE_START && chars[i] <= SCC_SPRITE_END) {
362 this->positions = other.positions;
363 this->glyph_to_char = other.glyph_to_char;
364 this->glyphs = other.glyphs;
366 other.positions =
nullptr;
367 other.glyph_to_char =
nullptr;
368 other.glyphs =
nullptr;
374 free(this->positions);
375 free(this->glyph_to_char);
394 return this->glyph_count;
412 return this->positions;
421 return this->glyph_to_char;
430 return this->GetFont()->fc->GetHeight();
440 for (
const auto &run : *
this) {
441 leading = std::max(leading, run.GetLeading());
453 if (this->size() == 0)
return 0;
460 const auto &run = this->GetVisualRun(this->CountRuns() - 1);
461 return (
int)run.GetPositions()[run.GetGlyphCount() * 2];
470 return (uint)this->size();
479 return this->at(run);
490 assert(
runs.End()[-1].first == length);
512 if (this->
buffer ==
nullptr)
return nullptr;
516 if (*this->
buffer ==
'\0') {
519 l->emplace_back(this->
runs.front().second, this->buffer, 0, 0);
524 FontMap::iterator iter = this->
runs.data();
525 while (iter->first <= offset) {
527 assert(iter != this->
runs.End());
531 const WChar *next_run = this->buffer_begin + iter->first;
534 const WChar *last_space =
nullptr;
535 const WChar *last_char;
546 if (this->
buffer == next_run) {
547 int w = l->GetWidth();
548 l->emplace_back(iter->second, begin, this->buffer - begin, w);
550 assert(iter != this->
runs.End());
552 next_run = this->buffer_begin + iter->first;
555 last_space =
nullptr;
563 if (width > max_width) {
566 if (width == char_width) {
573 if (last_space ==
nullptr) {
583 this->
buffer = last_space + 1;
584 last_char = last_space;
593 if (l->size() == 0 || last_char - begin != 0) {
594 int w = l->GetWidth();
595 l->emplace_back(iter->second, begin, last_char - begin, w);
609 template <
typename T>
616 typename T::CharType *buff = buff_begin;
628 for (; buff < buffer_last;) {
629 WChar c = Utf8Consume(
const_cast<const char **
>(&str));
630 if (c ==
'\0' || c ==
'\n') {
632 }
else if (c >= SCC_BLUE && c <= SCC_BLACK) {
634 }
else if (c == SCC_PUSH_COLOUR) {
636 }
else if (c == SCC_POP_COLOUR) {
638 }
else if (c >= SCC_FIRST_FONT && c <= SCC_LAST_FONT) {
642 if (!IsPrintable(c))
continue;
647 buff += T::AppendToBuffer(buff, buffer_last, c);
651 if (!fontMapping.
Contains(buff - buff_begin)) {
652 fontMapping.
Insert(buff - buff_begin, f);
660 if (!fontMapping.
Contains(buff - buff_begin)) {
661 fontMapping.
Insert(buff - buff_begin, f);
663 line.
layout = T::GetParagraphLayout(buff_begin, buff, fontMapping);
681 const char *lineend = str;
684 if (c ==
'\0' || c ==
'\n')
break;
689 if (line.
layout !=
nullptr) {
697 #if defined(WITH_ICU_LX) || defined(WITH_UNISCRIBE) || defined(WITH_COCOA)
698 const char *old_str = str;
702 GetLayouter<ICUParagraphLayoutFactory>(line, str, state);
703 if (line.
layout ==
nullptr) {
704 static bool warned =
false;
706 Debug(misc, 0,
"ICU layouter bailed on the font. Falling back to the fallback layouter");
715 #ifdef WITH_UNISCRIBE
716 if (line.
layout ==
nullptr) {
717 GetLayouter<UniscribeParagraphLayoutFactory>(line, str, state);
718 if (line.
layout ==
nullptr) {
726 if (line.
layout ==
nullptr) {
727 GetLayouter<CoreTextParagraphLayoutFactory>(line, str, state);
728 if (line.
layout ==
nullptr) {
735 if (line.
layout ==
nullptr) {
736 GetLayouter<FallbackParagraphLayoutFactory>(line, str, state);
742 auto l = line.
layout->NextLine(maxw);
743 if (l ==
nullptr)
break;
744 this->push_back(std::move(l));
756 for (
const auto &l : *
this) {
757 d.width = std::max<uint>(d.width, l->GetWidth());
758 d.height += l->GetLeading();
774 const char *str = this->
string;
778 if (c ==
'\0' || c ==
'\n')
break;
780 index += this->front()->GetInternalCharLength(c);
785 const auto &line = this->front();
788 if (*ch ==
'\0' || *ch ==
'\n') {
789 Point p = { line->GetWidth(), 0 };
794 for (
int run_index = 0; run_index < line->CountRuns(); run_index++) {
797 for (
int i = 0; i < run.GetGlyphCount(); i++) {
799 if ((
size_t)run.GetGlyphToCharMap()[i] == index) {
800 Point p = { (int)run.GetPositions()[i * 2], (int)run.GetPositions()[i * 2 + 1] };
818 const auto &line = this->front();
820 for (
int run_index = 0; run_index < line->CountRuns(); run_index++) {
823 for (
int i = 0; i < run.GetGlyphCount(); i++) {
825 if (run.GetGlyphs()[i] == 0xFFFF)
continue;
827 int begin_x = (int)run.GetPositions()[i * 2];
828 int end_x = (int)run.GetPositions()[i * 2 + 2];
832 size_t index = run.GetGlyphToCharMap()[i];
835 for (
const char *str = this->
string; *str !=
'\0'; ) {
836 if (cur_idx == index)
return str;
838 WChar c = Utf8Consume(&str);
839 cur_idx += line->GetInternalCharLength(c);
853 FontColourMap::iterator it =
fonts[size].
Find(colour);
854 if (it !=
fonts[size].End())
return it->second;
856 Font *f =
new Font(size, colour);
857 fonts[size].emplace_back(colour, f);
867 for (
auto &pair :
fonts[size]) {
875 #if defined(WITH_UNISCRIBE)
876 UniscribeResetScriptCache(size);
878 #if defined(WITH_COCOA)
899 match != linecache->end()) {
900 return match->second;
905 key.state_before = state;
906 key.str.assign(str, len);
907 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.
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.