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;
133 ICUVisualRun(
const icu::ParagraphLayout::VisualRun *vr) : vr(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;
148 ICULine(icu::ParagraphLayout::Line *l) : l(l)
150 for (
int i = 0; i < l->countRuns(); i++) {
151 this->emplace_back(l->getVisualRun(i));
154 ~
ICULine()
override {
delete l; }
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));
187 static const bool SUPPORTS_RTL =
true;
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;
263 int GetGlyphCount()
const override;
264 const GlyphID *GetGlyphs()
const override;
265 const float *GetPositions()
const override;
266 int GetLeading()
const override;
267 const int *GetGlyphToCharMap()
const override;
273 int GetLeading()
const override;
274 int GetWidth()
const override;
275 int CountRuns()
const override;
278 int GetInternalCharLength(
WChar c)
const override {
return 1; }
286 void Reflow()
override;
287 std::unique_ptr<const Line> NextLine(
int max_width)
override;
298 static const bool SUPPORTS_RTL =
false;
334 font(font), glyph_count(char_count)
341 this->positions[0] = x;
342 this->positions[1] = 0;
345 this->
glyphs[i] = font->fc->MapCharToGlyph(chars[i]);
346 this->positions[2 * i + 2] = this->positions[2 * i] + font->fc->GetGlyphWidth(this->
glyphs[i]);
347 this->positions[2 * i + 3] = 0;
348 this->glyph_to_char[i] = i;
357 this->
glyphs = other.glyphs;
359 other.positions =
nullptr;
360 other.glyph_to_char =
nullptr;
361 other.glyphs =
nullptr;
423 return this->
GetFont()->fc->GetHeight();
433 for (
const auto &run : *
this) {
434 leading =
max(leading, run.GetLeading());
446 if (this->size() == 0)
return 0;
453 const auto &run = this->GetVisualRun(this->CountRuns() - 1);
454 return (
int)run.GetPositions()[run.GetGlyphCount() * 2];
463 return (uint)this->size();
472 return this->at(run);
483 assert(runs.End()[-1].first == length);
505 if (this->
buffer ==
nullptr)
return nullptr;
509 if (*this->
buffer ==
'\0') {
512 l->emplace_back(this->
runs.front().second, this->
buffer, 0, 0);
518 while (iter->first <= offset) {
520 assert(iter != this->
runs.End());
524 const WChar *next_run = this->buffer_begin + iter->first;
527 const WChar *last_space =
nullptr;
528 const WChar *last_char;
539 if (this->
buffer == next_run) {
540 int w = l->GetWidth();
541 l->emplace_back(iter->second, begin, this->buffer - begin, w);
543 assert(iter != this->
runs.End());
545 next_run = this->buffer_begin + iter->first;
548 last_space =
nullptr;
556 if (width > max_width) {
559 if (width == char_width) {
566 if (last_space ==
nullptr) {
576 this->
buffer = last_space + 1;
577 last_char = last_space;
586 if (l->size() == 0 || last_char - begin != 0) {
587 int w = l->GetWidth();
588 l->emplace_back(iter->second, begin, last_char - begin, w);
602 template <
typename T>
609 typename T::CharType *buff = buff_begin;
621 for (; buff < buffer_last;) {
622 WChar c = Utf8Consume(const_cast<const char **>(&str));
623 if (c ==
'\0' || c ==
'\n') {
625 }
else if (c >= SCC_BLUE && c <= SCC_BLACK) {
627 }
else if (c == SCC_PUSH_COLOUR) {
629 }
else if (c == SCC_POP_COLOUR) {
631 }
else if (c >= SCC_FIRST_FONT && c <= SCC_LAST_FONT) {
638 buff += T::AppendToBuffer(buff, buffer_last, c);
642 if (!fontMapping.
Contains(buff - buff_begin)) {
643 fontMapping.
Insert(buff - buff_begin, f);
651 if (!fontMapping.
Contains(buff - buff_begin)) {
652 fontMapping.
Insert(buff - buff_begin, f);
654 line.
layout = T::GetParagraphLayout(buff_begin, buff, fontMapping);
672 const char *lineend = str;
675 if (c ==
'\0' || c ==
'\n')
break;
680 if (line.
layout !=
nullptr) {
688 #if defined(WITH_ICU_LX) || defined(WITH_UNISCRIBE) || defined(WITH_COCOA) 689 const char *old_str = str;
693 GetLayouter<ICUParagraphLayoutFactory>(line, str, state);
694 if (line.layout ==
nullptr) {
695 static bool warned =
false;
697 DEBUG(misc, 0,
"ICU layouter bailed on the font. Falling back to the fallback layouter");
706 #ifdef WITH_UNISCRIBE 707 if (line.layout ==
nullptr) {
708 GetLayouter<UniscribeParagraphLayoutFactory>(line, str, state);
709 if (line.layout ==
nullptr) {
717 if (line.layout ==
nullptr) {
718 GetLayouter<CoreTextParagraphLayoutFactory>(line, str, state);
719 if (line.layout ==
nullptr) {
726 if (line.layout ==
nullptr) {
727 GetLayouter<FallbackParagraphLayoutFactory>(line, str, state);
733 auto l = line.
layout->NextLine(maxw);
734 if (l ==
nullptr)
break;
735 this->push_back(std::move(l));
747 for (
const auto &l : *
this) {
748 d.width = max<uint>(d.width, l->GetWidth());
749 d.height += l->GetLeading();
765 const char *str = this->
string;
769 if (c ==
'\0' || c ==
'\n')
break;
771 index += this->front()->GetInternalCharLength(c);
776 const auto &line = this->front();
779 if (*ch ==
'\0' || *ch ==
'\n') {
780 Point p = { line->GetWidth(), 0 };
785 for (
int run_index = 0; run_index < line->CountRuns(); run_index++) {
788 for (
int i = 0; i < run.GetGlyphCount(); i++) {
790 if ((
size_t)run.GetGlyphToCharMap()[i] == index) {
791 Point p = { (int)run.GetPositions()[i * 2], (int)run.GetPositions()[i * 2 + 1] };
809 const auto &line = this->front();
811 for (
int run_index = 0; run_index < line->CountRuns(); run_index++) {
814 for (
int i = 0; i < run.GetGlyphCount(); i++) {
816 if (run.GetGlyphs()[i] == 0xFFFF)
continue;
818 int begin_x = (int)run.GetPositions()[i * 2];
819 int end_x = (int)run.GetPositions()[i * 2 + 2];
823 size_t index = run.GetGlyphToCharMap()[i];
826 for (
const char *str = this->
string; *str !=
'\0'; ) {
827 if (cur_idx == index)
return str;
829 WChar c = Utf8Consume(&str);
830 cur_idx += line->GetInternalCharLength(c);
845 if (it !=
fonts[size].End())
return it->second;
847 Font *f =
new Font(size, colour);
848 fonts[size].emplace_back(colour, f);
858 for (
auto &pair :
fonts[size]) {
866 #if defined(WITH_UNISCRIBE) 867 UniscribeResetScriptCache(size);
869 #if defined(WITH_COCOA) 891 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.