Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vertical Alignment Off #23

Open
brianwozeniak opened this issue Feb 15, 2019 · 6 comments
Open

Vertical Alignment Off #23

brianwozeniak opened this issue Feb 15, 2019 · 6 comments

Comments

@brianwozeniak
Copy link

I am trying to vertically align text, but its definitely off. When I look at your textDimensions method I am a little confused on exactly what this calculation does:

$lineHeight = ( $this->font->ascent + $this->font->descent ) * $fontSize * 2;

Is this really getting the line height of the text? The ascent usually comes in as a positive number, and the descent a negative number. 1 + -1 = 0, how is this measuring distance? Could this be related to to the vertical centering issue?

@kartsims
Copy link
Owner

You are right, these calculations are off ! This was made a long time ago and I am actually surprised it has been used for so long without anyone noticing.

I can't write the code right now so if you want to give it a go, please do.

It should be something along those lines (to include multi line text vertical centering) :

  1. calculate the "real" text height (which is actually calculated by adding ascent and descent)
  2. based on the line height set by the user, calculate the distance between two lines
  3. count the number of lines (by counting the number of \n)
  4. get the total height of the text nb of lines * real text height + (nb of lines - 1) * distance between lines
  5. move the path by (svg height - total text height) / 2

There is probably a check to be made in the code that the bad calculation isn't used somewhere that would mess up the display

Thanks to anyone who would tackle this issue, please send a PR including your own name in a Contributors section of the README (to be created)

@brianwozeniak
Copy link
Author

  1. calculate the "real" text height (which is actually calculated by adding [ascent and descent]

I still think you need to subtract these two, or at least take the absolute value of each before adding them. I ran your code through a debugger and the descent is negative which means its decreasing the total height if adding them together.

Your x-center is being calculated correctly, but for my code I am just manually passing in a Y value now instead of 'center'. I know my formula isn't accurate, but for my situation it gets me in the ballpark which is good enough and lets me move on with my project:

$yCenter = ($heightOfCanvas / 2) - ($fontSize / 1.2)

Dividing the font size by 1.2 for my situation solves the problem for my specific case, but I know that is likely an arbitrary value depending on the font. I think the 1.2 represents the distance between the ascent and top, and the descent and bottom since if you don't take that white space area into the calculation it tends to make it look centered to high or too low. I tried numerous font sizes and it is perfectly centering on the y-axis for me. I am using Open Sans.

@Ambient-Impact
Copy link

Ambient-Impact commented Nov 25, 2019

Instead of jumping through those hoops to calculate the dimensions, couldn't you just figure that from a <path> generated similarly to what you do in addText(), by reading coordinates and calculating a bounding box? I'm trying to get this to generate text using the Furore font, and it has some extra horizontal space (which seems a problem in the font itself) in addition to the existing issues detailed in this thread, so I wonder if such an approach would solve both issues?

@treii28
Copy link

treii28 commented Sep 20, 2022

What about the possibility of parsing the path itself? I found this from part of the meyfa/php-svg library: https://github.com/meyfa/php-svg/blob/main/src/Rasterization/Path/PathParser.php

Feed it the 'd' attribute of the 'path' element. I added something like this to it to get maximums, minimums and relative width and height. I'm assuming the min values represent the top left for translations?:

    public function getBounds($description)
    {
        $bounds = [ 'minX' => 0, 'minY' => 0, 'maxX' => 0, 'maxY' => 0 ];

        foreach($this->parse($description) as $p) {
            if(count($p['args']) == 2) {
                [$x,$y] = $p['args'];
                if($x < $bounds['minX']) $bounds['minX'] = $x;
                if($x > $bounds['maxX']) $bounds['maxX'] = $x;
                if($y < $bounds['minY']) $bounds['minY'] = $y;
                if($y > $bounds['maxY']) $bounds['maxY'] = $y;
                $foo = 'bar';
            }
        };
        $bounds['width'] = $bounds['maxX'] - $bounds['minX'];
        $bounds['height'] = $bounds['maxY'] - $bounds['minY'];
        return $bounds;
    }

I'm still toying with it, but you can do things like $easySvg->addAttribute("viewBox", "0 219 110 68") or add a translate:

        $svgData = simplexml_load_string($easySvg->asXML());
        $svgData->path->addAttribute('transform', "translate(0,40));
        return $svgData->asXML();

(such attributes can be passed in to the addText, but you can't parse the path until it's generated and the svg property is protected. but presumably, something similar could be done inside the addText itself after the path is generated)

@kartsims
Copy link
Owner

kartsims commented Sep 22, 2022

@treii28 I am afraid this approach wouldn't work because for bezier curves (widely used in fonts) the points coordinates aren't always the max X/Y of the line described

@Ambient-Impact that makes sense but you will be getting the vertical alignment based on the min/max height, and depending on the characters, on a multiline text for instance you'd get weird results.

ie.

hi fi
poo
long

each line would be aligned differently and the end result would look off

@raphaelbastide
Copy link

I am very interested in the outcome of this issue or if anyone has any tips about it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants