Chrome RenderText分析(1)

继续分析以下步骤

 

一.TextRun结构

struct TextRun {
TextRun();
~TextRun(); ui::Range range;
Font font;
// A gfx::Font::FontStyle flag to specify bold and italic styles.
// Supersedes |font.GetFontStyle()|. Stored separately to avoid calling
// |font.DeriveFont()|, which is expensive on Windows.
int font_style; // TODO(msw): Disambiguate color/style from TextRuns for proper glyph shaping.
// See an example: http://www.catch22.net/tuts/uniscribe-mysteries
SkColor foreground;
bool strike;
bool diagonal_strike;
bool underline; int width;
// The cumulative widths of preceding runs.
int preceding_run_widths; SCRIPT_ANALYSIS script_analysis; scoped_ptr<WORD[]> glyphs;
scoped_ptr<WORD[]> logical_clusters;
scoped_ptr<SCRIPT_VISATTR[]> visible_attributes;
int glyph_count; scoped_ptr<int[]> advance_widths;
scoped_ptr<GOFFSET[]> offsets;
ABC abc_widths;
SCRIPT_CACHE script_cache; private:
DISALLOW_COPY_AND_ASSIGN(TextRun);
};

TextRun可以理解为一个输出结果

  1. ScriptItemize输出script_analysis
  2. ScriptShape输出glyphs,logical_clusters,visible_attributes,glyph_count
  3. ScriptPlace输出advance_widths,offsets,abc_widths(真正想要的宽度结果)

二.ScriptShape

  1. 根据文字的长度初始化相关的缓冲区
  2. 选择文字字体
  3. 调用ScriptShape来填充TextRun
  4. 如果调用ScriptShape失败的话则使用SCRIPT_FONTPROPERTIES的默认值来填充
void RenderTextWin::LayoutTextRun(internal::TextRun* run) {
const size_t run_length = run->range.length();
const wchar_t* run_text = &(GetLayoutText()[run->range.start()]);
Font original_font = run->font;
LinkedFontsIterator fonts(original_font);
bool tried_cached_font = false;
bool tried_fallback = false;
// Keep track of the font that is able to display the greatest number of
// characters for which ScriptShape() returned S_OK. This font will be used
// in the case where no font is able to display the entire run.
int best_partial_font_missing_char_count = INT_MAX;
Font best_partial_font = original_font;
bool using_best_partial_font = false;
Font current_font; run->logical_clusters.reset(new WORD[run_length]);
while (fonts.NextFont(&current_font)) {
HRESULT hr = ShapeTextRunWithFont(run, current_font); bool glyphs_missing = false;
if (hr == USP_E_SCRIPT_NOT_IN_FONT) {
glyphs_missing = true;
} else if (hr == S_OK) {
// If |hr| is S_OK, there could still be missing glyphs in the output.
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd368564.aspx
const int missing_count = CountCharsWithMissingGlyphs(run);
// Track the font that produced the least missing glyphs.
if (missing_count < best_partial_font_missing_char_count) {
best_partial_font_missing_char_count = missing_count;
best_partial_font = run->font;
}
glyphs_missing = (missing_count != 0);
} else {
NOTREACHED() << hr;
} // Use the font if it had glyphs for all characters.
if (!glyphs_missing) {
// Save the successful fallback font that was chosen.
if (tried_fallback)
successful_substitute_fonts_[original_font.GetFontName()] = run->font;
return;
} // First, try the cached font from previous runs, if any.
if (!tried_cached_font) {
tried_cached_font = true; std::map<std::string, Font>::const_iterator it =
successful_substitute_fonts_.find(original_font.GetFontName());
if (it != successful_substitute_fonts_.end()) {
fonts.SetNextFont(it->second);
continue;
}
} // If there are missing glyphs, first try finding a fallback font using a
// meta file, if it hasn't yet been attempted for this run.
// TODO(msw|asvitkine): Support RenderText's font_list()?
if (!tried_fallback) {
tried_fallback = true; Font fallback_font;
if (ChooseFallbackFont(cached_hdc_, run->font, run_text, run_length,
&fallback_font)) {
fonts.SetNextFont(fallback_font);
continue;
}
}
} // If a font was able to partially display the run, use that now.
if (best_partial_font_missing_char_count < static_cast<int>(run_length)) {
// Re-shape the run only if |best_partial_font| differs from the last font.
if (best_partial_font.GetNativeFont() != run->font.GetNativeFont())
ShapeTextRunWithFont(run, best_partial_font);
return;
} // If no font was able to partially display the run, replace all glyphs
// with |wgDefault| from the original font to ensure to they don't hold
// garbage values.
// First, clear the cache and select the original font on the HDC.
ScriptFreeCache(&run->script_cache);
run->font = original_font;
SelectObject(cached_hdc_, run->font.GetNativeFont());
// Now, get the font's properties.
SCRIPT_FONTPROPERTIES properties;
memset(&properties, 0, sizeof(properties));
properties.cBytes = sizeof(properties);
HRESULT hr = ScriptGetFontProperties(cached_hdc_, &run->script_cache,
&properties);
if (hr == S_OK) {
// Finally, initialize |glyph_count|, |glyphs| and |visible_attributes| on
// the run (since they may not have been set yet).
run->glyph_count = run_length;
memset(run->visible_attributes.get(), 0,
run->glyph_count * sizeof(SCRIPT_VISATTR));
for (int i = 0; i < run->glyph_count; ++i) {
run->glyphs[i] = IsWhitespace(run_text[i]) ? properties.wgBlank :
properties.wgDefault;
}
}
// TODO(msw): Don't use SCRIPT_UNDEFINED. Apparently Uniscribe can
// crash on certain surrogate pairs with SCRIPT_UNDEFINED.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=341500
// And http://maxradi.us/documents/uniscribe/
run->script_analysis.eScript = SCRIPT_UNDEFINED;

} HRESULT RenderTextWin::ShapeTextRunWithFont(internal::TextRun* run,
const Font& font) {
// Update the run's font only if necessary. If the two fonts wrap the same
// PlatformFontWin object, their native fonts will have the same value.
if (run->font.GetNativeFont() != font.GetNativeFont()) {
const int font_size = run->font.GetFontSize();
const int font_height = run->font.GetHeight();
run->font = font;
DeriveFontIfNecessary(font_size, font_height, run->font_style, &run->font);
ScriptFreeCache(&run->script_cache);
}
// Select the font desired for glyph generation.
SelectObject(cached_hdc_, run->font.GetNativeFont()); HRESULT hr = E_OUTOFMEMORY;
const size_t run_length = run->range.length();
const wchar_t* run_text = &(GetLayoutText()[run->range.start()]);
// Max glyph guess: http://msdn.microsoft.com/en-us/library/dd368564.aspx
size_t max_glyphs = static_cast<size_t>(1.5 * run_length + 16);
while (hr == E_OUTOFMEMORY && max_glyphs < kMaxGlyphs) {
run->glyph_count = 0;
run->glyphs.reset(new WORD[max_glyphs]);
run->visible_attributes.reset(new SCRIPT_VISATTR[max_glyphs]);
hr = ScriptShape(cached_hdc_,
&run->script_cache,
run_text,
run_length,
max_glyphs,
&run->script_analysis,
run->glyphs.get(),
run->logical_clusters.get(),
run->visible_attributes.get(),
&run->glyph_count);
max_glyphs *= 2;
}
return hr;
}

三.ScriptPlace

run->abc_widths是计算的结果

void RenderTextWin::LayoutVisualText() {
DCHECK(!runs_.empty()); if (!cached_hdc_)
cached_hdc_ = CreateCompatibleDC(NULL); HRESULT hr = E_FAIL;
string_size_.set_height(0);
for (size_t i = 0; i < runs_.size(); ++i) {
internal::TextRun* run = runs_[i];
LayoutTextRun(run); string_size_.set_height(std::max(string_size_.height(),
run->font.GetHeight()));
common_baseline_ = std::max(common_baseline_, run->font.GetBaseline()); if (run->glyph_count > 0) {
run->advance_widths.reset(new int[run->glyph_count]);
run->offsets.reset(new GOFFSET[run->glyph_count]);
hr = ScriptPlace(cached_hdc_,
&run->script_cache,
run->glyphs.get(),
run->glyph_count,
run->visible_attributes.get(),
&(run->script_analysis),
run->advance_widths.get(),
run->offsets.get(),
&(run->abc_widths));
DCHECK(SUCCEEDED(hr));
}

} // Build the array of bidirectional embedding levels.
scoped_ptr<BYTE[]> levels(new BYTE[runs_.size()]);
for (size_t i = 0; i < runs_.size(); ++i)
levels[i] = runs_[i]->script_analysis.s.uBidiLevel; // Get the maps between visual and logical run indices.
visual_to_logical_.reset(new int[runs_.size()]);
logical_to_visual_.reset(new int[runs_.size()]);
hr = ScriptLayout(runs_.size(),
levels.get(),
visual_to_logical_.get(),
logical_to_visual_.get());
DCHECK(SUCCEEDED(hr)); // Precalculate run width information.
size_t preceding_run_widths = 0;
for (size_t i = 0; i < runs_.size(); ++i) {
internal::TextRun* run = runs_[visual_to_logical_[i]];
run->preceding_run_widths = preceding_run_widths;
const ABC& abc = run->abc_widths;
run->width = abc.abcA + abc.abcB + abc.abcC;
preceding_run_widths += run->width;
}
string_size_.set_width(preceding_run_widths);
}

Chrome RenderText分析(2)的更多相关文章

  1. Chrome RenderText分析(1)

      先从一些基础的类开始 1.Range // A Range contains two integer values that represent a numeric range, like the ...

  2. JS内存泄漏 和Chrome 内存分析工具简介(摘)

    原文地址:http://web.jobbole.com/88463/ JavaScript 中 4 种常见的内存泄露陷阱   原文:Sebastián Peyrott 译文:伯乐在线专栏作者 - AR ...

  3. Chrome渲染分析之Timeline工具的使用

    原文http://www.th7.cn/web/html-css/201406/42043.shtml Timeline工具栏提供了对于在装载你的Web应用的过程中,时间花费情况的概览,这些应用包括处 ...

  4. chrome性能分析

    Chrome开发者工具之JavaScript内存分析 前端性能优化 —— 前端性能分析 Chrome DevTools - 性能监控

  5. 通过chrome浏览器分析网页加载时间

    今天趁着下班的时间看了下chrome浏览器的网页加载时间分析工具和相关文档,简单写点儿东西记录一下. 以百度首页加载为例,分析下一张图片1.jgp(就是背景图)的加载时间 看右侧的Timing标签,从 ...

  6. Chrome性能分析工具lightHouse用法指南

    本文主要讲如何使用Chrome开发者工具linghtHouse进行页面性能分析. 1.安装插件 非常简单,点击右上角的“添加至Chrome”即可. 2.使用方式 1)打开要测试的页面,点击浏览器右上角 ...

  7. Wappalyzer(chrome网站分析插件)

    Wappalyzer是一款功能强大的.且非常实用的chrome网站技术分析插件,通过该插件能够分析目标网站所采用的平台构架. 网站环境.服务器配置环境.JavaScript框架.编程语言等参数,使用时 ...

  8. Chrome性能分析工具Coverage使用方法

    操作路径如下: 打开控制台-->点击‘Sources’-->ctrl+shift+p-->在命令窗口输入coverage-->在下边新出现的窗口中点击左上角刷新按钮. 界面如下 ...

  9. 使用Chrome逆向分析JS实战---分析google网站翻译器原文存放位置

    剧透:就是使用了一下Chrome DevTools的Memory功能,通过已知的JS变量的值查找JS内存中变量的引用 一:不分析一下现有的网页翻译方法么? 总所周知,(As is well known ...

随机推荐

  1. React学习之一:React初探

    一,React简介 React是由Facebook和Instagram开发的一套创建用户界面的JavaScript库.许多人认为React是MVC中的V. React创建的目的是为了:构建数据随时会改 ...

  2. 【转载】大数据量传输时配置WCF的注意事项

    WCF传输数据量的能力受到许多因素的制约,如果程序中出现因需要传输的数据量较大而导致调用WCF服务失败的问题,应注意以下配置: 1.MaxReceivedMessageSize:获取或设置配置了此绑定 ...

  3. python json学习之路2-认识python种的json模块

    1.从python原始类型向json类型的转化过程,具体的转化对照如下: 2.从json到python的类型转化对照如下: 3.json提供四个功能:dumps, dump, loads, load ...

  4. Jquery easyui中的有效性检查

    使用过程中的一积累,备查. EasyUI 验证框使用方法: //*************************** missingMessage:未填写时显示的信息 validType:验证类型见 ...

  5. 开源PLM软件Aras详解一 安装

    对于Aras,一定很多人陌生,Aras Innovator是开源的PLM系统,优点就是免费license,没有节点限制,最棒的是基于SOAP,扩展性非常强,但是国内很多想入手的人入门很难, 关于Ara ...

  6. Oracle题目

    1. 创建一个函数fun_sal,该函数根据部门号获得该部门下所有员工的平均工资Create or replace function fun_sal(deptnos number)return var ...

  7. Python:print显示颜色

    显示颜色格式:\033[显示方式;字体色;背景色m......[\033[0m] ------------------------------------------- --------------- ...

  8. 使用 IntraWeb (38) - TIWAppForm、TIWForm、TIWBaseHTMLForm、TIWBaseForm

    窗体 TIWAppForm 所在单元及继承链: IWAppForm.TIWAppForm 主要成员: property OnURLRequest: TOnURLRequest //响应下面的 DoUR ...

  9. acm入门编成题

    http://wenku.baidu.com/view/c8f2f64acf84b9d528ea7aee.html

  10. GNU M4 - GNU Project - 免费软件基金会(FSF)

    -------------------------------------------------------------------------------------- GNU M4介绍: GNU ...