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 <map> | 7 #include <map> |
8 | 8 |
9 #include "base/i18n/bidi_line_iterator.h" | 9 #include "base/i18n/bidi_line_iterator.h" |
10 #include "base/i18n/break_iterator.h" | 10 #include "base/i18n/break_iterator.h" |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
261 | 261 |
262 hb_face_t* get() { | 262 hb_face_t* get() { |
263 return face_; | 263 return face_; |
264 } | 264 } |
265 | 265 |
266 private: | 266 private: |
267 hb_face_t* face_; | 267 hb_face_t* face_; |
268 }; | 268 }; |
269 | 269 |
270 // Creates a HarfBuzz font from the given Skia face and text size. | 270 // Creates a HarfBuzz font from the given Skia face and text size. |
271 hb_font_t* CreateHarfBuzzFont(SkTypeface* skia_face, int text_size) { | 271 hb_font_t* CreateHarfBuzzFont(SkTypeface* skia_face, |
272 int text_size, | |
273 const FontRenderParams& params) { | |
272 typedef std::pair<HarfBuzzFace, GlyphCache> FaceCache; | 274 typedef std::pair<HarfBuzzFace, GlyphCache> FaceCache; |
273 | 275 |
274 // TODO(ckocagil): This shouldn't grow indefinitely. Maybe use base::MRUCache? | 276 // TODO(ckocagil): This shouldn't grow indefinitely. Maybe use base::MRUCache? |
275 static std::map<SkFontID, FaceCache> face_caches; | 277 static std::map<SkFontID, FaceCache> face_caches; |
276 | 278 |
277 FaceCache* face_cache = &face_caches[skia_face->uniqueID()]; | 279 FaceCache* face_cache = &face_caches[skia_face->uniqueID()]; |
278 if (face_cache->first.get() == NULL) | 280 if (face_cache->first.get() == NULL) |
279 face_cache->first.Init(skia_face); | 281 face_cache->first.Init(skia_face); |
280 | 282 |
281 hb_font_t* harfbuzz_font = hb_font_create(face_cache->first.get()); | 283 hb_font_t* harfbuzz_font = hb_font_create(face_cache->first.get()); |
282 const int scale = SkScalarToFixed(text_size); | 284 const int scale = SkScalarToFixed(text_size); |
283 hb_font_set_scale(harfbuzz_font, scale, scale); | 285 hb_font_set_scale(harfbuzz_font, scale, scale); |
284 FontData* hb_font_data = new FontData(&face_cache->second); | 286 FontData* hb_font_data = new FontData(&face_cache->second); |
285 hb_font_data->paint_.setTypeface(skia_face); | 287 hb_font_data->paint_.setTypeface(skia_face); |
286 hb_font_data->paint_.setTextSize(text_size); | 288 hb_font_data->paint_.setTextSize(text_size); |
289 // TODO(ckocagil): Do we need to update these params later? | |
290 internal::ApplyRenderParams(params, &hb_font_data->paint_); | |
287 hb_font_set_funcs(harfbuzz_font, g_font_funcs.Get().get(), hb_font_data, | 291 hb_font_set_funcs(harfbuzz_font, g_font_funcs.Get().get(), hb_font_data, |
288 DeleteByType<FontData>); | 292 DeleteByType<FontData>); |
289 hb_font_make_immutable(harfbuzz_font); | 293 hb_font_make_immutable(harfbuzz_font); |
290 return harfbuzz_font; | 294 return harfbuzz_font; |
291 } | 295 } |
292 | 296 |
293 // Returns true if characters of |block_code| may trigger font fallback. | 297 // Returns true if characters of |block_code| may trigger font fallback. |
294 bool IsUnusualBlockCode(UBlockCode block_code) { | 298 bool IsUnusualBlockCode(UBlockCode block_code) { |
295 return block_code == UBLOCK_GEOMETRIC_SHAPES || | 299 return block_code == UBLOCK_GEOMETRIC_SHAPES || |
296 block_code == UBLOCK_MISCELLANEOUS_SYMBOLS; | 300 block_code == UBLOCK_MISCELLANEOUS_SYMBOLS; |
(...skipping 568 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
865 } | 869 } |
866 } | 870 } |
867 | 871 |
868 void RenderTextHarfBuzz::DrawVisualText(Canvas* canvas) { | 872 void RenderTextHarfBuzz::DrawVisualText(Canvas* canvas) { |
869 DCHECK(!needs_layout_); | 873 DCHECK(!needs_layout_); |
870 internal::SkiaTextRenderer renderer(canvas); | 874 internal::SkiaTextRenderer renderer(canvas); |
871 ApplyFadeEffects(&renderer); | 875 ApplyFadeEffects(&renderer); |
872 ApplyTextShadows(&renderer); | 876 ApplyTextShadows(&renderer); |
873 | 877 |
874 #if defined(OS_WIN) || defined(OS_LINUX) | 878 #if defined(OS_WIN) || defined(OS_LINUX) |
875 renderer.SetFontRenderParams( | 879 renderer.SetFontRenderParams( |
msw
2014/08/15 19:21:17
Can we somehow use the run-specific |hb_font_data-
ckocagil
2014/08/15 22:28:01
We're now calculating FontRenderParams once while
msw
2014/08/16 00:30:11
Nice.
| |
876 font_list().GetPrimaryFont().GetFontRenderParams(), | 880 font_list().GetPrimaryFont().GetFontRenderParams(), |
877 background_is_transparent()); | 881 background_is_transparent()); |
878 #endif | 882 #endif |
879 | 883 |
880 ApplyCompositionAndSelectionStyles(); | 884 ApplyCompositionAndSelectionStyles(); |
881 | 885 |
882 int current_x = 0; | 886 int current_x = 0; |
883 const Vector2d line_offset = GetLineOffset(0); | 887 const Vector2d line_offset = GetLineOffset(0); |
884 for (size_t i = 0; i < runs_.size(); ++i) { | 888 for (size_t i = 0; i < runs_.size(); ++i) { |
885 const internal::TextRunHarfBuzz& run = *runs_[visual_to_logical_[i]]; | 889 const internal::TextRunHarfBuzz& run = *runs_[visual_to_logical_[i]]; |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1105 } | 1109 } |
1106 | 1110 |
1107 bool RenderTextHarfBuzz::ShapeRunWithFont(internal::TextRunHarfBuzz* run, | 1111 bool RenderTextHarfBuzz::ShapeRunWithFont(internal::TextRunHarfBuzz* run, |
1108 const std::string& font_family) { | 1112 const std::string& font_family) { |
1109 const base::string16& text = GetLayoutText(); | 1113 const base::string16& text = GetLayoutText(); |
1110 skia::RefPtr<SkTypeface> skia_face = | 1114 skia::RefPtr<SkTypeface> skia_face = |
1111 internal::CreateSkiaTypeface(font_family, run->font_style); | 1115 internal::CreateSkiaTypeface(font_family, run->font_style); |
1112 if (skia_face == NULL) | 1116 if (skia_face == NULL) |
1113 return false; | 1117 return false; |
1114 run->skia_face = skia_face; | 1118 run->skia_face = skia_face; |
1119 FontRenderParamsQuery query(false); | |
1120 query.families.push_back(font_family); | |
1121 query.pixel_size = run->font_size; | |
1122 query.style = run->font_style; | |
1123 FontRenderParams params = GetFontRenderParams(query, NULL); | |
1124 if (background_is_transparent()) | |
1125 params.subpixel_rendering = FontRenderParams::SUBPIXEL_RENDERING_NONE; | |
Daniel Erat
2014/08/15 18:34:25
can you make ApplyRenderParams() check whether the
ckocagil
2014/08/15 19:05:57
ApplyRenderParams doesn't know whether the backgro
msw
2014/08/15 19:21:17
I wonder if the pattern here is correct, given how
ckocagil
2014/08/15 22:28:01
gfx::Font (as it currently is) is kinda heavyweigh
msw
2014/08/16 00:30:11
Acknowledged; if you see a specific reason to add
| |
1115 hb_font_t* harfbuzz_font = CreateHarfBuzzFont(run->skia_face.get(), | 1126 hb_font_t* harfbuzz_font = CreateHarfBuzzFont(run->skia_face.get(), |
1116 run->font_size); | 1127 run->font_size, params); |
1117 | 1128 |
1118 // Create a HarfBuzz buffer and add the string to be shaped. The HarfBuzz | 1129 // Create a HarfBuzz buffer and add the string to be shaped. The HarfBuzz |
1119 // buffer holds our text, run information to be used by the shaping engine, | 1130 // buffer holds our text, run information to be used by the shaping engine, |
1120 // and the resulting glyph data. | 1131 // and the resulting glyph data. |
1121 hb_buffer_t* buffer = hb_buffer_create(); | 1132 hb_buffer_t* buffer = hb_buffer_create(); |
1122 hb_buffer_add_utf16(buffer, reinterpret_cast<const uint16*>(text.c_str()), | 1133 hb_buffer_add_utf16(buffer, reinterpret_cast<const uint16*>(text.c_str()), |
1123 text.length(), run->range.start(), run->range.length()); | 1134 text.length(), run->range.start(), run->range.length()); |
1124 hb_buffer_set_script(buffer, ICUScriptToHBScript(run->script)); | 1135 hb_buffer_set_script(buffer, ICUScriptToHBScript(run->script)); |
1125 hb_buffer_set_direction(buffer, | 1136 hb_buffer_set_direction(buffer, |
1126 run->is_rtl ? HB_DIRECTION_RTL : HB_DIRECTION_LTR); | 1137 run->is_rtl ? HB_DIRECTION_RTL : HB_DIRECTION_LTR); |
(...skipping 13 matching lines...) Expand all Loading... | |
1140 run->glyph_to_char.resize(run->glyph_count); | 1151 run->glyph_to_char.resize(run->glyph_count); |
1141 run->positions.reset(new SkPoint[run->glyph_count]); | 1152 run->positions.reset(new SkPoint[run->glyph_count]); |
1142 run->width = 0.0f; | 1153 run->width = 0.0f; |
1143 for (size_t i = 0; i < run->glyph_count; ++i) { | 1154 for (size_t i = 0; i < run->glyph_count; ++i) { |
1144 run->glyphs[i] = infos[i].codepoint; | 1155 run->glyphs[i] = infos[i].codepoint; |
1145 run->glyph_to_char[i] = infos[i].cluster; | 1156 run->glyph_to_char[i] = infos[i].cluster; |
1146 const int x_offset = SkFixedToScalar(hb_positions[i].x_offset); | 1157 const int x_offset = SkFixedToScalar(hb_positions[i].x_offset); |
1147 const int y_offset = SkFixedToScalar(hb_positions[i].y_offset); | 1158 const int y_offset = SkFixedToScalar(hb_positions[i].y_offset); |
1148 run->positions[i].set(run->width + x_offset, -y_offset); | 1159 run->positions[i].set(run->width + x_offset, -y_offset); |
1149 run->width += SkFixedToScalar(hb_positions[i].x_advance); | 1160 run->width += SkFixedToScalar(hb_positions[i].x_advance); |
1161 run->width = std::floor(run->width + 0.5f); | |
msw
2014/08/15 19:21:17
Whoa, this seems really bad... This rounds the run
ckocagil
2014/08/15 22:28:01
This rounding is needed to place the glyphs at int
msw
2014/08/16 00:30:11
Yuck, please add a comment then. Would we get the
ckocagil
2014/08/16 14:01:14
Subpixel positioning seems to be always disabled o
| |
1150 } | 1162 } |
1151 | 1163 |
1152 hb_buffer_destroy(buffer); | 1164 hb_buffer_destroy(buffer); |
1153 hb_font_destroy(harfbuzz_font); | 1165 hb_font_destroy(harfbuzz_font); |
1154 return true; | 1166 return true; |
1155 } | 1167 } |
1156 | 1168 |
1157 } // namespace gfx | 1169 } // namespace gfx |
OLD | NEW |