pharo-graphics / Alexandrie

FFI bindings and a 2D canvas for Pharo based on Cairo, Freetype and Harfbuzz
MIT License
5 stars 2 forks source link

Crash on Hb example #42

Closed tinchodias closed 11 months ago

tinchodias commented 12 months ago

Reported by Renaud @rvillemeur in mailing-list: (+ very small adaptation)

| surface context text buffer fontLibrary freetypeFace fontHeight scaledFont fontOptions |
fontHeight := 22.
text := 'a := A->B->>C <= c|=>d~~>e.'.
surface := AeCairoImageSurface
           extent: 1000 @ (fontHeight * 2)
           format: AeCairoSurfaceFormat argb32.
context := surface newContext.
context
sourceColorRGBA: Color white;
paint.

"Margin"
context translateBy: fontHeight / 2 @ 0.
"----------------------------------------------------------"
fontLibrary := AeFTLibrary newInitialized.
freetypeFace := AeCascadiaCodeDownloadedFont new
                downloadDirectory:
                AeFilesystemResources downloadedFontsDirectory;
                ensureDownloaded;
                firstFaceUsing: fontLibrary.
fontOptions := AeCairoFontOptions new
               antialias: AeCairoAntialias fast;
               hintMetrics: AeCairoHintMetrics on;
               hintStyle: AeCairoHintStyle slight;
               subpixelOrder: AeCairoSubpixelOrder default.
scaledFont := AeCairoScaledFont
              fontFace:
              (AeCairoFreetypeFontFace newForFace: freetypeFace)
              fontMatrix:
              (AeCairoMatrix newScalingByX: fontHeight y: fontHeight)
              userToDeviceMatrix: AeCairoMatrix newIdentity
              options: fontOptions.
"Draw text with Harfbuzz:"
buffer := AeHbBuffer new
          direction: AeHbDirection leftToRight;
          script: AeHbScript latin;
          language: AeHbLanguage en;
          clusterLevel: AeHbBufferClusterLevel recommended;
          flags: AeHbBufferFlags beginningOrEndingOfText;
          addString: text.
context translateBy: 0 @ (fontHeight * 1.1).
context sourceColorRGB: Color green muchDarker.
context
scaledFont: scaledFont;
showGlyphs:
(buffer cairoGlyphArrayForFace: freetypeFace size: fontHeight).
^ surface asForm
tinchodias commented 11 months ago

Hi, I run it now in P11 and P12 and don't get a crash but only unexpected rendering output. I'm checking what happens. Probably it's fixed by a change where I added references in font objects (else Garbage collector could free some objects before it should).

I paste the adapted script, since now sourceColorRGBA: is deprecated:

| surface context text buffer fontLibrary freetypeFace fontHeight scaledFont fontOptions glyphs |
fontHeight := 22.
text := 'a := A->B->>C <= c|=>d~~>e.'.
surface := AeCairoImageSurface
           extent: 1000 @ (fontHeight * 2)
           format: AeCairoSurfaceFormat argb32.
context := surface newContext.
context
    sourceColor: Color white;
    paint.

"Margin"
context translateBy: fontHeight / 2 @ 0.
"----------------------------------------------------------"
fontLibrary := AeFTLibrary newInitialized.
freetypeFace :=
                AeCascadiaCodeDownloadedFont new
                downloadDirectory:
                AeFilesystemResources downloadedFontsDirectory;
                ensureDownloaded;
                firstFaceUsing: fontLibrary.
fontOptions :=
       AeCairoFontOptions new
               antialias: AeCairoAntialias fast;
               hintMetrics: AeCairoHintMetrics on;
               hintStyle: AeCairoHintStyle slight;
               subpixelOrder: AeCairoSubpixelOrder default.
scaledFont :=
        AeCairoScaledFont
              fontFace:
                 (AeCairoFreetypeFontFace newForFace: freetypeFace)
              fontMatrix:
                 (AeCairoMatrix newScalingByX: fontHeight y: fontHeight)
              userToDeviceMatrix: AeCairoMatrix newIdentity
              options: fontOptions.
buffer :=
     AeHbBuffer new
          direction: AeHbDirection leftToRight;
          script: AeHbScript latin;
          language: AeHbLanguage en;
          clusterLevel: AeHbBufferClusterLevel recommended;
          flags: AeHbBufferFlags beginningOrEndingOfText;
          addString: text.
glyphs := buffer cairoGlyphArrayForFace: freetypeFace size: fontHeight.
context translateBy: 0 @ (fontHeight * 1.1).
context sourceColor: Color green muchDarker.
context
    scaledFont: scaledFont;
    showGlyphs: glyphs.

surface asForm inspect

The unexpected result is:

Screenshot 2023-11-23 at 10 25 24
tinchodias commented 11 months ago

@rvillemeur now the output is:

Screenshot 2023-11-23 at 11 45 21
rvillemeur commented 10 months ago

crash.zip @tinchodias , unfortunately, I can still experience the problem (as of 15 of dec 2023). My script is

| aFTLibrary aFace aeCanvas cairoScaledFont  fontHeight string glyphs|
    aFTLibrary := AeFTLibrary newInitialized.
    aFace := AeCascadiaCodeDownloadedFont new 
        downloadDirectory: AeFilesystemResources downloadedFontsDirectory;
        ensureDownloaded;
        firstFaceUsing: aFTLibrary.
fontHeight := 20.
string := 'a := A->B->>C <= c|=>d~~>e.'.

    aeCanvas := AeCanvas extent: 1000 @ (fontHeight * 4).
    aeCanvas clear: Color white.

    cairoScaledFont := aeCanvas scaledFontForFace: aFace size: fontHeight.

    "Margin"
    aeCanvas pathTranslate: (fontHeight/2) @ 0.

    "Draw text with Harfbuzz:"
    aeCanvas pathTranslate: 0 @ (fontHeight*1.1).
    aeCanvas setSourceColor: Color green muchDarker.
    glyphs := AeHbBuffer new
        direction: AeHbDirection leftToRight;
        script: AeHbScript latin;
        language: AeHbLanguage en;
        clusterLevel: AeHbBufferClusterLevel recommended;
        flags: AeHbBufferFlags beginningOrEndingOfText;
        addString: string;
        cairoGlyphArrayForFace: aFace size: fontHeight.

    aeCanvas
        drawText: glyphs
        font: cairoScaledFont.

    ^ aeCanvas asForm

If I execute it several time very quickly in a playground, I'll experience a crash. I have the same behaviour on Windows 10 and Fedora Linux 38, latest Pharo 11 fresh image and latest VM update. It's frustrating because this script is a direct write of AeHarfbuzzRenderExample class >> example5CascadiaCode which seems to work OK (no crash experienced), so it's look like a timing issue, but as I don't have any crash message, I can't figure out what goes wrong. I added crash.dmp as watched on my linux machine.

Ducasse commented 10 months ago

Thanks Renault. Can you open a new issue with a pointer to this one?

rvillemeur commented 10 months ago

Thanks Renault. Can you open a new issue with a pointer to this one?

Done. I have spent a couple of hour trying to figure out if I was missing something, or if I could document how it should work to avoid unwanted crash...