588 void Layout::doLayoutRunCached(const uint16_t* buf, size_t start, size_t count, size_t bufSize,
589 bool isRtl, LayoutContext* ctx, size_t dstStart) {
590 if (!isRtl) {
591
592 size_t wordstart = start == bufSize ? start : getPrevWordBreak(buf, start + 1);
593 size_t wordend;
594 for (size_t iter = start; iter < start + count; iter = wordend) {
595 wordend = getNextWordBreak(buf, iter, bufSize);
596 size_t wordcount = std::min(start + count, wordend) - iter;
597 doLayoutWord(buf + wordstart, iter - wordstart, wordcount, wordend - wordstart,
598 isRtl, ctx, iter - dstStart);
599 wordstart = wordend;
600 }
601 } else {
602
603 size_t wordstart;
604 size_t end = start + count;
605 size_t wordend = end == 0 ? 0 : getNextWordBreak(buf, end - 1, bufSize);
606 for (size_t iter = end; iter > start; iter = wordstart) {
607 wordstart = getPrevWordBreak(buf, iter);
608 size_t bufStart = std::max(start, wordstart);
609 doLayoutWord(buf + wordstart, bufStart - wordstart, iter - bufStart,
610 wordend - wordstart, isRtl, ctx, bufStart - dstStart);
611 wordend = wordstart;
612 }
613 }
614 }
616 void Layout::doLayoutWord(const uint16_t* buf, size_t start, size_t count, size_t bufSize,
617 bool isRtl, LayoutContext* ctx, size_t bufStart) {
618 LayoutCache& cache = LayoutEngine::getInstance().layoutCache;
619 LayoutCacheKey key(mCollection, ctx->paint, ctx->style, buf, start, count, bufSize, isRtl);
620 bool skipCache = ctx->paint.skipCache();
621 if (skipCache) {
622 Layout layout;
623 key.doLayout(&layout, ctx, mCollection);
624 appendLayout(&layout, bufStart);
625 } else {
626 Layout* layout = cache.get(key, ctx, mCollection);
627 appendLayout(layout, bufStart);
628 }
629 }
652 void Layout::doLayoutRun(const uint16_t* buf, size_t start, size_t count, size_t bufSize,
653 bool isRtl, LayoutContext* ctx) {
654 hb_buffer_t* buffer = LayoutEngine::getInstance().hbBuffer;
655 vector<FontCollection::Run> items;
656 mCollection->itemize(buf + start, count, ctx->style, &items); <=====
657 if (isRtl) {
658 std::reverse(items.begin(), items.end());
659 }
660
661 vector<hb_feature_t> features;
662
663
664
665
666
667 if (fabs(ctx->paint.letterSpacing) > 0.03)
668 {
669 static const hb_feature_t no_liga = { HB_TAG('l', 'i', 'g', 'a'), 0, 0, ~0u };
670 static const hb_feature_t no_clig = { HB_TAG('c', 'l', 'i', 'g'), 0, 0, ~0u };
671 features.push_back(no_liga);
672 features.push_back(no_clig);
673 }
674 addFeatures(ctx->paint.fontFeatureSettings, &features);
675
676 double size = ctx->paint.size;
677 double scaleX = ctx->paint.scaleX;
678 double letterSpace = ctx->paint.letterSpacing * size * scaleX;
679 double letterSpaceHalfLeft;
680 if ((ctx->paint.paintFlags & LinearTextFlag) == 0) {
681 letterSpace = round(letterSpace);
682 letterSpaceHalfLeft = floor(letterSpace * 0.5);
683 } else {
684 letterSpaceHalfLeft = letterSpace * 0.5;
685 }
686 double letterSpaceHalfRight = letterSpace - letterSpaceHalfLeft;
687
688 float x = mAdvance;
689 float y = 0;
690 for (size_t run_ix = 0; run_ix < items.size(); run_ix++) {
691 FontCollection::Run &run = items[run_ix];
692 if (run.fakedFont.font == NULL) {
693 ALOGE("no font for run starting u+%04x length %d", buf[run.start], run.end - run.start);
694 continue;
695 }
696 int font_ix = findFace(run.fakedFont, ctx);
697 ctx->paint.font = mFaces[font_ix].font;
698 ctx->paint.fakery = mFaces[font_ix].fakery;
699 hb_font_t* hbFont = ctx->hbFonts[font_ix];
700 #ifdef VERBOSE
701 std::cout << "Run " << run_ix << ", font " << font_ix <<
702 " [" << run.start << ":" << run.end << "]" << std::endl;
703 #endif
704
705 hb_font_set_ppem(hbFont, size * scaleX, size);
706 hb_font_set_scale(hbFont, HBFloatToFixed(size * scaleX), HBFloatToFixed(size));
707
708 TODO
709
710
711 ssize_t srunend;
712 for (ssize_t srunstart = run.start; srunstart < run.end; srunstart = srunend) {
713 srunend = srunstart;
714 hb_script_t script = getScriptRun(buf + start, run.end, &srunend);
715
716 hb_buffer_reset(buffer);
717 hb_buffer_set_script(buffer, script);
718 hb_buffer_set_direction(buffer, isRtl? HB_DIRECTION_RTL : HB_DIRECTION_LTR);
719 FontLanguage language = ctx->style.getLanguage();
720 if (language) {
721 string lang = language.getString();
722 hb_buffer_set_language(buffer, hb_language_from_string(lang.c_str(), -1));
723 }
724 hb_buffer_add_utf16(buffer, buf, bufSize, srunstart + start, srunend - srunstart);
725 hb_shape(hbFont, buffer, features.empty() ? NULL : &features[0], features.size());
726 unsigned int numGlyphs;
727 hb_glyph_info_t* info = hb_buffer_get_glyph_infos(buffer, &numGlyphs);
728 hb_glyph_position_t* positions = hb_buffer_get_glyph_positions(buffer, NULL);
729 if (numGlyphs)
730 {
731 mAdvances[info[0].cluster - start] += letterSpaceHalfLeft;
732 x += letterSpaceHalfLeft;
733 }
734 for (unsigned int i = 0; i < numGlyphs; i++) {
735 #ifdef VERBOSE
736 std::cout << positions[i].x_advance << " " << positions[i].y_advance << " " << positions[i].x_offset << " " << positions[i].y_offset << std::endl; std::cout << "DoLayout " << info[i].codepoint <<
737 ": " << HBFixedToFloat(positions[i].x_advance) << "; " << positions[i].x_offset << ", " << positions[i].y_offset << std::endl;
738 #endif
739 if (i > 0 && info[i - 1].cluster != info[i].cluster) {
740 mAdvances[info[i - 1].cluster - start] += letterSpaceHalfRight;
741 mAdvances[info[i].cluster - start] += letterSpaceHalfLeft;
742 x += letterSpace;
743 }
744
745 hb_codepoint_t glyph_ix = info[i].codepoint;
746 float xoff = HBFixedToFloat(positions[i].x_offset);
747 float yoff = -HBFixedToFloat(positions[i].y_offset);
748 xoff += yoff * ctx->paint.skewX;
749 LayoutGlyph glyph = {font_ix, glyph_ix, x + xoff, y + yoff};
750 mGlyphs.push_back(glyph);
751 float xAdvance = HBFixedToFloat(positions[i].x_advance);
752 if ((ctx->paint.paintFlags & LinearTextFlag) == 0) {
753 xAdvance = roundf(xAdvance);
754 }
755 MinikinRect glyphBounds;
756 ctx->paint.font->GetBounds(&glyphBounds, glyph_ix, ctx->paint);
757 glyphBounds.offset(x + xoff, y + yoff);
758 mBounds.join(glyphBounds);
759 mAdvances[info[i].cluster - start] += xAdvance;
760 x += xAdvance;
761 }
762 if (numGlyphs)
763 {
764 mAdvances[info[numGlyphs - 1].cluster - start] += letterSpaceHalfRight;
765 x += letterSpaceHalfRight;
766 }
767 }
768 }
769 mAdvance = x;
770 }
182 void FontCollection::itemize(const uint16_t *string, size_t string_size, FontStyle style,
183 vector<Run>* result) const {
184 FontLanguage lang = style.getLanguage();
185 int variant = style.getVariant();
186 const FontInstance* lastInstance = NULL;
187 Run* run = NULL;
188 int nShorts;
189 for (size_t i = 0; i < string_size; i += nShorts) {
190 nShorts = 1;
191 uint32_t ch = string[i];
192
193 if ((ch & 0xfc00) == 0xd800) {
194 if ((i + 1) < string_size) {
195 ch = 0x10000 + ((ch & 0x3ff) << 10) + (string[i + 1] & 0x3ff);
196 nShorts = 2;
197 }
198 }
199
200 if (lastInstance == NULL
201 || !(isStickyWhitelisted(ch) && lastInstance->mCoverage->get(ch))) {
202 const FontInstance* instance = getInstanceForChar(ch, lang, variant); <=====
203 if (i == 0 || instance != lastInstance) {
204 size_t start = i;
205
206
207
208
209
210 if (ch == KEYCAP && i && instance && instance->mCoverage->get(string[i - 1])) {
211 run->end--;
212 if (run->start == run->end) {
213 result->pop_back();
214 }
215 start--;
216 }
217 Run dummy;
218 result->push_back(dummy);
219 run = &result->back();
220 if (instance == NULL) {
221 run->fakedFont.font = NULL;
222 } else {
223 run->fakedFont = instance->mFamily->getClosestMatch(style);
224 }
225 lastInstance = instance;
226 run->start = start;
227 }
228 }
229 run->end = i + nShorts;
230 }
231 }
114
115
116
117
118
119
120 const FontCollection::FontInstance* FontCollection::getInstanceForChar(uint32_t ch,
121 FontLanguage lang, int variant) const {
122 if (ch >= mMaxChar) {
123 return NULL;
124 }
125 const Range& range = mRanges[ch >> kLogCharsPerPage];
126 #ifdef VERBOSE_DEBUG
127 ALOGD("querying range %d:%d\n", range.start, range.end);
128 #endif
129 const FontInstance* bestInstance = NULL;
130 int bestScore = -1;
131 for (size_t i = range.start; i < range.end; i++) {
132 const FontInstance* instance = mInstanceVec[i];
133 if (instance->mCoverage->get(ch)) {
134 FontFamily* family = instance->mFamily;
135
136 if (mInstances[0].mFamily == family) {
137 return instance;
138 }
139 int score = lang.match(family->lang()) * 2;
140 if (variant != 0 && variant == family->variant()) {
141 score++;
142 }
143 if (score > bestScore) {
144 bestScore = score;
145 bestInstance = instance;
146 }
147 }
148 }
149 if (bestInstance == NULL && !mInstanceVec.empty()) {
150 UErrorCode errorCode = U_ZERO_ERROR;
151 const UNormalizer2* normalizer = unorm2_getNFDInstance(&errorCode);
152 if (U_SUCCESS(errorCode)) {
153 UChar decomposed[4];
154 int len = unorm2_getRawDecomposition(normalizer, ch, decomposed, 4, &errorCode);
155 if (U_SUCCESS(errorCode) && len > 0) {
156 int off = 0;
157 U16_NEXT_UNSAFE(decomposed, off, ch);
158 return getInstanceForChar(ch, lang, variant);
159 }
160 }
161 bestInstance = &mInstances[0];
162 }
163 return bestInstance;
164 }