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

Refactoring/vector_xxx() #107

Merged
merged 25 commits into from Jun 18, 2018
Merged

Refactoring/vector_xxx() #107

merged 25 commits into from Jun 18, 2018

Conversation

ghost
Copy link

@ghost ghost commented May 13, 2018

New features

  • options first
  • defaults options
  • text height (see note below)
  • multiline text alignement
  • letters spacing
  • lines spacing
  • extrusion (see note below)

New syntax

vectorChar([options], char)

  • {Object|String} [options] - options for construction or ascii character
    • {Float} [options.xOffset=0] - x offset
    • {Float} [options.yOffset=0] - y offset
    • {Float} [options.height=21] - font size (uppercase height)
    • {Float} [options.extrudeOffset=0] - width of the extrusion that will be applied manually after the creation of the character
    • {String} [options.input='?'] - ascii character (ignored/overwrited if provided as seconds parameter)
  • {String} [char='?'] - ascii character

vectorText([options], text)

  • {Object|String} [options] - options for construction or ascii string
    • {Float} [options.xOffset=0] - x offset
    • {Float} [options.yOffset=0] - y offset
    • {Float} [options.height=21] - font size (uppercase height)
    • {Float} [options.lineSpacing=1.4] - line spacing expressed as a percentage of font size
    • {Float} [options.letterSpacing=1] - extra letter spacing expressed as a percentage of font size
    • {String} [options.align='left'] - multi-line text alignement: left, center or right
    • {Float} [options.extrudeOffset=0] - width of the extrusion that will be applied manually after the creation of the character
    • {String} [options.input='?'] - ascii string (ignored/overwrited if provided as seconds parameter)
  • {String} [text='?'] - ascii string

Old syntax supported but discouraged

vector_char(x, y, char)
vector_text(x, y, text)

Text height and extrusion

  • Text and char height is given for uppercase lowecase letters.
  • Since vectorXXX functions return glyphs in the form of segments it is necessary to extrude along the segments to get a 3D object. The text/char height is given for the segments, but for precise sizing you can anticipate the extrude offset by specifying the parameter options.extrudeOffset. Or you can set both options.extrude.w and options.extrude.h and get a CSG rather than text or char segments.

Preview

jscad

Example

function main(params) {
    let char0 = vectorChar().segments;
    let char1 = vectorChar('!').segments;
    let char2 = vectorChar({ xOffset: 50 }, 'H').segments;
    let char3 = vectorChar({ xOffset: 75, input: 'e' }).segments;
    let char4 = vectorChar({ xOffset: 100, height: 10, extrudeOffset: 1, input: 'Y' }).segments;

    let text0 = vectorText();
    let text1 = vectorText('OpenJSCAD');
    let text2 = vectorText({ yOffset: 20 }, 'OpenJSCAD');
    let text3 = vectorText({ yOffset: -10, input: 'OpenJSCAD', letterSpacing: 1.5 });
    let text4 = vectorText({ yOffset: -40, extrudeOffset: 2, input: 'OpenJSCAD\nLOVE<3' });
    let text5 = vectorText({ yOffset: -90, height: 10, extrudeOffset: 2, input: 'OpenJSCAD\nLOVE<3' });
    let text6 = vectorText({ height: 25, align: 'right', lineSpacing: 2.2, extrudeOffset: 2 }, lorem);

    return [
        csgFromSegments(char0).translate([-100, 80]),
        csgFromSegments(char1).translate([-75,  80]),
        csgFromSegments(char2).translate([-100, 80]),
        csgFromSegments(char3).translate([-100, 80]),
        csgFromSegments(char4).translate([-100, 80]),

        csgFromSegments(text1).translate([-100, 50]),
        csgFromSegments(text2).translate([-100, 0]),
        csgFromSegments(text3).translate([-100, 0]),
        csgFromSegments(text4).translate([-100, 0]),
        csgFromSegments(text5).translate([-100, 0]),
        csgFromSegments(text6).translate([-300, 40])
    ];
}

function csgFromSegments (segments) {
  let output = [];
  segments.forEach(polyline => output.push(
    rectangular_extrude(polyline, { w:2, h:1 })
  ));
  return union(output);
}

const lorem = `Lorem
ipsum
dolor
sit
amet...`;

@z3dev
Copy link
Member

z3dev commented May 13, 2018

SMILE

@ghost
Copy link
Author

ghost commented May 13, 2018

I'm compiling some single line fonts, it's coming soon...

@z3dev
Copy link
Member

z3dev commented May 13, 2018

This is going to be awesome. Take your time... we can wait a little longer.

Do you need this merged now?

@ghost
Copy link
Author

ghost commented May 13, 2018

@z3dev no need to merge now ;)

@kaosat-dev
Copy link
Contributor

Wow this is great once more !
Will take me a bit of time to go through all the potential API variations that you have in there , but it looks good on first glance!
The only thing I am a bit doubtful about is the ability to generate CSG's directly (I think single purpose functions should be favored). But I'll first dig into the rest of the code ;)

@ghost
Copy link
Author

ghost commented May 14, 2018

The only thing I am a bit doubtful about is the ability to generate CSG's directly (I think single purpose functions should be favored). But I'll first dig into the rest of the code ;)

I agree, I also hesitate to add it. In addition it raises some circular dependencies in unit tests...

@kaosat-dev
Copy link
Contributor

Sorry for the slowness @lautr3k but I think I can review in full tomorrow :)

@jonsadka
Copy link

Small nit: would be great if we could change the argument pattern from vectorText([options], text) to vectorText(text, [options])

@kaosat-dev
Copy link
Contributor

@jonsadka the order of arguments is (options, text) on purpose and is our standard for the upcoming 'V2' of csg.js as well for multiple reasons

  • for coherence with the rest of the API
  • for the ability to apply currying to functions when applicable
  • for the ability to pass multiple objects where applicable (ie not for text specifically but for example translate([0,10,1], obj1, obj2, obj3) etc
  • there can also be a way of detecting the argument type so that vectorText(text) (no options) would still work

@z3dev
Copy link
Member

z3dev commented May 16, 2018

I was playing with a new design, and downloaded the HAVANA font.

http://legionfonts.com/fonts/habana

This is really small, only 19.1K. Is there anyway to embed this font (or another) rather then the vector based font?

FYI, the code for the vector based font is 45K.

@ghost
Copy link
Author

ghost commented May 17, 2018

FYI, the code for the vector based font is 45K.

What ??? the new code for vectorXXX is now about 8K (5K without the comments)....
And the font file itself is now 7K vs 45K before !!! Total for all things 15K !!!

I was playing with a new design, and downloaded the HAVANA font.
...
This is really small, only 19.1K. Is there anyway to embed this font (or another) rather then the vector based font?

We can embed/replace what you want, but your font is not single-line and will not work with vectorXXX, remember what i said "I'm compiling some single line fonts, it's coming soon..," Most of the fonts come from there with an explanation of what a single-line font is.

For all other fonts wait for the text() function which will return an CAG object from a list of polygons (instead of a list of open paths).

Copy link
Contributor

@kaosat-dev kaosat-dev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice PR once again , thanks for all the great work !
I added a few points that I think need tweaking, but great work overall !

@@ -1,41 +1,213 @@
const test = require('ava')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lots of very thorough tests, awesome !

// -- reduced to save some bytes...
// { [ascii code]: [width, x, y, ...] } - undefined value as path separator
module.exports = {
height: 21,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

very nice & compact

// FIXME ! circular dependencies (only in test)
// location: core\math\Path2.js:197
// message : CAG.fromSides is not a function
test.failing('vectorChar ({ height, extrude }, char)', t => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hurray for v2 !

char = char.charCodeAt(0)
char -= 32
if (char < 0 || char >= 95) return { width: 0, segments: [] }
const defaultsVectorParams = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure I understand why the defaults are outside the function ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because is shared from the two functions (avoid multiple sources of truths and save some bytes)

src/api/text.js Outdated
char -= 32
if (char < 0 || char >= 95) return { width: 0, segments: [] }
const defaultsVectorParams = {
x: 0,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think x & y should be named xOffset & yOffset : clarity is better than concision, and I did not immediately understand their purpose in the tests before looking the implementation up

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those names probably come from SCAD API.

But I must agree that xoffset, yoffset are more meaningful.

src/api/text.js Outdated
height: 21, // == old vector_xxx simplex font height
lineSpacing: 1.4285714285714286, // == 30/21 == old vector_xxx ratio
letterSpacing: 1,
extrude: { w: 0, h: 0 }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

like x&y , I think w should be width and h should be height, again for clarity rather than concision

src/api/text.js Outdated
* let vectorCharObject = vector_char(36, 0, 'B')
*/
function vector_char (x, y, char) {
return vectorChar({ x, y }, char)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice way of doing non breaking changes ! 👍

src/api/text.js Outdated
* let textSegments = vector_text(0, -20, 'OpenJSCAD')
*/
function vector_text (x, y, text) {
return vectorText({ x, y }, text)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, well done ! 👍

src/api/text.js Outdated
* @param {Float} [options.extrude.h=0] - extrusion height, if > 0 the function return a CSG object
* @param {String} [options.input='?'] - ascii character (ignored/overwrited if provided as seconds parameter)
* @param {String} [char='?'] - ascii character
* @returns {VectorCharObject|CSG} vectorCharObject or an CSG object if `options.extrude.h` is > 0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as discussed, I really think extrusion to a CSG should be left out of this , there are already tools for that , single purpose functions are better :)

@z3dev
Copy link
Member

z3dev commented May 17, 2018

Compact is good! Thanks again for the explanations.

@kaosat-dev
Copy link
Contributor

@lautr3k thanks for the changes and sorry for the delay !
It looks all good to me, I will take it for a spin tomorrow, and (finally) merge ;)

@ghost
Copy link
Author

ghost commented Jun 4, 2018

The font can be passed as a parameter. I have compiled several fonts like JSCAD module on another repository (not yet published), which can be simply included like any other JSCAD module.

Include the font with include('fonts/CamBamStick9.jscad'); and then access to it with CamBamStick9Font().

jscad

@z3dev
Copy link
Member

z3dev commented Jun 4, 2018

@lautr3k thanks!

If you think the fonts can / will be reused then we could maintain another special repository. Could be interesting.

And even more valuable if characters beside ASCII are included. Are there single line fonts that supply the complete UTF8 set? That would be quite large.

@ghost
Copy link
Author

ghost commented Jun 4, 2018

@z3dev i have made a vector font "compiler" (provided in the repo). You'll be able to virtualy compile any single line fonts you want.

@ghost
Copy link
Author

ghost commented Jun 5, 2018

@z3dev @kaosat-dev https://github.com/lautr3k/jscad-vector-fonts the documentation is very basic, but that's enough to understand I think? All the fonts are not present yet, but there's already 22, that's enough to test.

@z3dev
Copy link
Member

z3dev commented Jun 5, 2018

Once again... so nice. Thanks!

@kaosat-dev
Copy link
Contributor

@lautr3k thanks for the addition, great work :)
Yep, the documentation in the jscad-vector-fonts repo seems good enough! and 22 is huge !
A few questions though:

  • from my understanding the default font is hershey/simplex.jsright ?
  • this means there will be two different font formats down the line ? (ie the vector-fonts above & the more complex fonts in standard font files)
    do you view this as a 'step towards full fonts' or do you think both should stick around ?
  • vector_char,
    vector_text,
    vectorChar,
    vectorText
    are all exported, vector_char & vector_text are for the current API and the other ones for the future right ?

@z3dev
Copy link
Member

z3dev commented Jun 13, 2018

@lautr3k
We would love to merge this. Are there any more changes planned?

@kaosat-dev
Copy link
Contributor

thanks a lot @lautr3k for your huge work , merging !

@kaosat-dev kaosat-dev merged commit eadcd58 into jscad:master Jun 18, 2018
@z3dev
Copy link
Member

z3dev commented Jun 19, 2018

Awesome!

@ghost ghost deleted the refactoring/vector_xxx() branch June 24, 2018 05:34
kaosat-dev pushed a commit that referenced this pull request Aug 15, 2018
…char system (#107)

This PR adds lots of new features, overhauls the implementation, and provides a future facing set of API changes for the text handling

(cherry picked from commit eadcd58)
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

Successfully merging this pull request may close these issues.

4 participants