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

Getting the bounding box of a text #124

Closed
gabrielstuff opened this issue Jun 8, 2015 · 22 comments
Closed

Getting the bounding box of a text #124

gabrielstuff opened this issue Jun 8, 2015 · 22 comments

Comments

@gabrielstuff
Copy link

Hi !
I'm trying to get the bounding box of a whole font. Not from each glyph.
Do you plan to integrate it as feature ?

Thanks

@fdb
Copy link
Contributor

fdb commented Jun 9, 2015

The font contains data for this, stored in the font.tables.head table as xMin, xMax, yMin and yMax. So to retrieve the maximum height of all characters, use font.tables.head.yMax.

@steren
Copy link

steren commented Aug 7, 2015

The original request was to get the bounding box of a given text as a Path I guess.

I think it would be great if the Path object would contain such information.

@eric-schleicher
Copy link

+1. We need this for a project we're working on. Is this as simple as determining the min/max x and min/mix y and creating a box from the command data?

I might try and do this right now.

@villanus
Copy link

villanus commented May 5, 2016

Did this work for you?

@panarch
Copy link

panarch commented May 5, 2016

svg-path-bounding-box works well.

@villanus
Copy link

villanus commented May 6, 2016

Sorry, i meant get the size when using in browser.

@panarch
Copy link

panarch commented May 6, 2016

You can use svg-path-bounding-box in browser.

@villanus
Copy link

villanus commented May 6, 2016

@panarch sorry, I am a little not familiar with how nodejs works. Which of the .js files would I reference in the browser?

And how do I call it on a path?
Right now I have:
svgPath = path.toSVG(decimalPlaces);

@panarch
Copy link

panarch commented May 7, 2016

@villanus That's ok, yes it's true that svg-path-bounding-box lib does not provide minified version. So, if you want to use the lib, you may need to use browserify or webpack to make bundle js file.
May be it's just only commonjs used so it's good to simply use browserify.

It looks that the entry file is caster.js

Anyway, in case of using svg-path-bounding-box in node.js is simple.
Something like this,

var getBoundingBox = require('svg-path-bounding-box');
getBoundingBox( { svg path string } );
/* it will return like this below,
{ minX: 10.5,
  x1: 10.5,
  minY: 4.77,
  y1: 4.77,
  maxX: 32.49,
  x2: 32.49,
  maxY: 20.21,
  y2: 20.21,
  width: 21.990000000000002,
  height: 15.440000000000001 }
*/

@villanus
Copy link

villanus commented May 7, 2016

Thanks,
I need to look into this browserify thing.

I have been avoiding NodeJS for the longest time, and now feel stupid when I actually need to use it. =)

@panarch
Copy link

panarch commented May 7, 2016

You're welcome, NodeJS will be ok, it's kind enough compared to web front-end...

@fdb
Copy link
Contributor

fdb commented May 9, 2016

RaphaelJS also has R.pathBBox that can be used to figure out the dimensions. You can pass it path data as returned by OpenType.js's Path.toPathData method. Something like this:

opentype.load('fonts/Roboto-Black.ttf', function(err, font) {
    console.assert(!err);
    var path = font.getPath('Hello, World!', 0, 0, 72);
    var dims = Raphael.pathBBox(path.toPathData());
    console.log(dims.width, dims.height);
});

RaphaelJS is self-contained, so just need to drop in the JS file.

@villanus
Copy link

villanus commented May 9, 2016

thanks

@hypothete
Copy link

SVGPathElements provide a getBBox method as well. If you're creating SVG path elements by parsing the string returned by Path.toSVG(), your path node will not be in the SVG namespace and will be a generic Element.
I've had more success calling document.createElementNS('http://www.w3.org/2000/svg', 'path') to create the path element and then applying the commands from Path.toPathData() to the 'd' attribute.

@villanus
Copy link

@hypothete does this mean you did not have to use a 3rd party library such as SVG.js or Raphael? If so, can you please put a code sample? I read through your comment a few times and am not smart enough to follow. =)

@hypothete
Copy link

hypothete commented May 16, 2016

@villanus for sure, here's what I mean. You don't need a 3rd party library for this measurement when you are working on the frontend. This does not apply to node.js.

//assume we have an opentype Path object called 'textPath'
var pathElem = document.createElementNS('http://www.w3.org/2000/svg', 'path');
pathElem.setAttribute('d', textPath.toPathData(precision));
console.dir(pathElem); //log out the object to inspect

Since I'm explicitly creating the element in the SVG namespace, its prototype is the SVGPathElement instead of a generic Element, and so it has additional methods like getBBox that you couldn't get otherwise.

Here's how to create the path element incorrectly as a generic Element. Don't do this!

var domp = new DOMParser(),
    pathString = '<path d="M0,0 L50,0 L50,50 L0,50Z" fill="red" />',
    pathElem = domp.parseFromString(pathString, 'image/svg+xml').documentElement;
console.dir(pathElem);

You would think that providing the MIME type to the parser would handle assigning the right element type to the parsed path, but it does not.

Now we want to measure the path. To get the bounds reliably across browsers, you must place the path on the DOM. This code makes a temporary SVG, adds it to the body, and removes it when we're done taking our measurement:

var tempSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
document.body.appendChild(tempSvg);
tempSvg.appendChild(pathElem);
var pathBounds = pathElem.getBBox(); //tada
document.body.removeChild(tempSvg);
console.log(pathBounds);

@fdb
Copy link
Contributor

fdb commented May 19, 2016

Creating a SVG Path element correctly seems like something useful to add to the OpenType.js API (with a disclaimer that it only works in the browser environment).

I didn't know you had to add it to the DOM to measure it correctly though! That's a bit silly.

@Jolg42
Copy link
Member

Jolg42 commented May 19, 2016

@fdb yes… :(
For Node I know that svgicons2svgfont is using sax for parsing xml & extracting svg infos + converting svg shapes to path.

@villanus
Copy link

@hypothete Thank you!
@fdb I agree, it should be added to the core.

@eric-schleicher
Copy link

Would jsdom support this?

I have other node code the uses createElementNS in jsdom in svg namespace
without issue. I dont have an example where im getting bbox but will try
and report back
On May 19, 2016 2:48 PM, "Frank" notifications@github.com wrote:

@hypothete https://github.com/hypothete Thank you!
@fdb https://github.com/fdb I agree, it should be added to the core.


You are receiving this because you commented.
Reply to this email directly or view it on GitHub
#124 (comment)

@cyberwombat
Copy link

cyberwombat commented Nov 28, 2016

@hypothete have you tried your fix in IE<11? I am unclear as to older IE SVG support. Seems like spotty support before 11. I guess OpenType works in IE10+ so that would be the only issue.

@fdb
Copy link
Contributor

fdb commented Jan 9, 2017

Version 0.6.8 now includes a getBoundingBox method on the Path and Glyph objects. This object is similar to svg-path-bounding-box: it has x1/y1/x2/y2 coordinates.

@fdb fdb closed this as completed Jan 9, 2017
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

9 participants