| 283 | } |
| 284 | |
| 285 | void TextCanvasTexture::RenderText(const char* str, int length, const CanvasTextStyle& style, TextMetrics& metrics, uint32_t mode, uint32_t char_limit) { |
| 286 | std::vector<uint32_t> utf32_string; |
| 287 | |
| 288 | try { |
| 289 | utf8::utf8to32(str, str + length, std::back_inserter(utf32_string)); |
| 290 | } catch (const utf8::not_enough_room& ner) { |
| 291 | LOGE << "Got utf8 exception \"" << ner.what() << "\" this might indicate invalid utf-8 data" << std::endl; |
| 292 | } |
| 293 | |
| 294 | FontRenderer* font_renderer = FontRenderer::Instance(); |
| 295 | FT_Matrix matrix; |
| 296 | FTMatrixFromAngle(&matrix, impl_->pen_rotation); |
| 297 | int orig_pen_x = impl_->pen.x; |
| 298 | int line_height = font_renderer->GetFontInfo(style.font_face_id, FontRenderer::INFO_HEIGHT); |
| 299 | int line_start = 0; |
| 300 | FT_Vector zero_vec = {0}; |
| 301 | ClearTextMetrics(&metrics); |
| 302 | for (unsigned i = 0; i <= utf32_string.size(); ++i) { |
| 303 | if (i == utf32_string.size() || utf32_string[i] == '\n') { // Find line endings to draw entire lines at once |
| 304 | TextMetrics line_metrics; |
| 305 | bool need_to_reset = true; |
| 306 | int next_end_id = 0; |
| 307 | |
| 308 | // Create newlines when the lines are too long. |
| 309 | // This includes the entire string, not just what we want to show based on |
| 310 | // char limit |
| 311 | while (need_to_reset) { |
| 312 | ClearTextMetrics(&line_metrics); |
| 313 | need_to_reset = false; |
| 314 | for (unsigned j = line_start; j < i; ++j) { |
| 315 | font_renderer->SetTransform(style.font_face_id, &matrix, &zero_vec); |
| 316 | FT_GlyphSlot slot = font_renderer->RenderCharacterBitmap(style.font_face_id, utf32_string[j], FontRenderer::RCB_METRIC); |
| 317 | ApplyGlyphSlotToTextMetrics(&line_metrics, slot); |
| 318 | |
| 319 | if (mode & TMF_AUTO_NEWLINE) { |
| 320 | if (line_metrics.advance[0] + impl_->pen.x + slot->metrics.width >= impl_->text_canvas.width() * 64) { |
| 321 | for (int k = j; k > 0; k--) { |
| 322 | if (utf32_string[k] == ' ') { |
| 323 | j = k; |
| 324 | break; |
| 325 | } |
| 326 | } |
| 327 | need_to_reset = true; |
| 328 | next_end_id = j; |
| 329 | break; |
| 330 | } |
| 331 | } |
| 332 | } |
| 333 | |
| 334 | if (need_to_reset) { |
| 335 | i = next_end_id; |
| 336 | } |
| 337 | } |
| 338 | |
| 339 | switch (style.alignment) { |
| 340 | case CanvasTextStyle::RIGHT: |
| 341 | if (mode & TMF_DRAW) { |
| 342 | impl_->pen.x = impl_->text_canvas.width() * 64 - line_metrics.bounds[1]; |
nothing calls this directly
no test coverage detected