|
4 | 4 | "bytes"
|
5 | 5 | "fmt"
|
6 | 6 | "math"
|
7 |
| - "sort" |
8 | 7 | "strings"
|
9 | 8 |
|
10 | 9 | "oss.terrastruct.com/d2/d2target"
|
@@ -64,11 +63,9 @@ func Render(diagram *d2target.Diagram, opts *RenderOpts) ([]byte, error) {
|
64 | 63 | }
|
65 | 64 | }
|
66 | 65 |
|
67 |
| - width, height = canvas.AutoSize() |
68 |
| - fmt.Println("==== ", canvas.w, canvas.h, "====") |
69 |
| - fmt.Println("==== ", width, height, "====") |
70 |
| - canvas.ReScale(width, height) |
71 |
| - |
| 66 | + height = canvas.AutoHeight() |
| 67 | + fmt.Println(canvas.h, height) |
| 68 | + canvas.ReScale(canvas.w, height) |
72 | 69 | return canvas.TrimBytes(), nil
|
73 | 70 | }
|
74 | 71 |
|
@@ -326,181 +323,34 @@ func (c *Canvas) TrimBytes() []byte {
|
326 | 323 | return buf.Bytes()
|
327 | 324 | }
|
328 | 325 |
|
329 |
| -func (c *Canvas) AutoSize() (width, height int) { |
330 |
| - type boxInfo struct { |
331 |
| - x, y, w, h int |
332 |
| - text string |
333 |
| - hasUp, hasDown bool |
334 |
| - hasLeft, hasRight bool |
335 |
| - hasDiagonal bool |
336 |
| - originalWidth int |
337 |
| - } |
338 |
| - |
339 |
| - boxes := make([]boxInfo, 0) |
340 |
| - |
341 |
| - // Collect boxes and their connections |
342 |
| - for _, pos := range c.textPositions { |
343 |
| - up, down, left, right, diag := false, false, false, false, false |
344 |
| - |
345 |
| - // Check surrounding area for connections |
346 |
| - checkRange := 2 |
347 |
| - minX := max(0, pos.x-checkRange) |
348 |
| - maxX := min(c.w, pos.x+pos.w+checkRange) |
349 |
| - minY := max(0, pos.y-checkRange) |
350 |
| - maxY := min(c.h, pos.y+pos.h+checkRange) |
351 |
| - |
352 |
| - // Check vertical connections |
353 |
| - for x := pos.x; x < pos.x+pos.w; x++ { |
354 |
| - if pos.y > 0 && c.grid[pos.y-1][x] == '|' { |
355 |
| - up = true |
356 |
| - } |
357 |
| - if pos.y+pos.h < c.h && c.grid[pos.y+pos.h][x] == '|' { |
358 |
| - down = true |
359 |
| - } |
360 |
| - } |
361 |
| - |
362 |
| - // Check horizontal and diagonal connections |
363 |
| - for y := minY; y < maxY; y++ { |
364 |
| - for x := minX; x < maxX; x++ { |
365 |
| - ch := c.grid[y][x] |
366 |
| - switch ch { |
367 |
| - case '-': |
368 |
| - if x < pos.x { |
369 |
| - left = true |
370 |
| - } else if x >= pos.x+pos.w { |
371 |
| - right = true |
372 |
| - } |
373 |
| - case '/', '\\': |
374 |
| - diag = true |
375 |
| - } |
376 |
| - } |
377 |
| - } |
378 |
| - |
379 |
| - boxes = append(boxes, boxInfo{ |
380 |
| - x: pos.x, |
381 |
| - y: pos.y, |
382 |
| - w: pos.w, |
383 |
| - h: pos.h, |
384 |
| - text: pos.text, |
385 |
| - hasUp: up, |
386 |
| - hasDown: down, |
387 |
| - hasLeft: left, |
388 |
| - hasRight: right, |
389 |
| - hasDiagonal: diag, |
390 |
| - originalWidth: pos.w, |
391 |
| - }) |
392 |
| - } |
393 |
| - |
394 |
| - // Sort boxes vertically |
395 |
| - yBoxes := make([]boxInfo, len(boxes)) |
396 |
| - copy(yBoxes, boxes) |
397 |
| - sort.Slice(yBoxes, func(i, j int) bool { |
398 |
| - return yBoxes[i].y < yBoxes[j].y |
399 |
| - }) |
400 |
| - |
401 |
| - // Calculate vertical layout with increased padding |
| 326 | +func (c *Canvas) AutoHeight() int { |
402 | 327 | currY := 0
|
403 |
| - yMapping := make(map[int]int) |
404 |
| - |
405 |
| - for i, box := range yBoxes { |
406 |
| - lines := strings.Split(box.text, "\n") |
407 |
| - minHeight := len(lines) + 4 // padding + border |
| 328 | + mapping := make(map[int]int) |
408 | 329 |
|
409 |
| - if box.hasDiagonal { // Add extra height for diagonal connections |
410 |
| - minHeight += 2 |
411 |
| - } |
| 330 | + for i, label := range c.textPositions { |
| 331 | + lines := strings.Split(label.text, "\n") |
| 332 | + minHeight := len(lines) + 2 // +border |
412 | 333 |
|
413 | 334 | if i == 0 {
|
414 |
| - yMapping[box.y] = 2 // Start with some padding |
| 335 | + mapping[label.y] = 0 |
415 | 336 | currY = minHeight + 2
|
416 | 337 | continue
|
417 | 338 | }
|
418 | 339 |
|
419 |
| - spacing := 2 // spacing between boxes |
420 |
| - prevBox := yBoxes[i-1] |
421 |
| - |
422 |
| - // Add more spacing for connections |
423 |
| - if box.hasUp || prevBox.hasDown { |
424 |
| - spacing = 3 |
425 |
| - } |
426 |
| - if box.hasDiagonal || prevBox.hasDiagonal { |
427 |
| - spacing = 4 |
428 |
| - } |
429 |
| - |
430 |
| - yMapping[box.y] = currY + spacing |
431 |
| - currY = yMapping[box.y] + minHeight |
| 340 | + mapping[label.y] = currY + 3 // +spacing |
| 341 | + currY = mapping[label.y] + minHeight |
432 | 342 | }
|
433 | 343 |
|
434 |
| - // Calculate final height |
435 | 344 | maxH := 0
|
436 |
| - for _, box := range yBoxes { |
437 |
| - newY := yMapping[box.y] |
438 |
| - lines := strings.Split(box.text, "\n") |
439 |
| - boxHeight := len(lines) + 4 // padding + border |
440 |
| - |
441 |
| - if box.hasDiagonal { |
442 |
| - boxHeight += 2 |
443 |
| - } |
| 345 | + for _, label := range c.textPositions { |
| 346 | + newY := mapping[label.y] |
| 347 | + lines := strings.Split(label.text, "\n") |
| 348 | + boxHeight := len(lines) + 2 // +border |
444 | 349 |
|
445 | 350 | maxH = max(maxH, newY+boxHeight)
|
446 | 351 | }
|
447 | 352 |
|
448 |
| - // Add extra vertical padding for top/bottom connections |
449 |
| - topPad := 2 |
450 |
| - bottomPad := 2 |
451 |
| - for x := 0; x < c.w; x++ { |
452 |
| - if c.grid[0][x] != ' ' { |
453 |
| - topPad = 3 |
454 |
| - } |
455 |
| - if c.grid[c.h-1][x] != ' ' { |
456 |
| - bottomPad = 3 |
457 |
| - } |
458 |
| - } |
459 |
| - maxH += topPad + bottomPad |
460 |
| - |
461 |
| - // preserve the original width of each box |
462 |
| - // but ensure it's wide enough for the content |
463 |
| - maxW := 0 |
464 |
| - for _, box := range boxes { |
465 |
| - // Calculate minimum width needed for text |
466 |
| - lines := strings.Split(box.text, "\n") |
467 |
| - textWidth := 0 |
468 |
| - for _, line := range lines { |
469 |
| - textWidth = max(textWidth, len(line)) |
470 |
| - } |
471 |
| - |
472 |
| - requiredWidth := textWidth + 4 // Base padding |
473 |
| - |
474 |
| - // Add extra width for connections |
475 |
| - if box.hasLeft { |
476 |
| - requiredWidth += 2 |
477 |
| - } |
478 |
| - if box.hasRight { |
479 |
| - requiredWidth += 2 |
480 |
| - } |
481 |
| - if box.hasDiagonal { |
482 |
| - requiredWidth += 4 |
483 |
| - } |
484 |
| - |
485 |
| - // Use the larger of required width or original width |
486 |
| - effectiveWidth := max(requiredWidth, box.originalWidth) |
487 |
| - maxW = max(maxW, box.x+effectiveWidth) |
488 |
| - } |
489 |
| - |
490 |
| - // Add padding for edge connections |
491 |
| - leftPad := 2 |
492 |
| - rightPad := 2 |
493 |
| - for y := 0; y < c.h; y++ { |
494 |
| - if c.grid[y][0] != ' ' { |
495 |
| - leftPad = max(leftPad, 3) |
496 |
| - } |
497 |
| - if c.grid[y][c.w-1] != ' ' { |
498 |
| - rightPad = max(rightPad, 3) |
499 |
| - } |
500 |
| - } |
501 |
| - maxW += leftPad + rightPad |
502 |
| - |
503 |
| - return min(c.w, maxW), min(c.h, maxH) |
| 353 | + return maxH |
504 | 354 | }
|
505 | 355 |
|
506 | 356 | // ReScale reduces the size of ASCII art using a pixel-like sampling technique
|
|
0 commit comments