| 264 | } |
| 265 | |
| 266 | static ReturnCode plot_axis_vertical( |
| 267 | Context* ctx, |
| 268 | PlotConfig* plot, |
| 269 | const AxisDefinition& axis_config, |
| 270 | double x, |
| 271 | double y0, |
| 272 | double y1) { |
| 273 | /* draw axis line */ |
| 274 | draw_line(ctx, {x, y0}, {x, y1}, axis_config.border_style); |
| 275 | |
| 276 | /* draw ticks */ |
| 277 | ScaleLayout ticks; |
| 278 | axis_config.tick_placement( |
| 279 | axis_config.scale, |
| 280 | axis_config.label_formatter, |
| 281 | &ticks); |
| 282 | |
| 283 | double tick_position = |
| 284 | std::clamp(axis_config.tick_offset, -1.0, 1.0); |
| 285 | |
| 286 | auto tick_length = measure_or( |
| 287 | axis_config.tick_length, |
| 288 | from_pt(kDefaultTickLengthPT, layer_get_dpi(ctx))); |
| 289 | |
| 290 | for (const auto& tick : ticks.positions) { |
| 291 | auto ty = y0 + (y1 - y0) * tick; |
| 292 | auto tx = x - tick_length + tick_length * (tick_position + 1) / 2.0; |
| 293 | |
| 294 | draw_line( |
| 295 | ctx, |
| 296 | {tx, ty}, |
| 297 | {tx + tick_length, ty}, |
| 298 | axis_config.border_style); |
| 299 | } |
| 300 | |
| 301 | /* draw labels */ |
| 302 | ScaleLayout labels; |
| 303 | axis_config.label_placement( |
| 304 | axis_config.scale, |
| 305 | axis_config.label_formatter, |
| 306 | &labels); |
| 307 | |
| 308 | double label_position = |
| 309 | std::clamp(axis_config.label_offset, -1.0, 1.0); |
| 310 | |
| 311 | auto label_padding = measure_or( |
| 312 | axis_config.label_padding, |
| 313 | from_em(kDefaultLabelPaddingEM, axis_config.label_font_size)); |
| 314 | |
| 315 | double label_size = 0; |
| 316 | if (auto rc = axis_layout_labels(axis_config, ctx, &label_size); |
| 317 | !rc) { |
| 318 | return rc; |
| 319 | } |
| 320 | |
| 321 | for (size_t i = 0; i < labels.positions.size(); ++i) { |
| 322 | auto tick = labels.positions[i]; |
| 323 | auto label_text = labels.labels[i]; |
no test coverage detected