OpenTTD
gfx_layout.cpp
Go to the documentation of this file.
1 /* $Id: gfx_layout.cpp 27367 2015-08-09 12:33:27Z rubidium $ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
6  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8  */
9 
12 #include "stdafx.h"
13 #include "gfx_layout.h"
14 #include "string_func.h"
15 #include "strings_func.h"
16 #include "debug.h"
17 
18 #include "table/control_codes.h"
19 
20 #ifdef WITH_ICU_LAYOUT
21 #include <unicode/ustring.h>
22 #endif /* WITH_ICU_LAYOUT */
23 
24 #include "safeguards.h"
25 
26 
28 Layouter::LineCache *Layouter::linecache;
29 
32 
33 
39 Font::Font(FontSize size, TextColour colour) :
40  fc(FontCache::Get(size)), colour(colour)
41 {
42  assert(size < FS_END);
43 }
44 
45 #ifdef WITH_ICU_LAYOUT
46 /* Implementation details of LEFontInstance */
47 
48 le_int32 Font::getUnitsPerEM() const
49 {
50  return this->fc->GetUnitsPerEM();
51 }
52 
53 le_int32 Font::getAscent() const
54 {
55  return this->fc->GetAscender();
56 }
57 
58 le_int32 Font::getDescent() const
59 {
60  return -this->fc->GetDescender();
61 }
62 
63 le_int32 Font::getLeading() const
64 {
65  return this->fc->GetHeight();
66 }
67 
68 float Font::getXPixelsPerEm() const
69 {
70  return (float)this->fc->GetHeight();
71 }
72 
73 float Font::getYPixelsPerEm() const
74 {
75  return (float)this->fc->GetHeight();
76 }
77 
78 float Font::getScaleFactorX() const
79 {
80  return 1.0f;
81 }
82 
83 float Font::getScaleFactorY() const
84 {
85  return 1.0f;
86 }
87 
88 const void *Font::getFontTable(LETag tableTag) const
89 {
90  size_t length;
91  return this->getFontTable(tableTag, length);
92 }
93 
94 const void *Font::getFontTable(LETag tableTag, size_t &length) const
95 {
96  return this->fc->GetFontTable(tableTag, length);
97 }
98 
99 LEGlyphID Font::mapCharToGlyph(LEUnicode32 ch) const
100 {
101  if (IsTextDirectionChar(ch)) return 0;
102  return this->fc->MapCharToGlyph(ch);
103 }
104 
105 void Font::getGlyphAdvance(LEGlyphID glyph, LEPoint &advance) const
106 {
107  advance.fX = glyph == 0xFFFF ? 0 : this->fc->GetGlyphWidth(glyph);
108  advance.fY = 0;
109 }
110 
111 le_bool Font::getGlyphPoint(LEGlyphID glyph, le_int32 pointNumber, LEPoint &point) const
112 {
113  return FALSE;
114 }
115 
116 static size_t AppendToBuffer(UChar *buff, const UChar *buffer_last, WChar c)
117 {
118  /* Transform from UTF-32 to internal ICU format of UTF-16. */
119  int32 length = 0;
120  UErrorCode err = U_ZERO_ERROR;
121  u_strFromUTF32(buff, buffer_last - buff, &length, (UChar32*)&c, 1, &err);
122  return length;
123 }
124 
128 class ICUParagraphLayout : public AutoDeleteSmallVector<ParagraphLayouter::Line *, 4>, public ParagraphLayouter {
129  ParagraphLayout *p;
130 public:
132  typedef UChar CharType;
134  static const bool SUPPORTS_RTL = true;
135 
138  const ParagraphLayout::VisualRun *vr;
139 
140  public:
141  ICUVisualRun(const ParagraphLayout::VisualRun *vr) : vr(vr) { }
142 
143  const Font *GetFont() const { return (const Font*)vr->getFont(); }
144  int GetGlyphCount() const { return vr->getGlyphCount(); }
145  const GlyphID *GetGlyphs() const { return vr->getGlyphs(); }
146  const float *GetPositions() const { return vr->getPositions(); }
147  int GetLeading() const { return vr->getLeading(); }
148  const int *GetGlyphToCharMap() const { return vr->getGlyphToCharMap(); }
149  };
150 
152  class ICULine : public AutoDeleteSmallVector<ICUVisualRun *, 4>, public ParagraphLayouter::Line {
153  ParagraphLayout::Line *l;
154 
155  public:
156  ICULine(ParagraphLayout::Line *l) : l(l)
157  {
158  for (int i = 0; i < l->countRuns(); i++) {
159  *this->Append() = new ICUVisualRun(l->getVisualRun(i));
160  }
161  }
162  ~ICULine() { delete l; }
163 
164  int GetLeading() const { return l->getLeading(); }
165  int GetWidth() const { return l->getWidth(); }
166  int CountRuns() const { return l->countRuns(); }
167  const ParagraphLayouter::VisualRun *GetVisualRun(int run) const { return *this->Get(run); }
168 
169  int GetInternalCharLength(WChar c) const
170  {
171  /* ICU uses UTF-16 internally which means we need to account for surrogate pairs. */
172  return Utf8CharLen(c) < 4 ? 1 : 2;
173  }
174  };
175 
176  ICUParagraphLayout(ParagraphLayout *p) : p(p) { }
177  ~ICUParagraphLayout() { delete p; }
178  void Reflow() { p->reflow(); }
179 
180  ParagraphLayouter::Line *NextLine(int max_width)
181  {
182  ParagraphLayout::Line *l = p->nextLine(max_width);
183  return l == NULL ? NULL : new ICULine(l);
184  }
185 };
186 
187 static ParagraphLayouter *GetParagraphLayout(UChar *buff, UChar *buff_end, FontMap &fontMapping)
188 {
189  int32 length = buff_end - buff;
190 
191  if (length == 0) {
192  /* ICU's ParagraphLayout cannot handle empty strings, so fake one. */
193  buff[0] = ' ';
194  length = 1;
195  fontMapping.End()[-1].first++;
196  }
197 
198  /* Fill ICU's FontRuns with the right data. */
199  FontRuns runs(fontMapping.Length());
200  for (FontMap::iterator iter = fontMapping.Begin(); iter != fontMapping.End(); iter++) {
201  runs.add(iter->second, iter->first);
202  }
203 
204  LEErrorCode status = LE_NO_ERROR;
205  /* ParagraphLayout does not copy "buff", so it must stay valid.
206  * "runs" is copied according to the ICU source, but the documentation does not specify anything, so this might break somewhen. */
207  ParagraphLayout *p = new ParagraphLayout(buff, length, &runs, NULL, NULL, NULL, _current_text_dir == TD_RTL ? UBIDI_DEFAULT_RTL : UBIDI_DEFAULT_LTR, false, status);
208  if (status != LE_NO_ERROR) {
209  delete p;
210  return NULL;
211  }
212 
213  return new ICUParagraphLayout(p);
214 }
215 
216 #endif /* WITH_ICU_LAYOUT */
217 
218 /*** Paragraph layout ***/
238 public:
240  typedef WChar CharType;
242  static const bool SUPPORTS_RTL = false;
243 
246  Font *font;
248  float *positions;
251 
252  public:
253  FallbackVisualRun(Font *font, const WChar *chars, int glyph_count, int x);
255  const Font *GetFont() const;
256  int GetGlyphCount() const;
257  const GlyphID *GetGlyphs() const;
258  const float *GetPositions() const;
259  int GetLeading() const;
260  const int *GetGlyphToCharMap() const;
261  };
262 
264  class FallbackLine : public AutoDeleteSmallVector<FallbackVisualRun *, 4>, public ParagraphLayouter::Line {
265  public:
266  int GetLeading() const;
267  int GetWidth() const;
268  int CountRuns() const;
269  const ParagraphLayouter::VisualRun *GetVisualRun(int run) const;
270 
271  int GetInternalCharLength(WChar c) const { return 1; }
272  };
273 
275  const WChar *buffer;
277 
278  FallbackParagraphLayout(WChar *buffer, int length, FontMap &runs);
279  void Reflow();
280  const ParagraphLayouter::Line *NextLine(int max_width);
281 };
282 
290 FallbackParagraphLayout::FallbackVisualRun::FallbackVisualRun(Font *font, const WChar *chars, int char_count, int x) :
291  font(font), glyph_count(char_count)
292 {
293  this->glyphs = MallocT<GlyphID>(this->glyph_count);
294  this->glyph_to_char = MallocT<int>(this->glyph_count);
295 
296  /* Positions contains the location of the begin of each of the glyphs, and the end of the last one. */
297  this->positions = MallocT<float>(this->glyph_count * 2 + 2);
298  this->positions[0] = x;
299  this->positions[1] = 0;
300 
301  for (int i = 0; i < this->glyph_count; i++) {
302  this->glyphs[i] = font->fc->MapCharToGlyph(chars[i]);
303  this->positions[2 * i + 2] = this->positions[2 * i] + font->fc->GetGlyphWidth(this->glyphs[i]);
304  this->positions[2 * i + 3] = 0;
305  this->glyph_to_char[i] = i;
306  }
307 }
308 
311 {
312  free(this->positions);
313  free(this->glyph_to_char);
314  free(this->glyphs);
315 }
316 
322 {
323  return this->font;
324 }
325 
331 {
332  return this->glyph_count;
333 }
334 
340 {
341  return this->glyphs;
342 }
343 
349 {
350  return this->positions;
351 }
352 
358 {
359  return this->glyph_to_char;
360 }
361 
367 {
368  return this->GetFont()->fc->GetHeight();
369 }
370 
376 {
377  int leading = 0;
378  for (const FallbackVisualRun * const *run = this->Begin(); run != this->End(); run++) {
379  leading = max(leading, (*run)->GetLeading());
380  }
381 
382  return leading;
383 }
384 
390 {
391  if (this->Length() == 0) return 0;
392 
393  /*
394  * The last X position of a run contains is the end of that run.
395  * Since there is no left-to-right support, taking this value of
396  * the last run gives us the end of the line and thus the width.
397  */
398  const ParagraphLayouter::VisualRun *run = this->GetVisualRun(this->CountRuns() - 1);
399  return (int)run->GetPositions()[run->GetGlyphCount() * 2];
400 }
401 
407 {
408  return this->Length();
409 }
410 
416 {
417  return *this->Get(run);
418 }
419 
426 FallbackParagraphLayout::FallbackParagraphLayout(WChar *buffer, int length, FontMap &runs) : buffer_begin(buffer), buffer(buffer), runs(runs)
427 {
428  assert(runs.End()[-1].first == length);
429 }
430 
435 {
436  this->buffer = this->buffer_begin;
437 }
438 
445 {
446  /* Simple idea:
447  * - split a line at a newline character, or at a space where we can break a line.
448  * - split for a visual run whenever a new line happens, or the font changes.
449  */
450  if (this->buffer == NULL) return NULL;
451 
452  FallbackLine *l = new FallbackLine();
453 
454  if (*this->buffer == '\0') {
455  /* Only a newline. */
456  this->buffer = NULL;
457  *l->Append() = new FallbackVisualRun(this->runs.Begin()->second, this->buffer, 0, 0);
458  return l;
459  }
460 
461  const WChar *begin = this->buffer;
462  const WChar *last_space = NULL;
463  const WChar *last_char = begin;
464  int width = 0;
465 
466  int offset = this->buffer - this->buffer_begin;
467  FontMap::iterator iter = this->runs.Begin();
468  while (iter->first <= offset) {
469  iter++;
470  assert(iter != this->runs.End());
471  }
472 
473  const FontCache *fc = iter->second->fc;
474  const WChar *next_run = this->buffer_begin + iter->first;
475 
476  for (;;) {
477  WChar c = *this->buffer;
478  last_char = this->buffer;
479 
480  if (c == '\0') {
481  this->buffer = NULL;
482  break;
483  }
484 
485  if (this->buffer == next_run) {
486  int w = l->GetWidth();
487  *l->Append() = new FallbackVisualRun(iter->second, begin, this->buffer - begin, w);
488  iter++;
489  assert(iter != this->runs.End());
490 
491  next_run = this->buffer_begin + iter->first;
492  begin = this->buffer;
493 
494  last_space = NULL;
495  }
496 
497  if (IsWhitespace(c)) last_space = this->buffer;
498 
499  if (IsPrintable(c) && !IsTextDirectionChar(c)) {
500  int char_width = GetCharacterWidth(fc->GetSize(), c);
501  width += char_width;
502  if (width > max_width) {
503  /* The string is longer than maximum width so we need to decide
504  * what to do with it. */
505  if (width == char_width) {
506  /* The character is wider than allowed width; don't know
507  * what to do with this case... bail out! */
508  this->buffer = NULL;
509  return l;
510  }
511 
512  if (last_space == NULL) {
513  /* No space has been found. Just terminate at our current
514  * location. This usually happens for languages that do not
515  * require spaces in strings, like Chinese, Japanese and
516  * Korean. For other languages terminating mid-word might
517  * not be the best, but terminating the whole string instead
518  * of continuing the word at the next line is worse. */
519  last_char = this->buffer;
520  } else {
521  /* A space is found; perfect place to terminate */
522  this->buffer = last_space + 1;
523  last_char = last_space;
524  }
525  break;
526  }
527  }
528 
529  this->buffer++;
530  }
531 
532  if (l->Length() == 0 || last_char - begin != 0) {
533  int w = l->GetWidth();
534  *l->Append() = new FallbackVisualRun(iter->second, begin, last_char - begin, w);
535  }
536  return l;
537 }
538 
546 static size_t AppendToBuffer(WChar *buff, const WChar *buffer_last, WChar c)
547 {
548  *buff = c;
549  return 1;
550 }
551 
559 static FallbackParagraphLayout *GetParagraphLayout(WChar *buff, WChar *buff_end, FontMap &fontMapping)
560 {
561  return new FallbackParagraphLayout(buff, buff_end - buff, fontMapping);
562 }
563 
573 template <typename T>
574 static inline void GetLayouter(Layouter::LineCacheItem &line, const char *&str, FontState &state)
575 {
576  if (line.buffer != NULL) free(line.buffer);
577 
578  typename T::CharType *buff_begin = MallocT<typename T::CharType>(DRAW_STRING_BUFFER);
579  const typename T::CharType *buffer_last = buff_begin + DRAW_STRING_BUFFER;
580  typename T::CharType *buff = buff_begin;
581  FontMap &fontMapping = line.runs;
582  Font *f = Layouter::GetFont(state.fontsize, state.cur_colour);
583 
584  line.buffer = buff_begin;
585 
586  /*
587  * Go through the whole string while adding Font instances to the font map
588  * whenever the font changes, and convert the wide characters into a format
589  * usable by ParagraphLayout.
590  */
591  for (; buff < buffer_last;) {
592  WChar c = Utf8Consume(const_cast<const char **>(&str));
593  if (c == '\0' || c == '\n') {
594  break;
595  } else if (c >= SCC_BLUE && c <= SCC_BLACK) {
596  state.SetColour((TextColour)(c - SCC_BLUE));
597  } else if (c == SCC_PREVIOUS_COLOUR) { // Revert to the previous colour.
598  state.SetPreviousColour();
599  } else if (c == SCC_TINYFONT) {
600  state.SetFontSize(FS_SMALL);
601  } else if (c == SCC_BIGFONT) {
602  state.SetFontSize(FS_LARGE);
603  } else {
604  /* Filter out text direction characters that shouldn't be drawn, and
605  * will not be handled in the fallback non ICU case because they are
606  * mostly needed for RTL languages which need more ICU support. */
607  if (!T::SUPPORTS_RTL && IsTextDirectionChar(c)) continue;
608  buff += AppendToBuffer(buff, buffer_last, c);
609  continue;
610  }
611 
612  if (!fontMapping.Contains(buff - buff_begin)) {
613  fontMapping.Insert(buff - buff_begin, f);
614  }
615  f = Layouter::GetFont(state.fontsize, state.cur_colour);
616  }
617 
618  /* Better safe than sorry. */
619  *buff = '\0';
620 
621  if (!fontMapping.Contains(buff - buff_begin)) {
622  fontMapping.Insert(buff - buff_begin, f);
623  }
624  line.layout = GetParagraphLayout(buff_begin, buff, fontMapping);
625  line.state_after = state;
626 }
627 
635 Layouter::Layouter(const char *str, int maxw, TextColour colour, FontSize fontsize) : string(str)
636 {
637  FontState state(colour, fontsize);
638  WChar c = 0;
639 
640  do {
641  /* Scan string for end of line */
642  const char *lineend = str;
643  for (;;) {
644  size_t len = Utf8Decode(&c, lineend);
645  if (c == '\0' || c == '\n') break;
646  lineend += len;
647  }
648 
649  LineCacheItem& line = GetCachedParagraphLayout(str, lineend - str, state);
650  if (line.layout != NULL) {
651  /* Line is in cache */
652  str = lineend + 1;
653  state = line.state_after;
654  line.layout->Reflow();
655  } else {
656  /* Line is new, layout it */
657 #ifdef WITH_ICU_LAYOUT
658  FontState old_state = state;
659  const char *old_str = str;
660 
661  GetLayouter<ICUParagraphLayout>(line, str, state);
662  if (line.layout == NULL) {
663  static bool warned = false;
664  if (!warned) {
665  DEBUG(misc, 0, "ICU layouter bailed on the font. Falling back to the fallback layouter");
666  warned = true;
667  }
668 
669  state = old_state;
670  str = old_str;
671  GetLayouter<FallbackParagraphLayout>(line, str, state);
672  }
673 #else
674  GetLayouter<FallbackParagraphLayout>(line, str, state);
675 #endif
676  }
677 
678  /* Copy all lines into a local cache so we can reuse them later on more easily. */
679  const ParagraphLayouter::Line *l;
680  while ((l = line.layout->NextLine(maxw)) != NULL) {
681  *this->Append() = l;
682  }
683 
684  } while (c != '\0');
685 }
686 
692 {
693  Dimension d = { 0, 0 };
694  for (const ParagraphLayouter::Line **l = this->Begin(); l != this->End(); l++) {
695  d.width = max<uint>(d.width, (*l)->GetWidth());
696  d.height += (*l)->GetLeading();
697  }
698  return d;
699 }
700 
707 Point Layouter::GetCharPosition(const char *ch) const
708 {
709  /* Find the code point index which corresponds to the char
710  * pointer into our UTF-8 source string. */
711  size_t index = 0;
712  const char *str = this->string;
713  while (str < ch) {
714  WChar c;
715  size_t len = Utf8Decode(&c, str);
716  if (c == '\0' || c == '\n') break;
717  str += len;
718  index += (*this->Begin())->GetInternalCharLength(c);
719  }
720 
721  if (str == ch) {
722  /* Valid character. */
723  const ParagraphLayouter::Line *line = *this->Begin();
724 
725  /* Pointer to the end-of-string/line marker? Return total line width. */
726  if (*ch == '\0' || *ch == '\n') {
727  Point p = { line->GetWidth(), 0 };
728  return p;
729  }
730 
731  /* Scan all runs until we've found our code point index. */
732  for (int run_index = 0; run_index < line->CountRuns(); run_index++) {
733  const ParagraphLayouter::VisualRun *run = line->GetVisualRun(run_index);
734 
735  for (int i = 0; i < run->GetGlyphCount(); i++) {
736  /* Matching glyph? Return position. */
737  if ((size_t)run->GetGlyphToCharMap()[i] == index) {
738  Point p = { (int)run->GetPositions()[i * 2], (int)run->GetPositions()[i * 2 + 1] };
739  return p;
740  }
741  }
742  }
743  }
744 
745  Point p = { 0, 0 };
746  return p;
747 }
748 
754 const char *Layouter::GetCharAtPosition(int x) const
755 {
756  const ParagraphLayouter::Line *line = *this->Begin();
757 
758  for (int run_index = 0; run_index < line->CountRuns(); run_index++) {
759  const ParagraphLayouter::VisualRun *run = line->GetVisualRun(run_index);
760 
761  for (int i = 0; i < run->GetGlyphCount(); i++) {
762  /* Not a valid glyph (empty). */
763  if (run->GetGlyphs()[i] == 0xFFFF) continue;
764 
765  int begin_x = (int)run->GetPositions()[i * 2];
766  int end_x = (int)run->GetPositions()[i * 2 + 2];
767 
768  if (IsInsideMM(x, begin_x, end_x)) {
769  /* Found our glyph, now convert to UTF-8 string index. */
770  size_t index = run->GetGlyphToCharMap()[i];
771 
772  size_t cur_idx = 0;
773  for (const char *str = this->string; *str != '\0'; ) {
774  if (cur_idx == index) return str;
775 
776  WChar c = Utf8Consume(&str);
777  cur_idx += line->GetInternalCharLength(c);
778  }
779  }
780  }
781  }
782 
783  return NULL;
784 }
785 
790 {
791  FontColourMap::iterator it = fonts[size].Find(colour);
792  if (it != fonts[size].End()) return it->second;
793 
794  Font *f = new Font(size, colour);
795  *fonts[size].Append() = FontColourMap::Pair(colour, f);
796  return f;
797 }
798 
804 {
805  for (FontColourMap::iterator it = fonts[size].Begin(); it != fonts[size].End(); ++it) {
806  delete it->second;
807  }
808  fonts[size].Clear();
809 
810  /* We must reset the linecache since it references the just freed fonts */
811  ResetLineCache();
812 }
813 
822 Layouter::LineCacheItem &Layouter::GetCachedParagraphLayout(const char *str, size_t len, const FontState &state)
823 {
824  if (linecache == NULL) {
825  /* Create linecache on first access to avoid trouble with initialisation order of static variables. */
826  linecache = new LineCache();
827  }
828 
829  LineCacheKey key;
830  key.state_before = state;
831  key.str.assign(str, len);
832  return (*linecache)[key];
833 }
834 
839 {
840  if (linecache != NULL) linecache->clear();
841 }
842 
847 {
848  if (linecache != NULL) {
849  /* TODO LRU cache would be fancy, but not exactly necessary */
850  if (linecache->size() > 4096) ResetLineCache();
851  }
852 }
Functions related to OTTD&#39;s strings.
const ParagraphLayouter::Line * NextLine(int max_width)
Construct a new line with a maximum width.
Definition: gfx_layout.cpp:444
bool Contains(const T &key) const
Tests whether a key is assigned in this map.
Control codes that are embedded in the translation strings.
const Pair * Find(const T &key) const
Finds given key in this map.
FallbackVisualRun(Font *font, const WChar *chars, int glyph_count, int x)
Create the visual run.
Definition: gfx_layout.cpp:290
static bool IsInsideMM(const T x, const uint min, const uint max)
Checks if a value is in an interval.
Definition: math_func.hpp:266
static void GetLayouter(Layouter::LineCacheItem &line, const char *&str, FontState &state)
Helper for getting a ParagraphLayouter of the given type.
Definition: gfx_layout.cpp:574
Functions related to debugging.
void * buffer
Accessed by both ICU&#39;s and our ParagraphLayout::nextLine.
Definition: gfx_layout.h:160
FallbackParagraphLayout(WChar *buffer, int length, FontMap &runs)
Create a new paragraph layouter.
Definition: gfx_layout.cpp:426
static LineCache * linecache
Cache of ParagraphLayout lines.
Definition: gfx_layout.h:171
const WChar * buffer_begin
Begin of the buffer.
Definition: gfx_layout.cpp:274
static const bool SUPPORTS_RTL
Helper for GetLayouter, to get whether the layouter supports RTL.
Definition: gfx_layout.cpp:134
static bool IsWhitespace(WChar c)
Check whether UNICODE character is whitespace or not, i.e.
Definition: string_func.h:242
Implementation of simple mapping class.
std::string str
Source string of the line (including colour and font size codes).
Definition: gfx_layout.h:145
int GetWidth() const
Get the width of this line.
Definition: gfx_layout.cpp:389
Switch to large font.
Definition: control_codes.h:31
Key into the linecache.
Definition: gfx_layout.h:143
void SetPreviousColour()
Switch to previous colour.
Definition: gfx_layout.h:53
void Clear()
Remove all items from the list.
int * glyph_to_char
The char index of the glyphs.
Definition: gfx_layout.cpp:249
byte GetCharacterWidth(FontSize size, WChar key)
Return width of character glyph.
Definition: gfx.cpp:1148
const T * Begin() const
Get the pointer to the first item (const)
int GetLeading() const
Get the height of this font.
Definition: gfx_layout.cpp:366
static bool IsTextDirectionChar(WChar c)
Is the given character a text direction character.
Definition: string_func.h:210
bool Insert(const T &key, const U &data)
Adds new item to this map.
static const int DRAW_STRING_BUFFER
Size of the buffer used for drawing strings.
Definition: gfx_func.h:87
const char * GetCharAtPosition(int x) const
Get the character that is at a position.
Definition: gfx_layout.cpp:754
size_t Utf8Decode(WChar *c, const char *s)
Decode and consume the next UTF-8 encoded character.
Definition: string.cpp:437
const int * GetGlyphToCharMap() const
Get the glyph-to-character map for this visual run.
Definition: gfx_layout.cpp:357
int glyph_count
The number of glyphs.
Definition: gfx_layout.cpp:250
Visual run contains data about the bit of text with the same font.
Definition: gfx_layout.h:108
ParagraphLayout::Line * l
The actual ICU line.
Definition: gfx_layout.cpp:153
static T max(const T a, const T b)
Returns the maximum of two values.
Definition: math_func.hpp:26
Functions related to laying out the texts.
FontMap runs
Accessed by our ParagraphLayout::nextLine.
Definition: gfx_layout.h:161
const T * End() const
Get the pointer behind the last valid item (const)
static size_t AppendToBuffer(WChar *buff, const WChar *buffer_last, WChar c)
Appand a wide character to the internal buffer.
Definition: gfx_layout.cpp:546
static Font * GetFont(FontSize size, TextColour colour)
Get a static font instance.
Definition: gfx_layout.cpp:789
void SetFontSize(FontSize f)
Switch to using a new font f.
Definition: gfx_layout.h:62
ParagraphLayouter::Line * * Append(uint to_add=1)
Append an item and return it.
ParagraphLayout * p
The actual ICU paragraph layout.
Definition: gfx_layout.cpp:129
Font * font
The font used to layout these.
Definition: gfx_layout.cpp:246
Functions related to low-level strings.
A single line worth of VisualRuns.
Definition: gfx_layout.h:120
uint Length() const
Get the number of items in the list.
Visual run contains data about the bit of text with the same font.
Definition: gfx_layout.cpp:137
Simple pair of data.
Interface to glue fallback and normal layouter into one.
Definition: gfx_layout.h:103
FontMap & runs
The fonts we have to use for this paragraph.
Definition: gfx_layout.cpp:276
Simple vector template class, with automatic delete.
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...
Definition: gfx_type.h:247
const ParagraphLayouter::VisualRun * GetVisualRun(int run) const
Get a specific visual run.
Definition: gfx_layout.cpp:415
void Reflow()
Reset the position to the start of the paragraph.
Definition: gfx_layout.cpp:434
void SetColour(TextColour c)
Switch to new colour c.
Definition: gfx_layout.h:45
const float * GetPositions() const
Get the positions of this run.
Definition: gfx_layout.cpp:348
static int8 Utf8CharLen(WChar c)
Return the length of a UTF-8 encoded character.
Definition: string_func.h:99
Class handling the splitting of a paragraph of text into lines and visual runs.
Definition: gfx_layout.cpp:237
int GetLeading() const
Get the height of the line.
Definition: gfx_layout.cpp:375
GlyphID * glyphs
The glyphs we&#39;re drawing.
Definition: gfx_layout.cpp:247
static void ResetFontCache(FontSize size)
Reset cached font information.
Definition: gfx_layout.cpp:803
Font cache for basic fonts.
Definition: fontcache.h:23
Dimension GetBounds()
Get the boundaries of this paragraph.
Definition: gfx_layout.cpp:691
#define DEBUG(name, level,...)
Output a line of debugging information.
Definition: debug.h:39
float * positions
The positions of the glyphs.
Definition: gfx_layout.cpp:248
Text drawing parameters, which can change while drawing a line, but are kept between multiple parts o...
Definition: gfx_layout.h:33
const ParagraphLayout::VisualRun * vr
The actual ICU vr.
Definition: gfx_layout.cpp:138
int CountRuns() const
Get the number of runs in this line.
Definition: gfx_layout.cpp:406
TextColour cur_colour
Current text colour.
Definition: gfx_layout.h:35
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition: strings.cpp:52
FontSize fontsize
Current font size.
Definition: gfx_layout.h:34
static FontColourMap fonts[FS_END]
Cache of Font instances.
Definition: gfx_layout.h:176
FontSize
Available font sizes.
Definition: gfx_type.h:203
FontState state_after
Font state after the line.
Definition: gfx_layout.h:163
A single line worth of VisualRuns.
Definition: gfx_layout.cpp:152
Wrapper for doing layouts with ICU.
Definition: gfx_layout.cpp:128
WChar CharType
Helper for GetLayouter, to get the right type.
Definition: gfx_layout.cpp:240
FontState state_before
Font state at the beginning of the line.
Definition: gfx_layout.h:144
Coordinates of a point in 2D.
static void ReduceLineCache()
Reduce the size of linecache if necessary to prevent infinite growth.
Definition: gfx_layout.cpp:846
Index of the small font in the font tables.
Definition: gfx_type.h:205
static void ResetLineCache()
Clear line cache.
Definition: gfx_layout.cpp:838
A single line worth of VisualRuns.
Definition: gfx_layout.cpp:264
static LineCacheItem & GetCachedParagraphLayout(const char *str, size_t len, const FontState &state)
Get reference to cache item.
Definition: gfx_layout.cpp:822
Visual run contains data about the bit of text with the same font.
Definition: gfx_layout.cpp:245
static void free(const void *ptr)
Version of the standard free that accepts const pointers.
Definition: depend.cpp:114
Index of the large font in the font tables.
Definition: gfx_type.h:206
static FallbackParagraphLayout * GetParagraphLayout(WChar *buff, WChar *buff_end, FontMap &fontMapping)
Get the actual ParagraphLayout for the given buffer.
Definition: gfx_layout.cpp:559
const ParagraphLayouter::Line * * Get(uint index) const
Get the pointer to item "number" (const)
const Font * GetFont() const
Get the font associated with this run.
Definition: gfx_layout.cpp:321
UChar CharType
Helper for GetLayouter, to get the right type.
Definition: gfx_layout.cpp:132
Text is written right-to-left by default.
Definition: strings_type.h:26
uint32 GlyphID
Glyphs are characters from a font.
Definition: fontcache.h:19
ParagraphLayouter * layout
Layout of the line.
Definition: gfx_layout.h:164
uint32 WChar
Type for wide characters, i.e.
Definition: string_type.h:35
int GetGlyphCount() const
Get the number of glyphs in this run.
Definition: gfx_layout.cpp:330
const WChar * buffer
The current location in the buffer.
Definition: gfx_layout.cpp:275
Layouter(const char *str, int maxw=INT32_MAX, TextColour colour=TC_FROMSTRING, FontSize fontsize=FS_NORMAL)
Create a new layouter.
Definition: gfx_layout.cpp:635
Dimensions (a width and height) of a rectangle in 2D.
Switch to small font.
Definition: control_codes.h:30
Point GetCharPosition(const char *ch) const
Get the position of a character in the layout.
Definition: gfx_layout.cpp:707
const char * string
Pointer to the original string.
Definition: gfx_layout.h:140
const GlyphID * GetGlyphs() const
Get the glyphs of this run.
Definition: gfx_layout.cpp:339
Item in the linecache.
Definition: gfx_layout.h:158