| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 Google Inc. All rights reserved. | 2 * Copyright (c) 2012 Google Inc. All rights reserved. |
| 3 * Copyright (C) 2013 BlackBerry Limited. All rights reserved. | 3 * Copyright (C) 2013 BlackBerry Limited. All rights reserved. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions are | 6 * modification, are permitted provided that the following conditions are |
| 7 * met: | 7 * met: |
| 8 * | 8 * |
| 9 * * Redistributions of source code must retain the above copyright | 9 * * Redistributions of source code must retain the above copyright |
| 10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 143 hb_buffer_set_direction(buffer, direction); | 143 hb_buffer_set_direction(buffer, direction); |
| 144 | 144 |
| 145 hb_font_t* hb_font = face->GetScaledFont(std::move(current_font_range_set)); | 145 hb_font_t* hb_font = face->GetScaledFont(std::move(current_font_range_set)); |
| 146 hb_shape(hb_font, buffer, font_features, font_features_size); | 146 hb_shape(hb_font, buffer, font_features, font_features_size); |
| 147 | 147 |
| 148 return true; | 148 return true; |
| 149 } | 149 } |
| 150 | 150 |
| 151 } // namespace | 151 } // namespace |
| 152 | 152 |
| 153 bool HarfBuzzShaper::ExtractShapeResults( | 153 void HarfBuzzShaper::ExtractShapeResults( |
| 154 RangeData* range_data, | 154 RangeData* range_data, |
| 155 bool& font_cycle_queued, | 155 bool& font_cycle_queued, |
| 156 const HolesQueueItem& current_queue_item, | 156 const HolesQueueItem& current_queue_item, |
| 157 const SimpleFontData* current_font, | 157 const SimpleFontData* current_font, |
| 158 UScriptCode current_run_script, | 158 UScriptCode current_run_script, |
| 159 bool is_last_resort, | 159 bool is_last_resort, |
| 160 ShapeResult* shape_result) const { | 160 ShapeResult* shape_result) const { |
| 161 enum ClusterResult { kShaped, kNotDef, kUnknown }; | 161 enum ClusterResult { kShaped, kNotDef, kUnknown }; |
| 162 ClusterResult current_cluster_result = kUnknown; | 162 ClusterResult current_cluster_result = kUnknown; |
| 163 ClusterResult previous_cluster_result = kUnknown; | 163 ClusterResult previous_cluster_result = kUnknown; |
| 164 unsigned previous_cluster = 0; | 164 unsigned previous_cluster = 0; |
| 165 unsigned current_cluster = 0; | 165 unsigned current_cluster = 0; |
| 166 | 166 |
| 167 // Find first notdef glyph in buffer. | 167 // Find first notdef glyph in buffer. |
| 168 unsigned num_glyphs = hb_buffer_get_length(range_data->buffer); | 168 unsigned num_glyphs = hb_buffer_get_length(range_data->buffer); |
| 169 hb_glyph_info_t* glyph_info = | 169 hb_glyph_info_t* glyph_info = |
| 170 hb_buffer_get_glyph_infos(range_data->buffer, 0); | 170 hb_buffer_get_glyph_infos(range_data->buffer, 0); |
| 171 | 171 |
| 172 unsigned last_change_position = 0; | 172 unsigned last_change_position = 0; |
| 173 | 173 |
| 174 if (!num_glyphs) { | 174 if (!num_glyphs) |
| 175 DLOG(ERROR) << "HarfBuzz returned empty glyph buffer after shaping."; | 175 return; |
| 176 return false; | |
| 177 } | |
| 178 | 176 |
| 179 for (unsigned glyph_index = 0; glyph_index <= num_glyphs; ++glyph_index) { | 177 for (unsigned glyph_index = 0; glyph_index <= num_glyphs; ++glyph_index) { |
| 180 // Iterating by clusters, check for when the state switches from shaped | 178 // Iterating by clusters, check for when the state switches from shaped |
| 181 // to non-shaped and vice versa. Taking into account the edge cases of | 179 // to non-shaped and vice versa. Taking into account the edge cases of |
| 182 // beginning of the run and end of the run. | 180 // beginning of the run and end of the run. |
| 183 previous_cluster = current_cluster; | 181 previous_cluster = current_cluster; |
| 184 current_cluster = glyph_info[glyph_index].cluster; | 182 current_cluster = glyph_info[glyph_index].cluster; |
| 185 | 183 |
| 186 if (glyph_index < num_glyphs) { | 184 if (glyph_index < num_glyphs) { |
| 187 // Still the same cluster, merge shaping status. | 185 // Still the same cluster, merge shaping status. |
| 188 if (previous_cluster == current_cluster && glyph_index != 0) { | 186 if (previous_cluster == current_cluster && glyph_index != 0) { |
| 189 if (glyph_info[glyph_index].codepoint == 0) { | 187 if (glyph_info[glyph_index].codepoint == 0) { |
| 190 current_cluster_result = kNotDef; | 188 current_cluster_result = kNotDef; |
| 191 } else { | 189 } else { |
| 192 // We can only call the current cluster fully shapped, if | 190 // We can only call the current cluster fully shapped, if |
| 193 // all characters that are part of it are shaped, so update | 191 // all characters that are part of it are shaped, so update |
| 194 // currentClusterResult to Shaped only if the previous | 192 // currentClusterResult to kShaped only if the previous |
| 195 // characters have been shaped, too. | 193 // characters have been shaped, too. |
| 196 current_cluster_result = | 194 current_cluster_result = |
| 197 current_cluster_result == kShaped ? kShaped : kNotDef; | 195 current_cluster_result == kShaped ? kShaped : kNotDef; |
| 198 } | 196 } |
| 199 continue; | 197 continue; |
| 200 } | 198 } |
| 201 // We've moved to a new cluster. | 199 // We've moved to a new cluster. |
| 202 previous_cluster_result = current_cluster_result; | 200 previous_cluster_result = current_cluster_result; |
| 203 current_cluster_result = | 201 current_cluster_result = |
| 204 glyph_info[glyph_index].codepoint == 0 ? kNotDef : kShaped; | 202 glyph_info[glyph_index].codepoint == 0 ? kNotDef : kShaped; |
| 205 } else { | 203 } else { |
| 206 // The code below operates on the "flanks"/changes between NotDef | 204 // The code below operates on the "flanks"/changes between kNotDef |
| 207 // and Shaped. In order to keep the code below from explictly | 205 // and kShaped. In order to keep the code below from explictly |
| 208 // dealing with character indices and run end, we explicitly | 206 // dealing with character indices and run end, we explicitly |
| 209 // terminate the cluster/run here by setting the result value to the | 207 // terminate the cluster/run here by setting the result value to the |
| 210 // opposite of what it was, leading to atChange turning true. | 208 // opposite of what it was, leading to atChange turning true. |
| 211 previous_cluster_result = current_cluster_result; | 209 previous_cluster_result = current_cluster_result; |
| 212 current_cluster_result = | 210 current_cluster_result = |
| 213 current_cluster_result == kNotDef ? kShaped : kNotDef; | 211 current_cluster_result == kNotDef ? kShaped : kNotDef; |
| 214 } | 212 } |
| 215 | 213 |
| 216 bool at_change = (previous_cluster_result != current_cluster_result) && | 214 bool at_change = (previous_cluster_result != current_cluster_result) && |
| 217 previous_cluster_result != kUnknown; | 215 previous_cluster_result != kUnknown; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 279 // choice than adding boxes to the ShapeResult. | 277 // choice than adding boxes to the ShapeResult. |
| 280 if ((current_cluster_result == kNotDef && num_characters) || | 278 if ((current_cluster_result == kNotDef && num_characters) || |
| 281 is_last_resort) { | 279 is_last_resort) { |
| 282 hb_direction_t direction = range_data->HarfBuzzDirection(current_font); | 280 hb_direction_t direction = range_data->HarfBuzzDirection(current_font); |
| 283 // Here we need to specify glyph positions. | 281 // Here we need to specify glyph positions. |
| 284 ShapeResult::RunInfo* run = new ShapeResult::RunInfo( | 282 ShapeResult::RunInfo* run = new ShapeResult::RunInfo( |
| 285 current_font, direction, ICUScriptToHBScript(current_run_script), | 283 current_font, direction, ICUScriptToHBScript(current_run_script), |
| 286 start_index, num_glyphs_to_insert, num_characters); | 284 start_index, num_glyphs_to_insert, num_characters); |
| 287 shape_result->InsertRun(WTF::WrapUnique(run), last_change_position, | 285 shape_result->InsertRun(WTF::WrapUnique(run), last_change_position, |
| 288 num_glyphs_to_insert, range_data->buffer); | 286 num_glyphs_to_insert, range_data->buffer); |
| 287 range_data->font->ReportNotDefGlyph(); |
| 289 } | 288 } |
| 290 last_change_position = glyph_index; | 289 last_change_position = glyph_index; |
| 291 } | 290 } |
| 292 return true; | |
| 293 } | 291 } |
| 294 | 292 |
| 295 static inline const SimpleFontData* FontDataAdjustedForOrientation( | 293 static inline const SimpleFontData* FontDataAdjustedForOrientation( |
| 296 const SimpleFontData* original_font, | 294 const SimpleFontData* original_font, |
| 297 FontOrientation run_orientation, | 295 FontOrientation run_orientation, |
| 298 OrientationIterator::RenderOrientation render_orientation) { | 296 OrientationIterator::RenderOrientation render_orientation) { |
| 299 if (!IsVerticalBaseline(run_orientation)) | 297 if (!IsVerticalBaseline(run_orientation)) |
| 300 return original_font; | 298 return original_font; |
| 301 | 299 |
| 302 if (run_orientation == FontOrientation::kVerticalRotated || | 300 if (run_orientation == FontOrientation::kVerticalRotated || |
| (...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 669 if (!ShapeRange(range_data->buffer, | 667 if (!ShapeRange(range_data->buffer, |
| 670 range_data->font_features.IsEmpty() | 668 range_data->font_features.IsEmpty() |
| 671 ? 0 | 669 ? 0 |
| 672 : range_data->font_features.data(), | 670 : range_data->font_features.data(), |
| 673 range_data->font_features.size(), | 671 range_data->font_features.size(), |
| 674 direction_and_small_caps_adjusted_font, | 672 direction_and_small_caps_adjusted_font, |
| 675 current_font_data_for_range_set->Ranges(), segment.script, | 673 current_font_data_for_range_set->Ranges(), segment.script, |
| 676 direction, language)) | 674 direction, language)) |
| 677 DLOG(ERROR) << "Shaping range failed."; | 675 DLOG(ERROR) << "Shaping range failed."; |
| 678 | 676 |
| 679 if (!ExtractShapeResults(range_data, font_cycle_queued, current_queue_item, | 677 ExtractShapeResults(range_data, font_cycle_queued, current_queue_item, |
| 680 direction_and_small_caps_adjusted_font, | 678 direction_and_small_caps_adjusted_font, segment.script, |
| 681 segment.script, !fallback_iterator->HasNext(), | 679 !fallback_iterator->HasNext(), result); |
| 682 result)) | |
| 683 DLOG(ERROR) << "Shape result extraction failed."; | |
| 684 | 680 |
| 685 hb_buffer_reset(range_data->buffer); | 681 hb_buffer_reset(range_data->buffer); |
| 686 } | 682 } |
| 687 } | 683 } |
| 688 | 684 |
| 689 PassRefPtr<ShapeResult> HarfBuzzShaper::Shape(const Font* font, | 685 PassRefPtr<ShapeResult> HarfBuzzShaper::Shape(const Font* font, |
| 690 TextDirection direction, | 686 TextDirection direction, |
| 691 unsigned start, | 687 unsigned start, |
| 692 unsigned end) const { | 688 unsigned end) const { |
| 693 DCHECK(end >= start); | 689 DCHECK(end >= start); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 719 } | 715 } |
| 720 return result.Release(); | 716 return result.Release(); |
| 721 } | 717 } |
| 722 | 718 |
| 723 PassRefPtr<ShapeResult> HarfBuzzShaper::Shape(const Font* font, | 719 PassRefPtr<ShapeResult> HarfBuzzShaper::Shape(const Font* font, |
| 724 TextDirection direction) const { | 720 TextDirection direction) const { |
| 725 return Shape(font, direction, 0, text_length_); | 721 return Shape(font, direction, 0, text_length_); |
| 726 } | 722 } |
| 727 | 723 |
| 728 } // namespace blink | 724 } // namespace blink |
| OLD | NEW |