| Index: ppapi/shared_impl/private/ppb_browser_font_trusted_shared.cc
|
| diff --git a/ppapi/shared_impl/private/ppb_browser_font_trusted_shared.cc b/ppapi/shared_impl/private/ppb_browser_font_trusted_shared.cc
|
| index e5414b3eb05b0e8b1c4017fffcd63a8847f9658d..9b2c0f53df4ae82b1a428b357aaee0ab8863a51c 100644
|
| --- a/ppapi/shared_impl/private/ppb_browser_font_trusted_shared.cc
|
| +++ b/ppapi/shared_impl/private/ppb_browser_font_trusted_shared.cc
|
| @@ -21,6 +21,7 @@
|
| #include "third_party/WebKit/Source/WebKit/chromium/public/WebFont.h"
|
| #include "third_party/WebKit/Source/WebKit/chromium/public/WebFontDescription.h"
|
| #include "third_party/WebKit/Source/WebKit/chromium/public/WebTextRun.h"
|
| +#include "unicode/ubidi.h"
|
|
|
| using ppapi::StringVar;
|
| using ppapi::thunk::EnterResourceNoLock;
|
| @@ -51,6 +52,74 @@ string16 GetFontFromMap(
|
| return string16();
|
| }
|
|
|
| +// Splits a PP_BrowserFont_Trusted_TextRun into a sequence or LTR and RTL
|
| +// WebTextRuns that can be used for WebKit. Normally WebKit does this for us,
|
| +// but the font drawing and measurement routines we call happen after this
|
| +// step. So for correct rendering of RTL content, we need to do it ourselves.
|
| +class TextRunCollection {
|
| + public:
|
| + explicit TextRunCollection(const PP_BrowserFont_Trusted_TextRun& run)
|
| + : bidi_(NULL),
|
| + num_runs_(0) {
|
| + StringVar* text_string = StringVar::FromPPVar(run.text);
|
| + if (!text_string)
|
| + return; // Leave num_runs_ = 0 so we'll do nothing.
|
| + text_ = UTF8ToUTF16(text_string->value());
|
| +
|
| + if (run.override_direction) {
|
| + // Skip autodetection.
|
| + num_runs_ = 1;
|
| + override_run_ = WebTextRun(text_, PP_ToBool(run.rtl), true);
|
| + } else {
|
| + bidi_ = ubidi_open();
|
| + UErrorCode uerror = U_ZERO_ERROR;
|
| + ubidi_setPara(bidi_, text_.data(), text_.size(), run.rtl, NULL, &uerror);
|
| + if (U_SUCCESS(uerror))
|
| + num_runs_ = ubidi_countRuns(bidi_, &uerror);
|
| + }
|
| + }
|
| +
|
| + ~TextRunCollection() {
|
| + if (bidi_)
|
| + ubidi_close(bidi_);
|
| + }
|
| +
|
| + const string16& text() const { return text_; }
|
| + int num_runs() const { return num_runs_; }
|
| +
|
| + // Returns a WebTextRun with the info for the run at the given index.
|
| + // The range covered by the run is in the two output params.
|
| + WebTextRun GetRunAt(int index, int32_t* run_start, int32_t* run_len) const {
|
| + DCHECK(index < num_runs_);
|
| + if (bidi_) {
|
| + bool run_rtl = !!ubidi_getVisualRun(bidi_, index, run_start, run_len);
|
| + return WebTextRun(string16(&text_[*run_start], *run_len),
|
| + run_rtl, true);
|
| + }
|
| +
|
| + // Override run, return the single one.
|
| + DCHECK(index == 0);
|
| + *run_start = 0;
|
| + *run_len = static_cast<int32_t>(text_.size());
|
| + return override_run_;
|
| + }
|
| +
|
| + private:
|
| + // Will be null if we skipped autodetection.
|
| + UBiDi* bidi_;
|
| +
|
| + // Text of all the runs.
|
| + string16 text_;
|
| +
|
| + int num_runs_;
|
| +
|
| + // When the content specifies override_direction (bidi_ is null) then this
|
| + // will contain the single text run for WebKit.
|
| + WebTextRun override_run_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(TextRunCollection);
|
| +};
|
| +
|
| bool PPTextRunToWebTextRun(const PP_BrowserFont_Trusted_TextRun& text,
|
| WebTextRun* run) {
|
| StringVar* text_string = StringVar::FromPPVar(text.text);
|
| @@ -280,25 +349,53 @@ int32_t PPB_BrowserFont_Trusted_Shared::MeasureText(
|
| uint32_t PPB_BrowserFont_Trusted_Shared::CharacterOffsetForPixel(
|
| const PP_BrowserFont_Trusted_TextRun* text,
|
| int32_t pixel_position) {
|
| - WebTextRun run;
|
| - if (!PPTextRunToWebTextRun(*text, &run))
|
| - return -1;
|
| - return static_cast<uint32_t>(font_->offsetForPosition(
|
| - run, static_cast<float>(pixel_position)));
|
| + TextRunCollection runs(*text);
|
| + int32_t cur_pixel_offset = 0;
|
| + for (int i = 0; i < runs.num_runs(); i++) {
|
| + int32_t run_begin = 0;
|
| + int32_t run_len = 0;
|
| + WebTextRun run = runs.GetRunAt(i, &run_begin, &run_len);
|
| + int run_width = font_->calculateWidth(run);
|
| + if (pixel_position < cur_pixel_offset + run_width) {
|
| + // Offset is in this run.
|
| + return static_cast<uint32_t>(font_->offsetForPosition(
|
| + run, static_cast<float>(pixel_position - cur_pixel_offset))) +
|
| + run_begin;
|
| + }
|
| + cur_pixel_offset += run_width;
|
| + }
|
| + return runs.text().size();
|
| }
|
|
|
| int32_t PPB_BrowserFont_Trusted_Shared::PixelOffsetForCharacter(
|
| const PP_BrowserFont_Trusted_TextRun* text,
|
| uint32_t char_offset) {
|
| - WebTextRun run;
|
| - if (!PPTextRunToWebTextRun(*text, &run))
|
| - return -1;
|
| - if (char_offset >= run.text.length())
|
| - return -1;
|
| -
|
| - WebFloatRect rect = font_->selectionRectForText(
|
| - run, WebFloatPoint(0.0f, 0.0f), font_->height(), 0, char_offset);
|
| - return static_cast<int>(rect.width);
|
| + TextRunCollection runs(*text);
|
| + int32_t cur_pixel_offset = 0;
|
| + for (int i = 0; i < runs.num_runs(); i++) {
|
| + int32_t run_begin = 0;
|
| + int32_t run_len = 0;
|
| + WebTextRun run = runs.GetRunAt(i, &run_begin, &run_len);
|
| + if (char_offset >= static_cast<uint32_t>(run_begin) &&
|
| + char_offset < static_cast<uint32_t>(run_begin + run_len)) {
|
| + // Character we're looking for is in this run.
|
| + //
|
| + // Here we ask WebKit to give us the rectangle around the character in
|
| + // question, and then return the left edge. If we asked for a range of
|
| + // 0 characters starting at the character in question, it would give us
|
| + // a 0-width rect around the insertion point. But that will be on the
|
| + // right side of the character for an RTL run, which would be wrong.
|
| + WebFloatRect rect = font_->selectionRectForText(
|
| + run, WebFloatPoint(0.0f, 0.0f), font_->height(),
|
| + char_offset - run_begin, char_offset - run_begin + 1);
|
| + return cur_pixel_offset + static_cast<int>(rect.x);
|
| + } else {
|
| + // Character is past this run, account for the pixels and continue
|
| + // looking.
|
| + cur_pixel_offset += font_->calculateWidth(run);
|
| + }
|
| + }
|
| + return -1; // Requested a char beyond the end.
|
| }
|
|
|
| void PPB_BrowserFont_Trusted_Shared::DrawTextToCanvas(
|
| @@ -308,10 +405,6 @@ void PPB_BrowserFont_Trusted_Shared::DrawTextToCanvas(
|
| uint32_t color,
|
| const PP_Rect* clip,
|
| PP_Bool image_data_is_opaque) {
|
| - WebTextRun run;
|
| - if (!PPTextRunToWebTextRun(text, &run))
|
| - return;
|
| -
|
| // Convert position and clip.
|
| WebFloatPoint web_position(static_cast<float>(position->x),
|
| static_cast<float>(position->y));
|
| @@ -328,8 +421,20 @@ void PPB_BrowserFont_Trusted_Shared::DrawTextToCanvas(
|
| clip->size.width, clip->size.height);
|
| }
|
|
|
| - font_->drawText(destination, run, web_position, color, web_clip,
|
| - PP_ToBool(image_data_is_opaque));
|
| + TextRunCollection runs(text);
|
| + for (int i = 0; i < runs.num_runs(); i++) {
|
| + int32_t run_begin = 0;
|
| + int32_t run_len = 0;
|
| + WebTextRun run = runs.GetRunAt(i, &run_begin, &run_len);
|
| + font_->drawText(destination, run, web_position, color, web_clip,
|
| + PP_ToBool(image_data_is_opaque));
|
| +
|
| + // Advance to the next run. Note that we avoid doing this for the last run
|
| + // since it's unnecessary, measuring text is slow, and most of the time
|
| + // there will be only one run anyway.
|
| + if (i != runs.num_runs() - 1)
|
| + web_position.x += font_->calculateWidth(run);
|
| + }
|
| }
|
|
|
| } // namespace ppapi
|
|
|