• Matching fonts in Figma ?

    General Questions
    4
    0 Votes
    4 Posts
    38 Views
    ChazroxC

    @lalalandsynth I gave your screenshot to Claude:

    Short version: the number you hand a JUCE/HISE Font is not the same quantity Figma calls "font size," and HISE's drawText doesn't lay glyphs out the same way Figma does. Those are two separate problems, and your three screenshots are actually showing both of them at once.

    Why the size number is different (the 16-vs-12 clue)

    Figma's font size is the em / point size — the classic typographic size. JUCE's plain Font(float) constructor does not take that. Historically it takes the font's total height (ascent + descent), which for most typefaces is larger than the em by roughly 1.2–1.35×. Your own result nails it: 16 in HISE ≈ 12 in Figma is a 1.333 ratio, which is exactly that height-to-em factor for your font. So when you type "12" into a HISE paint routine, you're really asking for a glyph whose height is 12px, which is a visibly bigger letter than a 12px-em Figma glyph.

    The fix is to size by point height instead of raw height:

    Newer JUCE / HISE: Font(FontOptions().withPointHeight(12.0f)), or someFont.withPointHeight(12.0f).
    If you only have the old API, multiply your Figma px by the font's em-to-height factor (≈1.33 here) — but withPointHeight is the correct, font-independent way.

    That single change is why your third screenshot ("make a text label and set it to 16") looks better and different: a real Label/TextLayout path applies proper metrics, whereas your hand-rolled paint routine was fighting the height/em confusion.

    Why it drifts in the middle even when the ends line up

    The accumulating spread in screenshot 1 (matches at the left, red creeps wider across the word) and the "fits end-to-end but wrong in the middle" in screenshot 2 are a layout/kerning problem, not a size problem. When you scaled the whole string to make the endpoints match, you corrected the total width but not the individual glyph advances — so every interior letter sits at a slightly wrong x. That happens because:

    Your paint routine is almost certainly stepping glyph-by-glyph and summing advance widths (or letting JUCE's older glyph path do it) with no kerning / no HarfBuzz shaping, while Figma shapes the run with full kerning and fractional positioning. The per-pair differences add up left-to-right, which is exactly the linear drift you see.
    Subpixel rounding: if positions are being rounded to integer pixels per glyph, the error accumulates too.

    Fix: don't advance glyphs yourself. Use a juce::GlyphArrangement / TextLayout (or Label / drawText) so the same shaping and kerning is applied, rather than a manual per-character loop. In JUCE 8 the text backend switched to HarfBuzz shaping, which gets much closer to what a design tool does — worth knowing if HISE's JUCE version matters here.

    The thing that's easy to miss: is HISE even using your font?

    You labeled red as "paint routine font (not label)." If the exact TTF isn't loaded as a typeface and you're selecting it by name, JUCE will silently fall back to a default face with completely different metrics — which would also produce width drift and a size mismatch. Make sure the paint routine is drawing with the same embedded typeface (loaded via the loaded font / Typeface::createSystemTypefaceFor on the actual TTF bytes), not just Font("SomeName", ...). A name lookup that fails is the single most common cause of "my custom font is subtly wrong in JUCE."

    What I'd do, in order

    Confirm the paint routine is drawing the actual embedded TTF, not a name-matched fallback.
    Switch sizing to withPointHeight() so the HISE number equals the Figma px number.
    Replace any manual glyph-advance loop with GlyphArrangement/drawText so kerning and fractional positioning match.

    Do those three and the red should sit on the black without the mid-word drift — and you won't need the 1.33 fudge anymore.

    If you paste the actual HISE paint routine (the LAF/drawText snippet and how the font is created/loaded), I can point at the exact line that's causing each effect.

  • 0 Votes
    1 Posts
    5 Views
    No one has replied
  • 4 Votes
    15 Posts
    436 Views
    OrvillainO

    @dannytaurus said in Why I'm not making a Windows installer (nor code-signing):

    If by alpha testing, you mean on your own machine and a few developer friends, then yes that'll work but it's unlikely to survive contact with the real world.

    It does. I have 30 odd testers up and running.

  • 0 Votes
    2 Posts
    19 Views
    David HealeyD

    @rawl747 I'm not aware of a specific channel switch midi message. What does a midi monitor show when it receives one of these messages from Dorico?

  • [BLOG] How does DSP work? [Part 2]

    C++ Development
    2
    6 Votes
    2 Posts
    45 Views
    David HealeyD

    @griffinboy Thanks for this. Put a link to part 1 at the top.

  • 1 Votes
    10 Posts
    246 Views
    ospfeigrpO

    @Chazrox yea similar to cosmos but cross platform at least win and linux it have a nice pixeldrain feature for sharing uploading user generated samples etc

  • letter spacing / kerning on ScriptLabel

    Feature Requests
    12
    0 Votes
    12 Posts
    185 Views
    David HealeyD

    @lalalandsynth I use a font unless I need to manipulate in some way that is easier outside of HISE. For example my company logo I use a vector.

  • BLUR.

    Bug Reports
    22
    0 Votes
    22 Posts
    184 Views
    lalalandsynthL

    @ustk Sweet , thanks !

  • 0 Votes
    10 Posts
    117 Views
    Christoph HartC

    @musicayciencia globals are used when you need to share data between script processors - although David correctly suggests that this should be the last tool you pick for that as there are way better ways for cross-module communication by now. The callback of a single script processor share all the variables declared in the onInit callback.

    Now about the non-deterministic issue: if you compile that script it won't cause an error, as the JS compiler cannot know whether the variable setGlobalVariable is a function that can be called - it might get assigned to something callable at some point so it stays put and doesn't complain. However when you play a note, then it's time to call this variable and that's where HISE realises that you can't execute the (empty) variable.

    var callableAtSecondTime = undefined; function onNoteOn() { callableAtSecondTime(); } function onNoteOff() { callableAtSecondTime = function() { Console.print("Now I work"); }; }

    This script will throw an error when you press the first note, but the first note off will then assign a function to the variable so subsequent notes will not raise the error but call the function. That example looks weird, but it's one of the more powerful features of JS (and HiseScript) to be able to reassign function slots to different functions like this so you can implement dynamic logic more easily.

  • How do I complete the jucer part in export setup wizard?

    Newbie League
    16
    0 Votes
    16 Posts
    144 Views
    LindonL

    @39oririn

    go to :

    https://github.com/christophhart/hise-cli

    and follow the instructions there...

  • Automatization!

    General Questions
    3
    0 Votes
    3 Posts
    65 Views
    gonzaloG

    @dannytaurus thank you so much my friend! 😁🙏🏻

  • [BLOG] How does DSP work? [Part 1]

    C++ Development
    7
    8 Votes
    7 Posts
    146 Views
    gonzaloG

    so cool my friend!

  • Hi! 👋🏻🙌🏻

    Blog Entries
    8
    8 Votes
    8 Posts
    251 Views
  • 0 Votes
    1 Posts
    39 Views
    No one has replied
  • Confused about Matrix Modulator Value Ranges

    General Questions
    1
    0 Votes
    1 Posts
    43 Views
    No one has replied
  • Added ShowFolderRows option to Preset Browser

    General Questions
    3
    2 Votes
    3 Posts
    64 Views
    dannytaurusD

    @David-Healey Yours always seems to be more generally useful than mine though 😂

    This one is pretty niche but I'll likely be using single column preset browsers in most of my plugins, so it's really useful for me.

  • 13 Votes
    120 Posts
    27k Views
    ChazroxC

    @digi @lalalandsynth lol I included the 'Control Token' feature so you can mess around with it and see if its something we should keep. See at the bottom of every 'ARC' layer there is a 'Token Control' toggle. Toggle that one and you can choose between controlling the arc with either a 'GlobalCable' or by connecting it to the components native 'Mod' values. In theory it should work, but I suck at wiring up the mod matrix so I could use some help testing this out. I would not use the GlobalCable mode just yet. I think I have to nail down some of the Hise code gen for this part. Try the 'Native' mode and hook up the knob to a mod source in HISE. I got it to "WORK" as much as seeing the mod source value move the arc knob properly but I still dont know how this will do in actual use case. Lmk what you guys think about that one. 🙏

    @ustk Can you please give it a go if you have a minute? I know you're pretty well versed in using modValues.

    (at the bottom of each ARC layer properties)
    Screenshot 2026-07-27 at 4.40.12 PM.png

  • Draggable Filter Panel PathType: Options?

    General Questions
    2
  • How to do text links in a settings panel?

    General Questions
    17
    0 Votes
    17 Posts
    846 Views
    dannytaurusD

    I also added a LineSpacing and LetterSpacing to the Markdown renderer so I can style it to match my plugin.

    https://github.com/christophhart/HISE/pull/1008

  • [bug] createScreenshot doesn't capture peak meters

    Solved Bug Reports
    3
    0 Votes
    3 Posts
    462 Views
    David HealeyD

    Had Claude fix this bug and also added an optional scaling parameter to the screenshot function: https://github.com/christophhart/HISE/pull/1004