OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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_pango.h" | 5 #include "ui/gfx/render_text_pango.h" |
6 | 6 |
7 #include <pango/pangocairo.h> | 7 #include <pango/pangocairo.h> |
8 #include <algorithm> | 8 #include <algorithm> |
9 #include <string> | 9 #include <string> |
10 #include <vector> | 10 #include <vector> |
(...skipping 22 matching lines...) Expand all Loading... |
33 } | 33 } |
34 | 34 |
35 // Returns true if the given visual cursor |direction| is logically forward | 35 // Returns true if the given visual cursor |direction| is logically forward |
36 // motion in the given Pango |item|. | 36 // motion in the given Pango |item|. |
37 bool IsForwardMotion(VisualCursorDirection direction, const PangoItem* item) { | 37 bool IsForwardMotion(VisualCursorDirection direction, const PangoItem* item) { |
38 bool rtl = item->analysis.level & 1; | 38 bool rtl = item->analysis.level & 1; |
39 return rtl == (direction == CURSOR_LEFT); | 39 return rtl == (direction == CURSOR_LEFT); |
40 } | 40 } |
41 | 41 |
42 // Checks whether |range| contains |index|. This is not the same as calling | 42 // Checks whether |range| contains |index|. This is not the same as calling |
43 // |range.Contains(gfx::Range(index))| - as that would return true when | 43 // range.Contains(Range(index)), which returns true if |index| == |range.end()|. |
44 // |index| == |range.end()|. | |
45 bool IndexInRange(const Range& range, size_t index) { | 44 bool IndexInRange(const Range& range, size_t index) { |
46 return index >= range.start() && index < range.end(); | 45 return index >= range.start() && index < range.end(); |
47 } | 46 } |
48 | 47 |
49 // Sets underline metrics on |renderer| according to Pango font |desc|. | 48 // Sets underline metrics on |renderer| according to Pango font |desc|. |
50 void SetPangoUnderlineMetrics(PangoFontDescription *desc, | 49 void SetPangoUnderlineMetrics(PangoFontDescription *desc, |
51 internal::SkiaTextRenderer* renderer) { | 50 internal::SkiaTextRenderer* renderer) { |
52 PangoFontMetrics* metrics = GetPangoFontMetrics(desc); | 51 PangoFontMetrics* metrics = GetPangoFontMetrics(desc); |
53 int thickness = pango_font_metrics_get_underline_thickness(metrics); | 52 int thickness = pango_font_metrics_get_underline_thickness(metrics); |
54 // Pango returns the position "above the baseline". Change its sign to convert | 53 // Pango returns the position "above the baseline". Change its sign to convert |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
242 Rect rect(x, 0, width, height); | 241 Rect rect(x, 0, width, height); |
243 rect.set_origin(ToViewPoint(rect.origin())); | 242 rect.set_origin(ToViewPoint(rect.origin())); |
244 bounds.push_back(rect); | 243 bounds.push_back(rect); |
245 } | 244 } |
246 g_free(ranges); | 245 g_free(ranges); |
247 return bounds; | 246 return bounds; |
248 } | 247 } |
249 | 248 |
250 size_t RenderTextPango::TextIndexToLayoutIndex(size_t index) const { | 249 size_t RenderTextPango::TextIndexToLayoutIndex(size_t index) const { |
251 DCHECK(layout_); | 250 DCHECK(layout_); |
252 ptrdiff_t offset = gfx::UTF16IndexToOffset(text(), 0, index); | 251 ptrdiff_t offset = UTF16IndexToOffset(text(), 0, index); |
253 // Clamp layout indices to the length of the text actually used for layout. | 252 // Clamp layout indices to the length of the text actually used for layout. |
254 offset = std::min<size_t>(offset, g_utf8_strlen(layout_text_, -1)); | 253 offset = std::min<size_t>(offset, g_utf8_strlen(layout_text_, -1)); |
255 const char* layout_pointer = g_utf8_offset_to_pointer(layout_text_, offset); | 254 const char* layout_pointer = g_utf8_offset_to_pointer(layout_text_, offset); |
256 return (layout_pointer - layout_text_); | 255 return (layout_pointer - layout_text_); |
257 } | 256 } |
258 | 257 |
259 size_t RenderTextPango::LayoutIndexToTextIndex(size_t index) const { | 258 size_t RenderTextPango::LayoutIndexToTextIndex(size_t index) const { |
260 DCHECK(layout_); | 259 DCHECK(layout_); |
261 const char* layout_pointer = layout_text_ + index; | 260 const char* layout_pointer = layout_text_ + index; |
262 const long offset = g_utf8_pointer_to_offset(layout_text_, layout_pointer); | 261 const long offset = g_utf8_pointer_to_offset(layout_text_, layout_pointer); |
263 return gfx::UTF16OffsetToIndex(text(), 0, offset); | 262 return UTF16OffsetToIndex(text(), 0, offset); |
264 } | 263 } |
265 | 264 |
266 bool RenderTextPango::IsCursorablePosition(size_t position) { | 265 bool RenderTextPango::IsValidCursorIndex(size_t index) { |
267 if (position == 0 && text().empty()) | 266 if (index == 0 || index == text().length()) |
268 return true; | 267 return true; |
269 if (position >= text().length()) | 268 if (!IsValidLogicalIndex(index)) |
270 return position == text().length(); | |
271 if (!gfx::IsValidCodePointIndex(text(), position)) | |
272 return false; | 269 return false; |
273 | 270 |
274 EnsureLayout(); | 271 EnsureLayout(); |
275 ptrdiff_t offset = gfx::UTF16IndexToOffset(text(), 0, position); | 272 ptrdiff_t offset = UTF16IndexToOffset(text(), 0, index); |
276 // Check that the index corresponds with a valid text code point, that it is | 273 // Check that the index is marked as a legitimate cursor position by Pango. |
277 // marked as a legitimate cursor position by Pango, and that it is not | 274 return offset < num_log_attrs_ && log_attrs_[offset].is_cursor_position; |
278 // truncated from layout text (its glyph is shown on screen). | |
279 return (offset < num_log_attrs_ && log_attrs_[offset].is_cursor_position && | |
280 offset < g_utf8_strlen(layout_text_, -1)); | |
281 } | 275 } |
282 | 276 |
283 void RenderTextPango::ResetLayout() { | 277 void RenderTextPango::ResetLayout() { |
284 // set_cached_bounds_and_offset_valid(false) is done in RenderText for every | 278 // set_cached_bounds_and_offset_valid(false) is done in RenderText for every |
285 // operation that triggers ResetLayout(). | 279 // operation that triggers ResetLayout(). |
286 if (layout_) { | 280 if (layout_) { |
287 // TODO(msw): Keep |layout_| across text changes, etc.; it can be re-used. | 281 // TODO(msw): Keep |layout_| across text changes, etc.; it can be re-used. |
288 g_object_unref(layout_); | 282 g_object_unref(layout_); |
289 layout_ = NULL; | 283 layout_ = NULL; |
290 } | 284 } |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
384 SkScalar y = SkIntToScalar(offset.y()); | 378 SkScalar y = SkIntToScalar(offset.y()); |
385 | 379 |
386 std::vector<SkPoint> pos; | 380 std::vector<SkPoint> pos; |
387 std::vector<uint16> glyphs; | 381 std::vector<uint16> glyphs; |
388 | 382 |
389 internal::SkiaTextRenderer renderer(canvas); | 383 internal::SkiaTextRenderer renderer(canvas); |
390 ApplyFadeEffects(&renderer); | 384 ApplyFadeEffects(&renderer); |
391 ApplyTextShadows(&renderer); | 385 ApplyTextShadows(&renderer); |
392 | 386 |
393 // TODO(derat): Use font-specific params: http://crbug.com/125235 | 387 // TODO(derat): Use font-specific params: http://crbug.com/125235 |
394 const gfx::FontRenderParams& render_params = | 388 const FontRenderParams& render_params = GetDefaultFontRenderParams(); |
395 gfx::GetDefaultFontRenderParams(); | |
396 const bool use_subpixel_rendering = | 389 const bool use_subpixel_rendering = |
397 render_params.subpixel_rendering != | 390 render_params.subpixel_rendering != |
398 gfx::FontRenderParams::SUBPIXEL_RENDERING_NONE; | 391 FontRenderParams::SUBPIXEL_RENDERING_NONE; |
399 renderer.SetFontSmoothingSettings( | 392 renderer.SetFontSmoothingSettings( |
400 render_params.antialiasing, | 393 render_params.antialiasing, |
401 use_subpixel_rendering && !background_is_transparent(), | 394 use_subpixel_rendering && !background_is_transparent(), |
402 render_params.subpixel_positioning); | 395 render_params.subpixel_positioning); |
403 | 396 |
404 SkPaint::Hinting skia_hinting = SkPaint::kNormal_Hinting; | 397 SkPaint::Hinting skia_hinting = SkPaint::kNormal_Hinting; |
405 switch (render_params.hinting) { | 398 switch (render_params.hinting) { |
406 case gfx::FontRenderParams::HINTING_NONE: | 399 case FontRenderParams::HINTING_NONE: |
407 skia_hinting = SkPaint::kNo_Hinting; | 400 skia_hinting = SkPaint::kNo_Hinting; |
408 break; | 401 break; |
409 case gfx::FontRenderParams::HINTING_SLIGHT: | 402 case FontRenderParams::HINTING_SLIGHT: |
410 skia_hinting = SkPaint::kSlight_Hinting; | 403 skia_hinting = SkPaint::kSlight_Hinting; |
411 break; | 404 break; |
412 case gfx::FontRenderParams::HINTING_MEDIUM: | 405 case FontRenderParams::HINTING_MEDIUM: |
413 skia_hinting = SkPaint::kNormal_Hinting; | 406 skia_hinting = SkPaint::kNormal_Hinting; |
414 break; | 407 break; |
415 case gfx::FontRenderParams::HINTING_FULL: | 408 case FontRenderParams::HINTING_FULL: |
416 skia_hinting = SkPaint::kFull_Hinting; | 409 skia_hinting = SkPaint::kFull_Hinting; |
417 break; | 410 break; |
418 } | 411 } |
419 renderer.SetFontHinting(skia_hinting); | 412 renderer.SetFontHinting(skia_hinting); |
420 | 413 |
421 // Temporarily apply composition underlines and selection colors. | 414 // Temporarily apply composition underlines and selection colors. |
422 ApplyCompositionAndSelectionStyles(); | 415 ApplyCompositionAndSelectionStyles(); |
423 | 416 |
424 internal::StyleIterator style(colors(), styles()); | 417 internal::StyleIterator style(colors(), styles()); |
425 for (GSList* it = current_line_->runs; it; it = it->next) { | 418 for (GSList* it = current_line_->runs; it; it = it->next) { |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
526 int glyph_index) const { | 519 int glyph_index) const { |
527 return LayoutIndexToTextIndex(run->item->offset + | 520 return LayoutIndexToTextIndex(run->item->offset + |
528 run->glyphs->log_clusters[glyph_index]); | 521 run->glyphs->log_clusters[glyph_index]); |
529 } | 522 } |
530 | 523 |
531 RenderText* RenderText::CreateInstance() { | 524 RenderText* RenderText::CreateInstance() { |
532 return new RenderTextPango; | 525 return new RenderTextPango; |
533 } | 526 } |
534 | 527 |
535 } // namespace gfx | 528 } // namespace gfx |
OLD | NEW |