OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/gfx/render_text_harfbuzz.h" | 5 #include "ui/gfx/render_text_harfbuzz.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 #include <map> | 8 #include <map> |
9 | 9 |
10 #include "base/i18n/bidi_line_iterator.h" | 10 #include "base/i18n/bidi_line_iterator.h" |
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 | 262 |
263 hb_face_t* get() { | 263 hb_face_t* get() { |
264 return face_; | 264 return face_; |
265 } | 265 } |
266 | 266 |
267 private: | 267 private: |
268 hb_face_t* face_; | 268 hb_face_t* face_; |
269 }; | 269 }; |
270 | 270 |
271 // Creates a HarfBuzz font from the given Skia face and text size. | 271 // Creates a HarfBuzz font from the given Skia face and text size. |
272 hb_font_t* CreateHarfBuzzFont(SkTypeface* skia_face, int text_size) { | 272 hb_font_t* CreateHarfBuzzFont(SkTypeface* skia_face, |
| 273 int text_size, |
| 274 const FontRenderParams& params, |
| 275 bool background_is_transparent) { |
273 typedef std::pair<HarfBuzzFace, GlyphCache> FaceCache; | 276 typedef std::pair<HarfBuzzFace, GlyphCache> FaceCache; |
274 | 277 |
275 // TODO(ckocagil): This shouldn't grow indefinitely. Maybe use base::MRUCache? | 278 // TODO(ckocagil): This shouldn't grow indefinitely. Maybe use base::MRUCache? |
276 static std::map<SkFontID, FaceCache> face_caches; | 279 static std::map<SkFontID, FaceCache> face_caches; |
277 | 280 |
278 FaceCache* face_cache = &face_caches[skia_face->uniqueID()]; | 281 FaceCache* face_cache = &face_caches[skia_face->uniqueID()]; |
279 if (face_cache->first.get() == NULL) | 282 if (face_cache->first.get() == NULL) |
280 face_cache->first.Init(skia_face); | 283 face_cache->first.Init(skia_face); |
281 | 284 |
282 hb_font_t* harfbuzz_font = hb_font_create(face_cache->first.get()); | 285 hb_font_t* harfbuzz_font = hb_font_create(face_cache->first.get()); |
283 const int scale = SkScalarToFixed(text_size); | 286 const int scale = SkScalarToFixed(text_size); |
284 hb_font_set_scale(harfbuzz_font, scale, scale); | 287 hb_font_set_scale(harfbuzz_font, scale, scale); |
285 FontData* hb_font_data = new FontData(&face_cache->second); | 288 FontData* hb_font_data = new FontData(&face_cache->second); |
286 hb_font_data->paint_.setTypeface(skia_face); | 289 hb_font_data->paint_.setTypeface(skia_face); |
287 hb_font_data->paint_.setTextSize(text_size); | 290 hb_font_data->paint_.setTextSize(text_size); |
| 291 // TODO(ckocagil): Do we need to update these params later? |
| 292 internal::ApplyRenderParams(params, background_is_transparent, |
| 293 &hb_font_data->paint_); |
288 hb_font_set_funcs(harfbuzz_font, g_font_funcs.Get().get(), hb_font_data, | 294 hb_font_set_funcs(harfbuzz_font, g_font_funcs.Get().get(), hb_font_data, |
289 DeleteByType<FontData>); | 295 DeleteByType<FontData>); |
290 hb_font_make_immutable(harfbuzz_font); | 296 hb_font_make_immutable(harfbuzz_font); |
291 return harfbuzz_font; | 297 return harfbuzz_font; |
292 } | 298 } |
293 | 299 |
294 // Returns true if characters of |block_code| may trigger font fallback. | 300 // Returns true if characters of |block_code| may trigger font fallback. |
295 bool IsUnusualBlockCode(UBlockCode block_code) { | 301 bool IsUnusualBlockCode(UBlockCode block_code) { |
296 return block_code == UBLOCK_GEOMETRIC_SHAPES || | 302 return block_code == UBLOCK_GEOMETRIC_SHAPES || |
297 block_code == UBLOCK_MISCELLANEOUS_SYMBOLS; | 303 block_code == UBLOCK_MISCELLANEOUS_SYMBOLS; |
(...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
864 | 870 |
865 set_lines(&lines); | 871 set_lines(&lines); |
866 } | 872 } |
867 } | 873 } |
868 | 874 |
869 void RenderTextHarfBuzz::DrawVisualText(Canvas* canvas) { | 875 void RenderTextHarfBuzz::DrawVisualText(Canvas* canvas) { |
870 DCHECK(!needs_layout_); | 876 DCHECK(!needs_layout_); |
871 internal::SkiaTextRenderer renderer(canvas); | 877 internal::SkiaTextRenderer renderer(canvas); |
872 ApplyFadeEffects(&renderer); | 878 ApplyFadeEffects(&renderer); |
873 ApplyTextShadows(&renderer); | 879 ApplyTextShadows(&renderer); |
874 | |
875 #if defined(OS_WIN) || defined(OS_LINUX) | |
876 renderer.SetFontRenderParams( | |
877 font_list().GetPrimaryFont().GetFontRenderParams(), | |
878 background_is_transparent()); | |
879 #endif | |
880 | |
881 ApplyCompositionAndSelectionStyles(); | 880 ApplyCompositionAndSelectionStyles(); |
882 | 881 |
883 int current_x = 0; | 882 int current_x = 0; |
884 const Vector2d line_offset = GetLineOffset(0); | 883 const Vector2d line_offset = GetLineOffset(0); |
885 for (size_t i = 0; i < runs_.size(); ++i) { | 884 for (size_t i = 0; i < runs_.size(); ++i) { |
886 const internal::TextRunHarfBuzz& run = *runs_[visual_to_logical_[i]]; | 885 const internal::TextRunHarfBuzz& run = *runs_[visual_to_logical_[i]]; |
887 renderer.SetTypeface(run.skia_face.get()); | 886 renderer.SetTypeface(run.skia_face.get()); |
888 renderer.SetTextSize(run.font_size); | 887 renderer.SetTextSize(run.font_size); |
| 888 renderer.SetFontRenderParams(run.render_params, |
| 889 background_is_transparent()); |
889 | 890 |
890 Vector2d origin = line_offset + Vector2d(current_x, lines()[0].baseline); | 891 Vector2d origin = line_offset + Vector2d(current_x, lines()[0].baseline); |
891 scoped_ptr<SkPoint[]> positions(new SkPoint[run.glyph_count]); | 892 scoped_ptr<SkPoint[]> positions(new SkPoint[run.glyph_count]); |
892 for (size_t j = 0; j < run.glyph_count; ++j) { | 893 for (size_t j = 0; j < run.glyph_count; ++j) { |
893 positions[j] = run.positions[j]; | 894 positions[j] = run.positions[j]; |
894 positions[j].offset(SkIntToScalar(origin.x()), SkIntToScalar(origin.y())); | 895 positions[j].offset(SkIntToScalar(origin.x()), SkIntToScalar(origin.y())); |
895 } | 896 } |
896 | 897 |
897 for (BreakList<SkColor>::const_iterator it = | 898 for (BreakList<SkColor>::const_iterator it = |
898 colors().GetBreak(run.range.start()); | 899 colors().GetBreak(run.range.start()); |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1106 } | 1107 } |
1107 | 1108 |
1108 bool RenderTextHarfBuzz::ShapeRunWithFont(internal::TextRunHarfBuzz* run, | 1109 bool RenderTextHarfBuzz::ShapeRunWithFont(internal::TextRunHarfBuzz* run, |
1109 const std::string& font_family) { | 1110 const std::string& font_family) { |
1110 const base::string16& text = GetLayoutText(); | 1111 const base::string16& text = GetLayoutText(); |
1111 skia::RefPtr<SkTypeface> skia_face = | 1112 skia::RefPtr<SkTypeface> skia_face = |
1112 internal::CreateSkiaTypeface(font_family, run->font_style); | 1113 internal::CreateSkiaTypeface(font_family, run->font_style); |
1113 if (skia_face == NULL) | 1114 if (skia_face == NULL) |
1114 return false; | 1115 return false; |
1115 run->skia_face = skia_face; | 1116 run->skia_face = skia_face; |
| 1117 FontRenderParamsQuery query(false); |
| 1118 query.families.push_back(font_family); |
| 1119 query.pixel_size = run->font_size; |
| 1120 query.style = run->font_style; |
| 1121 run->render_params = GetFontRenderParams(query, NULL); |
1116 hb_font_t* harfbuzz_font = CreateHarfBuzzFont(run->skia_face.get(), | 1122 hb_font_t* harfbuzz_font = CreateHarfBuzzFont(run->skia_face.get(), |
1117 run->font_size); | 1123 run->font_size, run->render_params, background_is_transparent()); |
1118 | 1124 |
1119 // Create a HarfBuzz buffer and add the string to be shaped. The HarfBuzz | 1125 // Create a HarfBuzz buffer and add the string to be shaped. The HarfBuzz |
1120 // buffer holds our text, run information to be used by the shaping engine, | 1126 // buffer holds our text, run information to be used by the shaping engine, |
1121 // and the resulting glyph data. | 1127 // and the resulting glyph data. |
1122 hb_buffer_t* buffer = hb_buffer_create(); | 1128 hb_buffer_t* buffer = hb_buffer_create(); |
1123 hb_buffer_add_utf16(buffer, reinterpret_cast<const uint16*>(text.c_str()), | 1129 hb_buffer_add_utf16(buffer, reinterpret_cast<const uint16*>(text.c_str()), |
1124 text.length(), run->range.start(), run->range.length()); | 1130 text.length(), run->range.start(), run->range.length()); |
1125 hb_buffer_set_script(buffer, ICUScriptToHBScript(run->script)); | 1131 hb_buffer_set_script(buffer, ICUScriptToHBScript(run->script)); |
1126 hb_buffer_set_direction(buffer, | 1132 hb_buffer_set_direction(buffer, |
1127 run->is_rtl ? HB_DIRECTION_RTL : HB_DIRECTION_LTR); | 1133 run->is_rtl ? HB_DIRECTION_RTL : HB_DIRECTION_LTR); |
(...skipping 13 matching lines...) Expand all Loading... |
1141 run->glyph_to_char.resize(run->glyph_count); | 1147 run->glyph_to_char.resize(run->glyph_count); |
1142 run->positions.reset(new SkPoint[run->glyph_count]); | 1148 run->positions.reset(new SkPoint[run->glyph_count]); |
1143 run->width = 0.0f; | 1149 run->width = 0.0f; |
1144 for (size_t i = 0; i < run->glyph_count; ++i) { | 1150 for (size_t i = 0; i < run->glyph_count; ++i) { |
1145 run->glyphs[i] = infos[i].codepoint; | 1151 run->glyphs[i] = infos[i].codepoint; |
1146 run->glyph_to_char[i] = infos[i].cluster; | 1152 run->glyph_to_char[i] = infos[i].cluster; |
1147 const int x_offset = SkFixedToScalar(hb_positions[i].x_offset); | 1153 const int x_offset = SkFixedToScalar(hb_positions[i].x_offset); |
1148 const int y_offset = SkFixedToScalar(hb_positions[i].y_offset); | 1154 const int y_offset = SkFixedToScalar(hb_positions[i].y_offset); |
1149 run->positions[i].set(run->width + x_offset, -y_offset); | 1155 run->positions[i].set(run->width + x_offset, -y_offset); |
1150 run->width += SkFixedToScalar(hb_positions[i].x_advance); | 1156 run->width += SkFixedToScalar(hb_positions[i].x_advance); |
| 1157 #if defined(OS_LINUX) |
| 1158 // Match Pango's glyph rounding logic on Linux. |
| 1159 if (!run->render_params.subpixel_positioning) |
| 1160 run->width = std::floor(run->width + 0.5f); |
| 1161 #endif |
1151 } | 1162 } |
1152 | 1163 |
1153 hb_buffer_destroy(buffer); | 1164 hb_buffer_destroy(buffer); |
1154 hb_font_destroy(harfbuzz_font); | 1165 hb_font_destroy(harfbuzz_font); |
1155 return true; | 1166 return true; |
1156 } | 1167 } |
1157 | 1168 |
1158 } // namespace gfx | 1169 } // namespace gfx |
OLD | NEW |