Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: ui/gfx/render_text_harfbuzz.cc

Issue 660953002: Type conversion fixes, text rendering edition. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix test Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/gfx/render_text.cc ('k') | ui/gfx/render_text_win.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
64 Type* typed_data = reinterpret_cast<Type*>(data); 64 Type* typed_data = reinterpret_cast<Type*>(data);
65 delete[] typed_data; 65 delete[] typed_data;
66 } 66 }
67 67
68 // Outputs the |width| and |extents| of the glyph with index |codepoint| in 68 // Outputs the |width| and |extents| of the glyph with index |codepoint| in
69 // |paint|'s font. 69 // |paint|'s font.
70 void GetGlyphWidthAndExtents(SkPaint* paint, 70 void GetGlyphWidthAndExtents(SkPaint* paint,
71 hb_codepoint_t codepoint, 71 hb_codepoint_t codepoint,
72 hb_position_t* width, 72 hb_position_t* width,
73 hb_glyph_extents_t* extents) { 73 hb_glyph_extents_t* extents) {
74 DCHECK_LE(codepoint, 0xFFFFU); 74 DCHECK_LE(codepoint, std::numeric_limits<uint16>::max());
75 paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding); 75 paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
76 76
77 SkScalar sk_width; 77 SkScalar sk_width;
78 SkRect sk_bounds; 78 SkRect sk_bounds;
79 uint16_t glyph = codepoint; 79 uint16_t glyph = static_cast<uint16_t>(codepoint);
80 80
81 paint->getTextWidths(&glyph, sizeof(glyph), &sk_width, &sk_bounds); 81 paint->getTextWidths(&glyph, sizeof(glyph), &sk_width, &sk_bounds);
82 if (width) 82 if (width)
83 *width = SkiaScalarToHarfBuzzPosition(sk_width); 83 *width = SkiaScalarToHarfBuzzPosition(sk_width);
84 if (extents) { 84 if (extents) {
85 // Invert y-axis because Skia is y-grows-down but we set up HarfBuzz to be 85 // Invert y-axis because Skia is y-grows-down but we set up HarfBuzz to be
86 // y-grows-up. 86 // y-grows-up.
87 extents->x_bearing = SkiaScalarToHarfBuzzPosition(sk_bounds.fLeft); 87 extents->x_bearing = SkiaScalarToHarfBuzzPosition(sk_bounds.fLeft);
88 extents->y_bearing = SkiaScalarToHarfBuzzPosition(-sk_bounds.fTop); 88 extents->y_bearing = SkiaScalarToHarfBuzzPosition(-sk_bounds.fTop);
89 extents->width = SkiaScalarToHarfBuzzPosition(sk_bounds.width()); 89 extents->width = SkiaScalarToHarfBuzzPosition(sk_bounds.width());
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
266 hb_face_t* get() { 266 hb_face_t* get() {
267 return face_; 267 return face_;
268 } 268 }
269 269
270 private: 270 private:
271 hb_face_t* face_; 271 hb_face_t* face_;
272 }; 272 };
273 273
274 // Creates a HarfBuzz font from the given Skia face and text size. 274 // Creates a HarfBuzz font from the given Skia face and text size.
275 hb_font_t* CreateHarfBuzzFont(SkTypeface* skia_face, 275 hb_font_t* CreateHarfBuzzFont(SkTypeface* skia_face,
276 int text_size, 276 SkScalar text_size,
277 const FontRenderParams& params, 277 const FontRenderParams& params,
278 bool background_is_transparent) { 278 bool background_is_transparent) {
279 typedef std::pair<HarfBuzzFace, GlyphCache> FaceCache; 279 typedef std::pair<HarfBuzzFace, GlyphCache> FaceCache;
280 280
281 // TODO(ckocagil): This shouldn't grow indefinitely. Maybe use base::MRUCache? 281 // TODO(ckocagil): This shouldn't grow indefinitely. Maybe use base::MRUCache?
282 static std::map<SkFontID, FaceCache> face_caches; 282 static std::map<SkFontID, FaceCache> face_caches;
283 283
284 FaceCache* face_cache = &face_caches[skia_face->uniqueID()]; 284 FaceCache* face_cache = &face_caches[skia_face->uniqueID()];
285 if (face_cache->first.get() == NULL) 285 if (face_cache->first.get() == NULL)
286 face_cache->first.Init(skia_face); 286 face_cache->first.Init(skia_face);
(...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after
875 875
876 for (size_t i = 0; i < runs_.size(); ++i) { 876 for (size_t i = 0; i < runs_.size(); ++i) {
877 const internal::TextRunHarfBuzz& run = *runs_[visual_to_logical_[i]]; 877 const internal::TextRunHarfBuzz& run = *runs_[visual_to_logical_[i]];
878 internal::LineSegment segment; 878 internal::LineSegment segment;
879 segment.x_range = Range(current_x, current_x + run.width); 879 segment.x_range = Range(current_x, current_x + run.width);
880 segment.char_range = run.range; 880 segment.char_range = run.range;
881 segment.run = i; 881 segment.run = i;
882 lines[0].segments.push_back(segment); 882 lines[0].segments.push_back(segment);
883 883
884 paint.setTypeface(run.skia_face.get()); 884 paint.setTypeface(run.skia_face.get());
885 paint.setTextSize(run.font_size); 885 paint.setTextSize(SkIntToScalar(run.font_size));
886 SkPaint::FontMetrics metrics; 886 SkPaint::FontMetrics metrics;
887 paint.getFontMetrics(&metrics); 887 paint.getFontMetrics(&metrics);
888 888
889 lines[0].size.set_width(lines[0].size.width() + run.width); 889 lines[0].size.set_width(lines[0].size.width() + run.width);
890 lines[0].size.set_height(std::max(lines[0].size.height(), 890 lines[0].size.set_height(std::max(lines[0].size.height(),
891 metrics.fDescent - metrics.fAscent)); 891 metrics.fDescent - metrics.fAscent));
892 lines[0].baseline = std::max(lines[0].baseline, 892 lines[0].baseline = std::max(lines[0].baseline,
893 SkScalarRoundToInt(-metrics.fAscent)); 893 SkScalarRoundToInt(-metrics.fAscent));
894 } 894 }
895 895
896 set_lines(&lines); 896 set_lines(&lines);
897 } 897 }
898 } 898 }
899 899
900 void RenderTextHarfBuzz::DrawVisualText(Canvas* canvas) { 900 void RenderTextHarfBuzz::DrawVisualText(Canvas* canvas) {
901 DCHECK(!needs_layout_); 901 DCHECK(!needs_layout_);
902 internal::SkiaTextRenderer renderer(canvas); 902 internal::SkiaTextRenderer renderer(canvas);
903 ApplyFadeEffects(&renderer); 903 ApplyFadeEffects(&renderer);
904 ApplyTextShadows(&renderer); 904 ApplyTextShadows(&renderer);
905 ApplyCompositionAndSelectionStyles(); 905 ApplyCompositionAndSelectionStyles();
906 906
907 int current_x = 0; 907 int current_x = 0;
908 const Vector2d line_offset = GetLineOffset(0); 908 const Vector2d line_offset = GetLineOffset(0);
909 for (size_t i = 0; i < runs_.size(); ++i) { 909 for (size_t i = 0; i < runs_.size(); ++i) {
910 const internal::TextRunHarfBuzz& run = *runs_[visual_to_logical_[i]]; 910 const internal::TextRunHarfBuzz& run = *runs_[visual_to_logical_[i]];
911 renderer.SetTypeface(run.skia_face.get()); 911 renderer.SetTypeface(run.skia_face.get());
912 renderer.SetTextSize(run.font_size); 912 renderer.SetTextSize(SkIntToScalar(run.font_size));
913 renderer.SetFontRenderParams(run.render_params, 913 renderer.SetFontRenderParams(run.render_params,
914 background_is_transparent()); 914 background_is_transparent());
915 915
916 Vector2d origin = line_offset + Vector2d(current_x, lines()[0].baseline); 916 Vector2d origin = line_offset + Vector2d(current_x, lines()[0].baseline);
917 scoped_ptr<SkPoint[]> positions(new SkPoint[run.glyph_count]); 917 scoped_ptr<SkPoint[]> positions(new SkPoint[run.glyph_count]);
918 for (size_t j = 0; j < run.glyph_count; ++j) { 918 for (size_t j = 0; j < run.glyph_count; ++j) {
919 positions[j] = run.positions[j]; 919 positions[j] = run.positions[j];
920 positions[j].offset(SkIntToScalar(origin.x()), SkIntToScalar(origin.y())); 920 positions[j].offset(SkIntToScalar(origin.x()), SkIntToScalar(origin.y()));
921 } 921 }
922 922
923 for (BreakList<SkColor>::const_iterator it = 923 for (BreakList<SkColor>::const_iterator it =
924 colors().GetBreak(run.range.start()); 924 colors().GetBreak(run.range.start());
925 it != colors().breaks().end() && it->first < run.range.end(); 925 it != colors().breaks().end() && it->first < run.range.end();
926 ++it) { 926 ++it) {
927 const Range intersection = colors().GetRange(it).Intersect(run.range); 927 const Range intersection = colors().GetRange(it).Intersect(run.range);
928 const Range colored_glyphs = run.CharRangeToGlyphRange(intersection); 928 const Range colored_glyphs = run.CharRangeToGlyphRange(intersection);
929 // The range may be empty if a portion of a multi-character grapheme is 929 // The range may be empty if a portion of a multi-character grapheme is
930 // selected, yielding two colors for a single glyph. For now, this just 930 // selected, yielding two colors for a single glyph. For now, this just
931 // paints the glyph with a single style, but it should paint it twice, 931 // paints the glyph with a single style, but it should paint it twice,
932 // clipped according to selection bounds. See http://crbug.com/366786 932 // clipped according to selection bounds. See http://crbug.com/366786
933 if (colored_glyphs.is_empty()) 933 if (colored_glyphs.is_empty())
934 continue; 934 continue;
935 935
936 renderer.SetForegroundColor(it->second); 936 renderer.SetForegroundColor(it->second);
937 renderer.DrawPosText(&positions[colored_glyphs.start()], 937 renderer.DrawPosText(&positions[colored_glyphs.start()],
938 &run.glyphs[colored_glyphs.start()], 938 &run.glyphs[colored_glyphs.start()],
939 colored_glyphs.length()); 939 colored_glyphs.length());
940 int width = (colored_glyphs.end() == run.glyph_count ? run.width : 940 int start_x = SkScalarRoundToInt(positions[colored_glyphs.start()].x());
941 run.positions[colored_glyphs.end()].x()) - 941 int end_x = SkScalarRoundToInt((colored_glyphs.end() == run.glyph_count) ?
942 run.positions[colored_glyphs.start()].x(); 942 (run.width + SkIntToScalar(origin.x())) :
943 renderer.DrawDecorations(origin.x(), origin.y(), width, run.underline, 943 positions[colored_glyphs.end()].x());
944 run.strike, run.diagonal_strike); 944 renderer.DrawDecorations(start_x, origin.y(), end_x - start_x,
945 run.underline, run.strike, run.diagonal_strike);
945 } 946 }
946 947
947 current_x += run.width; 948 current_x += run.width;
948 } 949 }
949 950
950 renderer.EndDiagonalStrike(); 951 renderer.EndDiagonalStrike();
951 952
952 UndoCompositionAndSelectionStyles(); 953 UndoCompositionAndSelectionStyles();
953 } 954 }
954 955
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
1138 skia::RefPtr<SkTypeface> skia_face = 1139 skia::RefPtr<SkTypeface> skia_face =
1139 internal::CreateSkiaTypeface(font_family, run->font_style); 1140 internal::CreateSkiaTypeface(font_family, run->font_style);
1140 if (skia_face == NULL) 1141 if (skia_face == NULL)
1141 return false; 1142 return false;
1142 run->skia_face = skia_face; 1143 run->skia_face = skia_face;
1143 FontRenderParamsQuery query(false); 1144 FontRenderParamsQuery query(false);
1144 query.families.push_back(font_family); 1145 query.families.push_back(font_family);
1145 query.pixel_size = run->font_size; 1146 query.pixel_size = run->font_size;
1146 query.style = run->font_style; 1147 query.style = run->font_style;
1147 run->render_params = GetFontRenderParams(query, NULL); 1148 run->render_params = GetFontRenderParams(query, NULL);
1148 hb_font_t* harfbuzz_font = CreateHarfBuzzFont(run->skia_face.get(), 1149 hb_font_t* harfbuzz_font = CreateHarfBuzzFont(
1149 run->font_size, run->render_params, background_is_transparent()); 1150 run->skia_face.get(), SkIntToScalar(run->font_size), run->render_params,
1151 background_is_transparent());
1150 1152
1151 // Create a HarfBuzz buffer and add the string to be shaped. The HarfBuzz 1153 // Create a HarfBuzz buffer and add the string to be shaped. The HarfBuzz
1152 // buffer holds our text, run information to be used by the shaping engine, 1154 // buffer holds our text, run information to be used by the shaping engine,
1153 // and the resulting glyph data. 1155 // and the resulting glyph data.
1154 hb_buffer_t* buffer = hb_buffer_create(); 1156 hb_buffer_t* buffer = hb_buffer_create();
1155 hb_buffer_add_utf16(buffer, reinterpret_cast<const uint16*>(text.c_str()), 1157 hb_buffer_add_utf16(buffer, reinterpret_cast<const uint16*>(text.c_str()),
1156 text.length(), run->range.start(), run->range.length()); 1158 text.length(), run->range.start(), run->range.length());
1157 hb_buffer_set_script(buffer, ICUScriptToHBScript(run->script)); 1159 hb_buffer_set_script(buffer, ICUScriptToHBScript(run->script));
1158 hb_buffer_set_direction(buffer, 1160 hb_buffer_set_direction(buffer,
1159 run->is_rtl ? HB_DIRECTION_RTL : HB_DIRECTION_LTR); 1161 run->is_rtl ? HB_DIRECTION_RTL : HB_DIRECTION_LTR);
1160 // TODO(ckocagil): Should we determine the actual language? 1162 // TODO(ckocagil): Should we determine the actual language?
1161 hb_buffer_set_language(buffer, hb_language_get_default()); 1163 hb_buffer_set_language(buffer, hb_language_get_default());
1162 1164
1163 // Shape the text. 1165 // Shape the text.
1164 hb_shape(harfbuzz_font, buffer, NULL, 0); 1166 hb_shape(harfbuzz_font, buffer, NULL, 0);
1165 1167
1166 // Populate the run fields with the resulting glyph data in the buffer. 1168 // Populate the run fields with the resulting glyph data in the buffer.
1167 unsigned int glyph_count = 0; 1169 unsigned int glyph_count = 0;
1168 hb_glyph_info_t* infos = hb_buffer_get_glyph_infos(buffer, &glyph_count); 1170 hb_glyph_info_t* infos = hb_buffer_get_glyph_infos(buffer, &glyph_count);
1169 run->glyph_count = glyph_count; 1171 run->glyph_count = glyph_count;
1170 hb_glyph_position_t* hb_positions = 1172 hb_glyph_position_t* hb_positions =
1171 hb_buffer_get_glyph_positions(buffer, NULL); 1173 hb_buffer_get_glyph_positions(buffer, NULL);
1172 run->glyphs.reset(new uint16[run->glyph_count]); 1174 run->glyphs.reset(new uint16[run->glyph_count]);
1173 run->glyph_to_char.resize(run->glyph_count); 1175 run->glyph_to_char.resize(run->glyph_count);
1174 run->positions.reset(new SkPoint[run->glyph_count]); 1176 run->positions.reset(new SkPoint[run->glyph_count]);
1175 run->width = 0.0f; 1177 run->width = 0.0f;
1176 for (size_t i = 0; i < run->glyph_count; ++i) { 1178 for (size_t i = 0; i < run->glyph_count; ++i) {
1177 run->glyphs[i] = infos[i].codepoint; 1179 DCHECK_LE(infos[i].codepoint, std::numeric_limits<uint16>::max());
1180 run->glyphs[i] = static_cast<uint16>(infos[i].codepoint);
1178 run->glyph_to_char[i] = infos[i].cluster; 1181 run->glyph_to_char[i] = infos[i].cluster;
1179 const int x_offset = SkFixedToScalar(hb_positions[i].x_offset); 1182 const SkScalar x_offset = SkFixedToScalar(hb_positions[i].x_offset);
1180 const int y_offset = SkFixedToScalar(hb_positions[i].y_offset); 1183 const SkScalar y_offset = SkFixedToScalar(hb_positions[i].y_offset);
1181 run->positions[i].set(run->width + x_offset, -y_offset); 1184 run->positions[i].set(run->width + x_offset, -y_offset);
1182 run->width += SkFixedToScalar(hb_positions[i].x_advance); 1185 run->width += SkFixedToScalar(hb_positions[i].x_advance);
1183 #if defined(OS_LINUX) 1186 #if defined(OS_LINUX)
1184 // Match Pango's glyph rounding logic on Linux. 1187 // Match Pango's glyph rounding logic on Linux.
1185 if (!run->render_params.subpixel_positioning) 1188 if (!run->render_params.subpixel_positioning)
1186 run->width = std::floor(run->width + 0.5f); 1189 run->width = std::floor(run->width + 0.5f);
1187 #endif 1190 #endif
1188 } 1191 }
1189 1192
1190 hb_buffer_destroy(buffer); 1193 hb_buffer_destroy(buffer);
1191 hb_font_destroy(harfbuzz_font); 1194 hb_font_destroy(harfbuzz_font);
1192 return true; 1195 return true;
1193 } 1196 }
1194 1197
1195 } // namespace gfx 1198 } // namespace gfx
OLDNEW
« no previous file with comments | « ui/gfx/render_text.cc ('k') | ui/gfx/render_text_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698