On the train to Wien

This commit is contained in:
Ehmry - 2023-09-08 13:25:25 +02:00
parent f344b29e1e
commit b28583c1ff
4 changed files with 66 additions and 48 deletions

View File

@ -1,4 +1,2 @@
include_rules
: well_of_text.nim |> !nim_bin |> {bin}
: text_spans.nim |> !nim_bin |> {bin}
: wells.nim |> !nim_bin |> {bin}

View File

@ -1,7 +1,7 @@
# SPDX-FileCopyrightText: ☭ Emery Hemingway
# SPDX-License-Identifier: Unlicense
import std/[asyncdispatch, options, os, tables]
import std/[asyncdispatch, options, os, streams, tables]
import preserves, syndicate, syndicate/[capabilities]
import bumpy, pixie
import sdl2
@ -59,10 +59,9 @@ func rect(img: Image): bumpy.Rect =
proc newApp(length: cint): App =
## Create a new square plane of `length` pixels.
result = App(
topFrame: newFrame(length shl 1, length shl 1),
well: newWell(length, length),
zoomFactor: 1.0,
)
app.well = newWell(length, length)
discard createWindowAndRenderer(
length, length,
SDL_WINDOW_RESIZABLE,
@ -88,13 +87,14 @@ proc redraw(app: App) =
app.renderer.setDrawColor(0x80, 0x80, 0x80)
app.renderer.clear()
let wellRect = well.Rect
let wellRect = app.well.rect
if viewPort.overlaps wellRect:
for (pane, rect) in well.intersectingPanes(viewPort)
for (index, rect) in app.well.intersectingPanes(viewPort):
let texture = app.well.texture(index, app.renderer, rect.wh * app.zoomFactor)
if texture.isNil: break
let
texture = pane.texture(rect.wh *­app.zoomFactor)
overlap = viewPort and rect
src = rect(overlap.xy - app.rect.xy, overlap.wh)
src = rect(overlap.xy - rect.xy, overlap.wh)
var dst: bumpy.Rect
dst.x = (overlap.x - viewPort.x) * (sdlViewPort.w / viewPort.w)
dst.y = (overlap.y - viewPort.y) * (sdlViewPort.h / viewPort.h)
@ -107,6 +107,8 @@ proc redraw(app: App) =
overlap.wh * app.zoomFactor
var (sdlSrc, sdlDst) = (src.toSdl, dst.toSdl)
app.renderer.copy(texture, addr sdlSrc, addr sdlDst)
else:
echo "no overlap of ", viewPort, " and ", wellRect
app.renderer.present()
proc resize(app: App) =
@ -126,18 +128,6 @@ proc recenter(app: App) =
app.zoomFactor = 1.0
app.redraw()
proc setImage(app: App; image: Image) =
app.rect = image.rect
echo "create surface of ", image.width, "x", cint image.height, " pixels"
var
dataPtr = image.data[0].addr
surface = createRGBSurfaceFrom(
dataPtr,
cint image.width, cint image.height,
cint 32, cint 4*image.width,
rmask, gmask, bmask, amask)
app.texture = createTextureFromSurface(app.renderer, surface)
proc main() =
discard sdl2.init(INIT_TIMER or INIT_VIDEO or INIT_EVENTS)
@ -145,7 +135,8 @@ proc main() =
let
typeface = readTypeface(typefacePath)
fontTODO = newFont(typeface, 48)
font = newFont(typeface)
# TODO
app.redraw()
@ -164,15 +155,17 @@ proc main() =
sdlTimeout = 500
asyncPollTimeout = 500
let streamTODO = newFileStream(stdin)
let stream = newFileStream(stdin)
# TODO
var
evt = sdl2.defaultEvent
mousePanning: bool
lineTODO: string
line: string
while true:
if readLine(streamTODO, lineTODO):
app.well.append(line, fontTODO)
if readLine(stream, line):
# TODO
app.well.append(line, font)
app.redraw()
# asyncdispatch.poll(0)
if waitEventTimeout(evt, sdlTimeout):

View File

@ -1,10 +1,12 @@
# SPDX-FileCopyrightText: ☭ Emery Hemingway
# SPDX-License-Identifier: Unlicense
import std/[deques]
import pixie
import std/[deques, streams]
import bumpy, pixie, sdl2
type
Rect = bumpy.Rect
Pane* = ref object
image: pixie.Image
spans: seq[Span]
@ -24,12 +26,12 @@ proc newWell*(width, height: int): Well =
proc margins*(well): Vec2 = well.dimensions / 9.0
proc bounds*(well): Vec2 = well.margin * 7.0
proc bounds*(well): Vec2 = well.margins * 7.0
proc rect*(well): Rect =
result.wh = well.dimensions
proc rectAt(well, offset:­int):­Rect =
proc rectAt(well; offset: int): Rect =
if offset < well.panes.len:
let n = succ offset
result.w = well.dimensions.x / float(2 * n)
@ -52,14 +54,14 @@ proc append*(well; text: string; font: Font) =
assert well.panes.len > 0
let span = newSpan(text, font)
while true:
pane = well.panes[0]
let pane = well.panes[0]
pane.spans.add(span)
var
arrangement = typeset(spans, frame.bounds)
arrangement = typeset(pane.spans, well.bounds)
bounds = layoutBounds arrangement
assert bounds.x <= well.boundx.x
if bounds.bounds.y <= well.bounds.y:
doAssert pane.spans.len > 1, "text does not find on a single pane"
# assert bounds.x <= well.bounds.x
if bounds.y <= well.bounds.y:
doAssert pane.spans.len > 0, "text does not find on a single pane - " & $bounds & $well.bounds
pane.arrangement = arrangement
break
else:
@ -70,6 +72,7 @@ proc append*(well; stream: Stream; font: Font) =
while readLine(stream, line):
append(well, line, font)
#[
proc render*(well; index: Natural; scale: float): Image =
if index < well.panes.len:
let dimensions = well.dimensions * scale
@ -77,17 +80,41 @@ proc render*(well; index: Natural; scale: float): Image =
result = newImage(int dimensions.x, int dimensions.y)
fill(result, rgba(255, 255, 255, 255))
fillText(well.panes[index].arrangment, translate(well.margin))
]#
iterator intersectingPanes(well; rect:­Rect): (Pane, Rect) =
iterator intersectingPanes*(well; rect: Rect): (int, Rect) =
var i = 0
while i <­well.panes.len:
let bounds = well.boundsAt(i)
if i and 3:
let quad = Rect(0, 0, bounds.x *­2.0, bounds.y * 2.0)
if not rect.overlaps quad:
# all further panes are non-intersecting
break
if rect.overlaps bounds:
yield (well.panes[i], bounds)
inc(i)
while i < well.panes.len:
let bounds = well.rectAt(i)
if (i and 3) == 3:
let quad = rect(vec2(0,0), bounds.wh * 2.0)
if not rect.overlaps quad:
# all further panes are non-intersecting
break
if rect.overlaps bounds:
yield (i, bounds)
inc(i)
const
amask = uint32 0xff000000
rmask = uint32 0x000000ff
gmask = uint32 0x0000ff00
bmask = uint32 0x00ff0000
proc texture*(well; index: int; renderer: RendererPtr; wh: Vec2): TexturePtr =
# TODO:­caching
if index >= well.panes.len or wh.x < 4 or wh.y < 4: return nil
let pane = well.panes[index]
let
image = newImage(wh.x.int, wh.y.int)
zoom = wh / well.dimensions
margin = wh / 9.0
if not pane.arrangement.isNil:
image.fillText(pane.arrangement, scale(zoom) * translate(margin))
var surface = createRGBSurfaceFrom(
image.data[0].addr, wh.x.cint, wh.y.cint, cint 32, 4 * wh.x.cint,
rmask, gmask, bmask, amask,
)
result = createTextureFromSurface(renderer, surface)
destroy(surface)

View File

@ -2,4 +2,4 @@ bin = @["well_of_text"]
license = "Unlicense"
requires: "nim", "syndicate", "sdl2"
srcDir = "src"
version = "20230906"
version = "20230908"