| 50 | } |
| 51 | |
| 52 | static bool LayoutText(LayoutContext* ctx, |
| 53 | uint32_t* codepoints, uint32_t num_codepoints, |
| 54 | TextLayoutSettings* settings, |
| 55 | TextLayout* layout) |
| 56 | { |
| 57 | HFontCollection font_collection = layout->m_FontCollection; |
| 58 | |
| 59 | float line_width = settings->m_Width; |
| 60 | // Ensure explicit line breaks are honored without forcing word-wrap. |
| 61 | // When auto line breaking is disabled or width is zero, use a very large width |
| 62 | // and keep wrap enabled so the layout engine can still split on '\n'. |
| 63 | if (!settings->m_LineBreak || line_width <= 0.0f) |
| 64 | line_width = 1000000.0f; |
| 65 | skb_layout_params_t params = {0}; |
| 66 | params.font_collection = FontCollectionGetSkribidiPtr(font_collection), |
| 67 | params.lang = "en-us", // TODO: support setting |
| 68 | params.origin = {0, 0}, |
| 69 | params.layout_width = line_width, |
| 70 | params.layout_height = 1000000.0f, |
| 71 | params.base_direction = SKB_DIRECTION_AUTO, |
| 72 | // Always allow wrapping in the layout engine. With a very large width, this |
| 73 | // does not introduce automatic wraps, but it lets explicit '\n' split lines. |
| 74 | params.text_wrap = (uint8_t)SKB_WRAP_WORD, |
| 75 | params.text_overflow = SKB_OVERFLOW_NONE, |
| 76 | params.vertical_trim = SKB_VERTICAL_TRIM_DEFAULT, |
| 77 | params.horizontal_align = SKB_ALIGN_START, // TODO: support the other way around (ask author for SKB_ALIGN_RIGHT/LEFT ?) |
| 78 | params.vertical_align = SKB_ALIGN_START, // TODO: support the other way around (ask author for SKB_ALIGN_RIGHT/LEFT ?) |
| 79 | params.baseline_align = SKB_BASELINE_MIDDLE, |
| 80 | params.flags = 0; |
| 81 | |
| 82 | float tracking = settings->m_Tracking * settings->m_Size; |
| 83 | HFont default_font = FontCollectionGetFont(font_collection, 0); |
| 84 | float font_scale = FontGetScaleFromSize(default_font, settings->m_Size); |
| 85 | uint32_t ascent = (uint32_t)FontGetAscent(default_font, 1.0f); |
| 86 | uint32_t descent = (uint32_t)fabsf(FontGetDescent(default_font, 1.0f)); |
| 87 | float line_height_scaled = (ascent + descent) * font_scale; |
| 88 | |
| 89 | // TODO: Allo setting default as italic etc |
| 90 | const skb_attribute_t attributes[] = { |
| 91 | skb_attribute_make_font(SKB_FONT_FAMILY_DEFAULT, settings->m_Size, SKB_WEIGHT_NORMAL, SKB_STYLE_NORMAL, SKB_STRETCH_NORMAL), |
| 92 | skb_attribute_make_line_height(SKB_LINE_HEIGHT_METRICS_RELATIVE, settings->m_Leading), |
| 93 | skb_attribute_make_spacing(tracking, 0.0f) |
| 94 | }; |
| 95 | |
| 96 | // TODO: Support rich text |
| 97 | |
| 98 | skb_text_run_utf32_t runs[] = { |
| 99 | { codepoints, (int32_t)num_codepoints, attributes, DM_ARRAY_SIZE(attributes) }, |
| 100 | }; |
| 101 | |
| 102 | skb_layout_t* skblayout = skb_layout_create_from_runs_utf32(ctx->m_Alloc, ¶ms, runs, DM_ARRAY_SIZE(runs)); |
| 103 | ctx->m_Layout = skblayout; |
| 104 | |
| 105 | const int32_t glyphs_count = skb_layout_get_glyphs_count(skblayout); |
| 106 | const skb_glyph_t* glyphs = skb_layout_get_glyphs(skblayout); |
| 107 | const skb_glyph_run_t* glyph_runs = skb_layout_get_glyph_runs(skblayout); |
| 108 | const skb_text_attributes_span_t* attrib_spans = skb_layout_get_attribute_spans(skblayout); |
| 109 | const skb_layout_line_t* layout_lines = skb_layout_get_lines(skblayout); |
no test coverage detected