21 #include <unicode/ustring.h> 50 assert(size < FS_END);
56 le_int32 Font::getUnitsPerEM()
const 58 return this->fc->GetUnitsPerEM();
61 le_int32 Font::getAscent()
const 63 return this->fc->GetAscender();
66 le_int32 Font::getDescent()
const 68 return -this->fc->GetDescender();
71 le_int32 Font::getLeading()
const 73 return this->fc->GetHeight();
76 float Font::getXPixelsPerEm()
const 78 return (
float)this->fc->GetHeight();
81 float Font::getYPixelsPerEm()
const 83 return (
float)this->fc->GetHeight();
86 float Font::getScaleFactorX()
const 91 float Font::getScaleFactorY()
const 96 const void *Font::getFontTable(LETag tableTag)
const 99 return this->getFontTable(tableTag, length);
102 const void *Font::getFontTable(LETag tableTag,
size_t &length)
const 104 return this->fc->GetFontTable(tableTag, length);
107 LEGlyphID Font::mapCharToGlyph(LEUnicode32 ch)
const 110 return this->fc->MapCharToGlyph(ch);
113 void Font::getGlyphAdvance(LEGlyphID glyph, LEPoint &advance)
const 115 advance.fX = glyph == 0xFFFF ? 0 : this->fc->GetGlyphWidth(glyph);
119 le_bool Font::getGlyphPoint(LEGlyphID glyph, le_int32 pointNumber, LEPoint &point)
const 128 icu::ParagraphLayout *
p;
132 const icu::ParagraphLayout::VisualRun *
vr;
135 ICUVisualRun(
const icu::ParagraphLayout::VisualRun *vr) : vr(vr) { }
137 const Font *GetFont()
const override {
return (
const Font*)vr->getFont(); }
138 int GetGlyphCount()
const override {
return vr->getGlyphCount(); }
139 const GlyphID *GetGlyphs()
const override {
return vr->getGlyphs(); }
140 const float *GetPositions()
const override {
return vr->getPositions(); }
141 int GetLeading()
const override {
return vr->getLeading(); }
142 const int *GetGlyphToCharMap()
const override {
return vr->getGlyphToCharMap(); }
147 icu::ParagraphLayout::Line *
l;
150 ICULine(icu::ParagraphLayout::Line *l) : l(l)
152 for (
int i = 0; i < l->countRuns(); i++) {
153 this->emplace_back(l->getVisualRun(i));
156 ~
ICULine()
override {
delete l; }
158 int GetLeading()
const override {
return l->getLeading(); }
159 int GetWidth()
const override {
return l->getWidth(); }
160 int CountRuns()
const override {
return l->countRuns(); }
163 int GetInternalCharLength(
WChar c)
const override 172 void Reflow()
override { p->reflow(); }
174 std::unique_ptr<const Line> NextLine(
int max_width)
override 176 icu::ParagraphLayout::Line *l = p->nextLine(max_width);
177 return std::unique_ptr<const Line>(l ==
nullptr ? nullptr :
new ICULine(l));
189 static const bool SUPPORTS_RTL =
true;
193 int32 length = buff_end - buff;
199 fontMapping.back().first++;
203 icu::FontRuns runs(fontMapping.size());
204 for (
auto &pair : fontMapping) {
205 runs.add(pair.second, pair.first);
208 LEErrorCode status = LE_NO_ERROR;
211 icu::ParagraphLayout *
p =
new icu::ParagraphLayout(buff, length, &runs,
nullptr,
nullptr,
nullptr,
_current_text_dir ==
TD_RTL ? 1 : 0,
false, status);
212 if (status != LE_NO_ERROR) {
220 static size_t AppendToBuffer(UChar *buff,
const UChar *buffer_last,
WChar c)
224 UErrorCode err = U_ZERO_ERROR;
225 u_strFromUTF32(buff, buffer_last - buff, &length, (UChar32*)&c, 1, &err);
264 const Font *GetFont()
const override;
265 int GetGlyphCount()
const override;
266 const GlyphID *GetGlyphs()
const override;
267 const float *GetPositions()
const override;
268 int GetLeading()
const override;
269 const int *GetGlyphToCharMap()
const override;
275 int GetLeading()
const override;
276 int GetWidth()
const override;
277 int CountRuns()
const override;
280 int GetInternalCharLength(
WChar c)
const override {
return 1; }
288 void Reflow()
override;
289 std::unique_ptr<const Line> NextLine(
int max_width)
override;
300 static const bool SUPPORTS_RTL =
false;
336 font(font), glyph_count(char_count)
343 this->positions[0] = x;
344 this->positions[1] = 0;
347 this->
glyphs[i] = font->fc->MapCharToGlyph(chars[i]);
348 this->positions[2 * i + 2] = this->positions[2 * i] + font->fc->GetGlyphWidth(this->
glyphs[i]);
349 this->positions[2 * i + 3] = 0;
350 this->glyph_to_char[i] = i;
359 this->
glyphs = other.glyphs;
361 other.positions =
nullptr;
362 other.glyph_to_char =
nullptr;
363 other.glyphs =
nullptr;
425 return this->
GetFont()->fc->GetHeight();
435 for (
const auto &run : *
this) {
436 leading =
max(leading, run.GetLeading());
448 if (this->size() == 0)
return 0;
455 const auto &run = this->GetVisualRun(this->CountRuns() - 1);
456 return (
int)run.GetPositions()[run.GetGlyphCount() * 2];
465 return (uint)this->size();
474 return this->at(run);
485 assert(runs.End()[-1].first == length);
507 if (this->
buffer ==
nullptr)
return nullptr;
511 if (*this->
buffer ==
'\0') {
514 l->emplace_back(this->
runs.front().second, this->
buffer, 0, 0);
520 while (iter->first <= offset) {
522 assert(iter != this->
runs.End());
526 const WChar *next_run = this->buffer_begin + iter->first;
529 const WChar *last_space =
nullptr;
530 const WChar *last_char;
541 if (this->
buffer == next_run) {
542 int w = l->GetWidth();
543 l->emplace_back(iter->second, begin, this->buffer - begin, w);
545 assert(iter != this->
runs.End());
547 next_run = this->buffer_begin + iter->first;
550 last_space =
nullptr;
558 if (width > max_width) {
561 if (width == char_width) {
568 if (last_space ==
nullptr) {
578 this->
buffer = last_space + 1;
579 last_char = last_space;
588 if (l->size() == 0 || last_char - begin != 0) {
589 int w = l->GetWidth();
590 l->emplace_back(iter->second, begin, last_char - begin, w);
604 template <
typename T>
611 typename T::CharType *buff = buff_begin;
623 for (; buff < buffer_last;) {
624 WChar c = Utf8Consume(const_cast<const char **>(&str));
625 if (c ==
'\0' || c ==
'\n') {
627 }
else if (c >= SCC_BLUE && c <= SCC_BLACK) {
629 }
else if (c == SCC_PUSH_COLOUR) {
631 }
else if (c == SCC_POP_COLOUR) {
633 }
else if (c >= SCC_FIRST_FONT && c <= SCC_LAST_FONT) {
640 buff += T::AppendToBuffer(buff, buffer_last, c);
644 if (!fontMapping.
Contains(buff - buff_begin)) {
645 fontMapping.
Insert(buff - buff_begin, f);
653 if (!fontMapping.
Contains(buff - buff_begin)) {
654 fontMapping.
Insert(buff - buff_begin, f);
656 line.
layout = T::GetParagraphLayout(buff_begin, buff, fontMapping);
674 const char *lineend = str;
677 if (c ==
'\0' || c ==
'\n')
break;
682 if (line.
layout !=
nullptr) {
690 #if defined(WITH_ICU_LX) || defined(WITH_UNISCRIBE) || defined(WITH_COCOA) 691 const char *old_str = str;
695 GetLayouter<ICUParagraphLayoutFactory>(line, str, state);
696 if (line.layout ==
nullptr) {
697 static bool warned =
false;
699 DEBUG(misc, 0,
"ICU layouter bailed on the font. Falling back to the fallback layouter");
708 #ifdef WITH_UNISCRIBE 709 if (line.layout ==
nullptr) {
710 GetLayouter<UniscribeParagraphLayoutFactory>(line, str, state);
711 if (line.layout ==
nullptr) {
719 if (line.layout ==
nullptr) {
720 GetLayouter<CoreTextParagraphLayoutFactory>(line, str, state);
721 if (line.layout ==
nullptr) {
728 if (line.layout ==
nullptr) {
729 GetLayouter<FallbackParagraphLayoutFactory>(line, str, state);
735 auto l = line.
layout->NextLine(maxw);
736 if (l ==
nullptr)
break;
737 this->push_back(std::move(l));
749 for (
const auto &l : *
this) {
750 d.width = max<uint>(d.width, l->GetWidth());
751 d.height += l->GetLeading();
767 const char *str = this->
string;
771 if (c ==
'\0' || c ==
'\n')
break;
773 index += this->front()->GetInternalCharLength(c);
778 const auto &line = this->front();
781 if (*ch ==
'\0' || *ch ==
'\n') {
782 Point p = { line->GetWidth(), 0 };
787 for (
int run_index = 0; run_index < line->CountRuns(); run_index++) {
790 for (
int i = 0; i < run.GetGlyphCount(); i++) {
792 if ((
size_t)run.GetGlyphToCharMap()[i] == index) {
793 Point p = { (int)run.GetPositions()[i * 2], (int)run.GetPositions()[i * 2 + 1] };
811 const auto &line = this->front();
813 for (
int run_index = 0; run_index < line->CountRuns(); run_index++) {
816 for (
int i = 0; i < run.GetGlyphCount(); i++) {
818 if (run.GetGlyphs()[i] == 0xFFFF)
continue;
820 int begin_x = (int)run.GetPositions()[i * 2];
821 int end_x = (int)run.GetPositions()[i * 2 + 2];
825 size_t index = run.GetGlyphToCharMap()[i];
828 for (
const char *str = this->
string; *str !=
'\0'; ) {
829 if (cur_idx == index)
return str;
831 WChar c = Utf8Consume(&str);
832 cur_idx += line->GetInternalCharLength(c);
847 if (it !=
fonts[size].End())
return it->second;
849 Font *f =
new Font(size, colour);
850 fonts[size].emplace_back(colour, f);
860 for (
auto &pair :
fonts[size]) {
868 #if defined(WITH_UNISCRIBE) 869 UniscribeResetScriptCache(size);
871 #if defined(WITH_COCOA) 893 key.
str.assign(str, len);
Functions related to OTTD's strings.
Functions related to laying out text on Win32.
UChar CharType
Helper for GetLayouter, to get the right type.
int GetWidth() const override
Get the width of this line.
Control codes that are embedded in the translation strings.
FallbackVisualRun(Font *font, const WChar *chars, int glyph_count, int x)
Create the visual run.
Helper class to construct a new FallbackParagraphLayout.
static void GetLayouter(Layouter::LineCacheItem &line, const char *&str, FontState &state)
Helper for getting a ParagraphLayouter of the given type.
const icu::ParagraphLayout::VisualRun * vr
The actual ICU vr.
Functions related to debugging.
void * buffer
Accessed by both ICU's and our ParagraphLayout::nextLine.
FallbackParagraphLayout(WChar *buffer, int length, FontMap &runs)
Create a new paragraph layouter.
std::vector< Pair >::const_iterator Find(const T &key) const
Finds given key in this map.
static LineCache * linecache
Cache of ParagraphLayout lines.
const WChar * buffer_begin
Begin of the buffer.
static bool IsWhitespace(WChar c)
Check whether UNICODE character is whitespace or not, i.e.
Implementation of simple mapping class.
std::string str
Source string of the line (including colour and font size codes).
int * glyph_to_char
The char index of the glyphs.
byte GetCharacterWidth(FontSize size, WChar key)
Return width of character glyph.
int CountRuns() const override
Get the number of runs in this line.
static bool IsTextDirectionChar(WChar c)
Is the given character a text direction character.
static const int DRAW_STRING_BUFFER
Size of the buffer used for drawing strings.
const char * GetCharAtPosition(int x) const
Get the character that is at a position.
size_t Utf8Decode(WChar *c, const char *s)
Decode and consume the next UTF-8 encoded character.
void Reflow() override
Reset the position to the start of the paragraph.
const Font * GetFont() const override
Get the font associated with this run.
int glyph_count
The number of glyphs.
Visual run contains data about the bit of text with the same font.
void MacOSResetScriptCache(FontSize size)
Delete CoreText font reference for a specific font size.
static T max(const T a, const T b)
Returns the maximum of two values.
const float * GetPositions() const override
Get the positions of this run.
Functions related to laying out the texts.
FontMap runs
Accessed by our ParagraphLayout::nextLine.
static Font * GetFont(FontSize size, TextColour colour)
Get a static font instance.
void SetFontSize(FontSize f)
Switch to using a new font f.
icu::ParagraphLayout::Line * l
The actual ICU line.
static bool IsInsideMM(const T x, const size_t min, const size_t max)
Checks if a value is in an interval.
Font * font
The font used to layout these.
Functions related to low-level strings.
A single line worth of VisualRuns.
Visual run contains data about the bit of text with the same font.
Interface to glue fallback and normal layouter into one.
FontMap & runs
The fonts we have to use for this paragraph.
bool Contains(const T &key) const
Tests whether a key is assigned in this map.
Definition of base types and functions in a cross-platform compatible way.
A number of safeguards to prevent using unsafe methods.
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
WChar CharType
Helper for GetLayouter, to get the right type.
Functions related to localized text support on OSX.
void SetColour(TextColour c)
Switch to new colour c.
static int8 Utf8CharLen(WChar c)
Return the length of a UTF-8 encoded character.
Class handling the splitting of a paragraph of text into lines and visual runs.
static size_t AppendToBuffer(WChar *buff, const WChar *buffer_last, WChar c)
Append a wide character to the internal buffer.
bool Insert(const T &key, const U &data)
Adds new item to this map.
int GetLeading() const override
Get the height of the line.
GlyphID * glyphs
The glyphs we're drawing.
static void ResetFontCache(FontSize size)
Reset cached font information.
Font cache for basic fonts.
Dimension GetBounds()
Get the boundaries of this paragraph.
#define DEBUG(name, level,...)
Output a line of debugging information.
float * positions
The positions of the glyphs.
Text drawing parameters, which can change while drawing a line, but are kept between multiple parts o...
int GetGlyphCount() const override
Get the number of glyphs in this run.
~FallbackVisualRun() override
Free all data.
int GetLeading() const override
Get the height of this font.
const ParagraphLayouter::VisualRun & GetVisualRun(int run) const override
Get a specific visual run.
void PopColour()
Switch to and pop the last saved colour on the stack.
TextColour cur_colour
Current text colour.
TextDirection _current_text_dir
Text direction of the currently selected language.
FontSize fontsize
Current font size.
static FontColourMap fonts[FS_END]
Cache of Font instances.
FontSize
Available font sizes.
FontState state_after
Font state after the line.
A single line worth of VisualRuns.
Wrapper for doing layouts with ICU.
void PushColour()
Push the current colour on to the stack.
FontState state_before
Font state at the beginning of the line.
Coordinates of a point in 2D.
static void ReduceLineCache()
Reduce the size of linecache if necessary to prevent infinite growth.
static void ResetLineCache()
Clear line cache.
A single line worth of VisualRuns.
const int * GetGlyphToCharMap() const override
Get the glyph-to-character map for this visual run.
static LineCacheItem & GetCachedParagraphLayout(const char *str, size_t len, const FontState &state)
Get reference to cache item.
Visual run contains data about the bit of text with the same font.
static void free(const void *ptr)
Version of the standard free that accepts const pointers.
icu::ParagraphLayout * p
The actual ICU paragraph layout.
Text is written right-to-left by default.
uint32 GlyphID
Glyphs are characters from a font.
Helper class to construct a new ICUParagraphLayout.
std::unique_ptr< const Line > NextLine(int max_width) override
Construct a new line with a maximum width.
ParagraphLayouter * layout
Layout of the line.
uint32 WChar
Type for wide characters, i.e.
const WChar * buffer
The current location in the buffer.
Layouter(const char *str, int maxw=INT32_MAX, TextColour colour=TC_FROMSTRING, FontSize fontsize=FS_NORMAL)
Create a new layouter.
Dimensions (a width and height) of a rectangle in 2D.
const GlyphID * GetGlyphs() const override
Get the glyphs of this run.
Point GetCharPosition(const char *ch) const
Get the position of a character in the layout.
const char * string
Pointer to the original string.
static ParagraphLayouter * GetParagraphLayout(WChar *buff, WChar *buff_end, FontMap &fontMapping)
Get the actual ParagraphLayout for the given buffer.