Skip to content
Snippets Groups Projects
Select Git revision
  • 975937c8c2a3d61d05bf56655704cda06ab60e3f
  • master default protected
  • e-infra2
  • ci-megalinter-speedup
  • e-infra
  • envri-hub-new-aai
  • egi-b2drop-no-collapse
  • lfs
  • gpu_staging
  • resurrect-testing-ownloud
  • experiments/collab
  • update_claim_group_keys
  • envri-hub
  • enable_rtc
  • eosc-ui
  • future/jupyterhub-5.x
  • versioning
  • eosc-templating
  • staging1-raw-image
  • token-exchange
  • del-users
21 results

hub.yaml

Blame
  • text-builder.ts 7.10 KiB
    /**
     * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
     *
     * @author Alexander Rose <alexander.rose@weirdbyte.de>
     */
    
    import { ParamDefinition as PD } from 'mol-util/param-definition';
    import { ValueCell } from 'mol-util/value-cell'
    import { ChunkedArray } from 'mol-data/util';
    import { Text } from './text';
    import { getFontAtlas } from './font-atlas';
    
    const quadIndices = new Uint16Array([
        0, 1, 2,
        1, 3, 2
    ])
    
    export interface TextBuilder {
        add(str: string, x: number, y: number, z: number, depth: number, group: number): void
        getText(): Text
    }
    
    export namespace TextBuilder {
        export function create(props: Partial<PD.Values<Text.Params>> = {}, initialCount = 2048, chunkSize = 1024, text?: Text): TextBuilder {
            initialCount *= 2
            chunkSize *= 2
            const centers = ChunkedArray.create(Float32Array, 3, chunkSize, text ? text.centerBuffer.ref.value : initialCount);
            const mappings = ChunkedArray.create(Float32Array, 2, chunkSize, text ? text.mappingBuffer.ref.value : initialCount);
            const depths = ChunkedArray.create(Float32Array, 1, chunkSize, text ? text.depthBuffer.ref.value : initialCount);
            const indices = ChunkedArray.create(Uint32Array, 3, chunkSize, text ? text.indexBuffer.ref.value : initialCount);
            const groups = ChunkedArray.create(Float32Array, 1, chunkSize, text ? text.groupBuffer.ref.value : initialCount);
            const tcoords = ChunkedArray.create(Float32Array, 2, chunkSize, text ? text.tcoordBuffer.ref.value : initialCount);
    
            const p = { ...PD.getDefaultValues(Text.Params), ...props }
            const { attachment, background, backgroundMargin } = p
    
            const fontAtlas = getFontAtlas(p)
            const margin = (1 / 2.5) * backgroundMargin
            const outline = fontAtlas.buffer / fontAtlas.lineHeight
    
            return {
                add: (str: string, x: number, y: number, z: number, depth: number, group: number) => {
                    let xadvance = 0
                    const nChar = str.length
    
                    // calculate width
                    for (let iChar = 0; iChar < nChar; ++iChar) {
                        const c = fontAtlas.get(str[iChar])
                        xadvance += c.nw - 2 * outline
                    }
    
                    // attachment
                    let yShift: number, xShift: number
                    if (attachment.startsWith('top')) {
                        yShift = 1 / 1.25
                    } else if (attachment.startsWith('middle')) {
                        yShift = 1 / 2.5
                    } else {
                        yShift = 0  // "bottom"
                    }
                    if (attachment.endsWith('right')) {
                        xShift = xadvance
                    } else if (attachment.endsWith('center')) {
                        xShift = xadvance / 2
                    } else {
                        xShift = 0  // "left"
                    }
    
                    // background
                    if (background) {
                        ChunkedArray.add2(mappings, -xadvance + xShift - margin - 0.1, yShift + margin) // top left
                        ChunkedArray.add2(mappings, -xadvance + xShift - margin - 0.1, -yShift - margin) // bottom left
                        ChunkedArray.add2(mappings, xadvance - xShift + margin + 0.1, yShift + margin) // top right
                        ChunkedArray.add2(mappings, xadvance - xShift + margin + 0.1, -yShift - margin) // bottom right
    
                        const offset = centers.elementCount
                        for (let i = 0; i < 4; ++i) {
                            ChunkedArray.add2(tcoords, 10, 10)
                            ChunkedArray.add3(centers, x, y, z);
                            ChunkedArray.add(depths, depth);
                            ChunkedArray.add(groups, group);
                        }
                        ChunkedArray.add3(indices, offset + quadIndices[0], offset + quadIndices[1], offset + quadIndices[2])
                        ChunkedArray.add3(indices, offset + quadIndices[3], offset + quadIndices[4], offset + quadIndices[5])
                    }
    
                    xShift += outline
                    yShift += outline
                    xadvance = 0
    
                    for (let iChar = 0; iChar < nChar; ++iChar) {
                        const c = fontAtlas.get(str[iChar])
    
                        ChunkedArray.add2(mappings, xadvance - xShift, c.nh - yShift) // top left
                        ChunkedArray.add2(mappings, xadvance - xShift, -yShift) // bottom left
                        ChunkedArray.add2(mappings, xadvance + c.nw - xShift, c.nh - yShift) // top right
                        ChunkedArray.add2(mappings, xadvance + c.nw - xShift, -yShift) // bottom right
    
                        const texWidth = fontAtlas.texture.width
                        const texHeight = fontAtlas.texture.height
    
                        ChunkedArray.add2(tcoords, c.x / texWidth, c.y / texHeight) // top left
                        ChunkedArray.add2(tcoords, c.x / texWidth, (c.y + c.h) / texHeight) // bottom left
                        ChunkedArray.add2(tcoords, (c.x + c.w) / texWidth, c.y / texHeight) // top right
                        ChunkedArray.add2(tcoords, (c.x + c.w) / texWidth, (c.y + c.h) / texHeight) // bottom right
    
                        xadvance += c.nw - 2 * outline
    
                        const offset = centers.elementCount
                        for (let i = 0; i < 4; ++i) {
                            ChunkedArray.add3(centers, x, y, z);
                            ChunkedArray.add(depths, depth);
                            ChunkedArray.add(groups, group);
                        }
                        ChunkedArray.add3(indices, offset + quadIndices[0], offset + quadIndices[1], offset + quadIndices[2])
                        ChunkedArray.add3(indices, offset + quadIndices[3], offset + quadIndices[4], offset + quadIndices[5])
                    }
                },
                getText: () => {
                    const ft = fontAtlas.texture
                    const cb = ChunkedArray.compact(centers, true) as Float32Array
                    const mb = ChunkedArray.compact(mappings, true) as Float32Array
                    const db = ChunkedArray.compact(depths, true) as Float32Array
                    const ib = ChunkedArray.compact(indices, true) as Uint32Array
                    const gb = ChunkedArray.compact(groups, true) as Float32Array
                    const tb = ChunkedArray.compact(tcoords, true) as Float32Array
                    return {
                        kind: 'text',
                        charCount: indices.elementCount / 2,
                        fontTexture: text ? ValueCell.update(text.fontTexture, ft) : ValueCell.create(ft),
                        centerBuffer: text ? ValueCell.update(text.centerBuffer, cb) : ValueCell.create(cb),
                        mappingBuffer: text ? ValueCell.update(text.mappingBuffer, mb) : ValueCell.create(mb),
                        depthBuffer: text ? ValueCell.update(text.depthBuffer, db) : ValueCell.create(db),
                        indexBuffer: text ? ValueCell.update(text.indexBuffer, ib) : ValueCell.create(ib),
                        groupBuffer: text ? ValueCell.update(text.groupBuffer, gb) : ValueCell.create(gb),
                        tcoordBuffer: text ? ValueCell.update(text.tcoordBuffer, tb) : ValueCell.create(tb),
                    }
                }
            }
        }
    }