20 #ifdef WITH_ICU_LAYOUT
21 #include <unicode/ustring.h>
42 assert(size < FS_END);
45 #ifdef WITH_ICU_LAYOUT
48 le_int32 Font::getUnitsPerEM()
const
50 return this->fc->GetUnitsPerEM();
53 le_int32 Font::getAscent()
const
55 return this->fc->GetAscender();
58 le_int32 Font::getDescent()
const
60 return -this->fc->GetDescender();
63 le_int32 Font::getLeading()
const
65 return this->fc->GetHeight();
68 float Font::getXPixelsPerEm()
const
70 return (
float)this->fc->GetHeight();
73 float Font::getYPixelsPerEm()
const
75 return (
float)this->fc->GetHeight();
78 float Font::getScaleFactorX()
const
83 float Font::getScaleFactorY()
const
88 const void *Font::getFontTable(LETag tableTag)
const
91 return this->getFontTable(tableTag, length);
94 const void *Font::getFontTable(LETag tableTag,
size_t &length)
const
96 return this->fc->GetFontTable(tableTag, length);
99 LEGlyphID Font::mapCharToGlyph(LEUnicode32 ch)
const
102 return this->fc->MapCharToGlyph(ch);
105 void Font::getGlyphAdvance(LEGlyphID glyph, LEPoint &advance)
const
107 advance.fX = glyph == 0xFFFF ? 0 : this->fc->GetGlyphWidth(glyph);
111 le_bool Font::getGlyphPoint(LEGlyphID glyph, le_int32 pointNumber, LEPoint &point)
const
120 UErrorCode err = U_ZERO_ERROR;
121 u_strFromUTF32(buff, buffer_last - buff, &length, (UChar32*)&c, 1, &err);
132 typedef UChar CharType;
134 static const bool SUPPORTS_RTL =
true;
138 const ParagraphLayout::VisualRun *vr;
141 ICUVisualRun(
const ParagraphLayout::VisualRun *vr) : vr(vr) { }
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(); }
153 ParagraphLayout::Line *l;
156 ICULine(ParagraphLayout::Line *l) : l(l)
158 for (
int i = 0; i < l->countRuns(); i++) {
159 *this->Append() =
new ICUVisualRun(l->getVisualRun(i));
162 ~ICULine() {
delete l; }
164 int GetLeading()
const {
return l->getLeading(); }
165 int GetWidth()
const {
return l->getWidth(); }
166 int CountRuns()
const {
return l->countRuns(); }
169 int GetInternalCharLength(
WChar c)
const
176 ICUParagraphLayout(ParagraphLayout *p) : p(p) { }
177 ~ICUParagraphLayout() {
delete p; }
178 void Reflow() { p->reflow(); }
182 ParagraphLayout::Line *l = p->nextLine(max_width);
183 return l == NULL ? NULL :
new ICULine(l);
189 int32 length = buff_end - buff;
195 fontMapping.
End()[-1].first++;
199 FontRuns runs(fontMapping.
Length());
201 runs.add(iter->second, iter->first);
204 LEErrorCode status = LE_NO_ERROR;
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) {
213 return new ICUParagraphLayout(p);
271 int GetInternalCharLength(
WChar c)
const {
return 1; }
291 font(font), glyph_count(char_count)
298 this->positions[0] = x;
299 this->positions[1] = 0;
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;
312 free(this->positions);
313 free(this->glyph_to_char);
332 return this->glyph_count;
350 return this->positions;
359 return this->glyph_to_char;
368 return this->GetFont()->fc->GetHeight();
378 for (
const FallbackVisualRun *
const *run = this->Begin(); run != this->End(); run++) {
379 leading =
max(leading, (*run)->GetLeading());
391 if (this->Length() == 0)
return 0;
399 return (
int)run->GetPositions()[run->GetGlyphCount() * 2];
408 return this->Length();
417 return *this->Get(run);
428 assert(runs.
End()[-1].first == length);
450 if (this->
buffer == NULL)
return NULL;
454 if (*this->
buffer ==
'\0') {
462 const WChar *last_space = NULL;
463 const WChar *last_char = begin;
468 while (iter->first <= offset) {
470 assert(iter != this->
runs.
End());
474 const WChar *next_run = this->buffer_begin + iter->first;
485 if (this->
buffer == next_run) {
489 assert(iter != this->
runs.
End());
491 next_run = this->buffer_begin + iter->first;
502 if (width > max_width) {
505 if (width == char_width) {
512 if (last_space == NULL) {
522 this->
buffer = last_space + 1;
523 last_char = last_space;
532 if (l->
Length() == 0 || last_char - begin != 0) {
573 template <
typename T>
580 typename T::CharType *buff = buff_begin;
591 for (; buff < buffer_last;) {
592 WChar c = Utf8Consume(const_cast<const char **>(&str));
593 if (c ==
'\0' || c ==
'\n') {
595 }
else if (c >= SCC_BLUE && c <= SCC_BLACK) {
597 }
else if (c == SCC_PREVIOUS_COLOUR) {
612 if (!fontMapping.
Contains(buff - buff_begin)) {
613 fontMapping.
Insert(buff - buff_begin, f);
621 if (!fontMapping.
Contains(buff - buff_begin)) {
622 fontMapping.
Insert(buff - buff_begin, f);
642 const char *lineend = str;
645 if (c ==
'\0' || c ==
'\n')
break;
650 if (line.
layout != NULL) {
657 #ifdef WITH_ICU_LAYOUT
659 const char *old_str = str;
661 GetLayouter<ICUParagraphLayout>(line, str, state);
662 if (line.layout == NULL) {
663 static bool warned =
false;
665 DEBUG(misc, 0,
"ICU layouter bailed on the font. Falling back to the fallback layouter");
671 GetLayouter<FallbackParagraphLayout>(line, str, state);
674 GetLayouter<FallbackParagraphLayout>(line, str, state);
680 while ((l = line.
layout->NextLine(maxw)) != NULL) {
695 d.width = max<uint>(d.width, (*l)->GetWidth());
696 d.height += (*l)->GetLeading();
712 const char *str = this->
string;
716 if (c ==
'\0' || c ==
'\n')
break;
718 index += (*this->
Begin())->GetInternalCharLength(c);
726 if (*ch ==
'\0' || *ch ==
'\n') {
727 Point p = { line->GetWidth(), 0 };
732 for (
int run_index = 0; run_index < line->CountRuns(); run_index++) {
735 for (
int i = 0; i < run->GetGlyphCount(); i++) {
737 if ((
size_t)run->GetGlyphToCharMap()[i] == index) {
738 Point p = { (int)run->GetPositions()[i * 2], (int)run->GetPositions()[i * 2 + 1] };
758 for (
int run_index = 0; run_index < line->CountRuns(); run_index++) {
761 for (
int i = 0; i < run->GetGlyphCount(); i++) {
763 if (run->GetGlyphs()[i] == 0xFFFF)
continue;
765 int begin_x = (int)run->GetPositions()[i * 2];
766 int end_x = (int)run->GetPositions()[i * 2 + 2];
770 size_t index = run->GetGlyphToCharMap()[i];
773 for (
const char *str = this->
string; *str !=
'\0'; ) {
774 if (cur_idx == index)
return str;
776 WChar c = Utf8Consume(&str);
777 cur_idx += line->GetInternalCharLength(c);
792 if (it !=
fonts[size].
End())
return it->second;
794 Font *f =
new Font(size, colour);
831 key.
str.assign(str, len);