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