metafloor / bwip-js

Barcode Writer in Pure JavaScript
Other
2.09k stars 301 forks source link

Code 128 internal error when unused ^NNN under some conditions #176

Open semireg opened 4 years ago

semireg commented 4 years ago

There seems to be an issue when unrecognized (unparsed?) ^NNN are encountered, but not "enabled" via parse option(s). This should probably fail gracefully by just rendering the ^NNN. I wrote "options" plural because I thought I could trigger this error with a different combination of parse/parsefnc... but looks like this is all I can reproduce for now.

TypeError: undefined is not an object (evaluating 's.length')
$P@http://bwip-js.metafloor.com/demo/dist/bwip-js-min.js:41:2708
http://bwip-js.metafloor.com/demo/dist/bwip-js-min.js:41:69701
http://bwip-js.metafloor.com/demo/dist/bwip-js-min.js:41:716622
Render@http://bwip-js.metafloor.com/demo/dist/bwip-js-min.js:41:718600
ToCanvas@http://bwip-js.metafloor.com/demo/dist/bwip-js-min.js:41:717027
render@http://bwip-js.metafloor.com/demo/demo.html:160:18

Image from demo.

2020-08-18 at 8 56 PM

metafloor commented 4 years ago

@terryburton: The error is occurring in the postscript code. The code does a get on the fncvals dict using the 4 characters after the ^ (i.e. 076^). This generates an undefined error. Here is the code:

            parsefnc char 94 eq and i barlen 4 sub lt and {
                barcode i 1 add get 94 ne {
                    /char fncvals barcode i 1 add 4 getinterval get def   %% undefined error
                    text j ( ) putinterval
                    /i i 4 add def
                } {
                    /i i 1 add def
                } ifelse
            } if

That get can be protected with a known test:

            parsefnc char 94 eq and i barlen 4 sub lt and {
                barcode i 1 add get 94 ne {
                    fncvals barcode i 1 add 4 getinterval known {  %% Test before get
                        /char fncvals barcode i 1 add 4 getinterval get def
                        text j ( ) putinterval
                        /i i 4 add def
                    } if
                } {
                    /i i 1 add def
                } ifelse
            } if

I tested that on my version of barcode.ps and it works as expected. Unfortunately, this pattern is in a lot of the encoders...

terryburton commented 4 years ago

That get can be protected with a known test:

True, but if we are accepting of ^XXXX for unknown sequences then we ossify the API as we cannot later introduce new function characters entries without possibly breaking existing users. (I don't care too much about this: BWIPP isn't baked into things in a way that's difficult to change.)

I would certainly be better to throw a specific BWIPP error rather than fail in the PostScript.

Perhaps something like this?

/fn1 -1 def
/fncvals <<
    (FNC1) fn1
>> def
/msg barlen array def
/i 0 def /j 0 def {
    i barlen eq {exit} if
    /char barcode i get def
    /i i 1 add def
    parsefnc char 94 eq and {
        barcode i 4 barlen i sub 2 copy gt {exch} if pop getinterval
        dup fncvals exch known not {
            dup length 28 add string dup 28 4 -1 roll putinterval
            dup 0 (Unknown function character: ) putinterval
            /bwipp.xxxUnknownFnc exch //raiseerror exec
        } if
        fncvals exch get /char exch def
        /i i 3 add def
    } if
    msg j char put
    /j j 1 add def
} loop
/msg msg 0 j getinterval def
/msglen msg length def

I hope to add support for ECI at some point in the future as I'm currently helping to revise the ISO standard and things will hopefully be more workable in future. At that point well need to introduce support for six-digit function character, e.g. (^ECI000004data_starts_here).

Also we need to support GS1 data containing ( and ) characters, so it's likely that the routines handling ^000, ^FNCx and GS1 AI syntax parsing will be reworked (and possibly combined) in some way.

metafloor commented 4 years ago

That seems reasonable. And gives the caller an idea of what they did wrong.

@semireg: The reason your input is incorrect is when the parsefnc flag is set, you must escape any plain carets ^ in the text by doubling them up i.e. ^^076^^FOO:

image

terryburton commented 4 years ago

I've pushed a commit for parsefnc error reporting and ECI parsing (but not encoding yet).

I'll give it a while before tagging it as a release.

melnik10 commented 2 years ago

@terryburton Hello! I get this mistake for barcode 'фывфыафыаф' Help me please.

bwipjs.toCanvas( canvas, { bcid: params.type, //code128 scale: params.scale, height: params.height, includetext: params.includeText, textxalign: 'center', text: text, textcolor: '000000', monochrome: true, textsize: (params.textSize ? params.textSize : 10), textyalign: 'below', parsefnc: true });

TypeError: Cannot read properties of null (reading 'pixels') at Object.getglyph (bwip-js.mjs:36610:1) at Object.measure (bwip-js.mjs:36064:1) at BWIPJS.stringwidth (bwip-js.mjs:35619:1) at bwipp_renlinear (bwip-js.mjs:35009:1) at bwipp_code128 (bwip-js.mjs:6991:1) at bwipp_encode (bwip-js.mjs:35128:1) at _Render (bwip-js.mjs:201:1) at Object.ToCanvas [as toCanvas] (bwip-js.mjs:65:1) at Function.drawBarcode (label.tsx:336:9) at Function.draw (label.tsx:523:30)

metafloor commented 2 years ago

The built-in fonts with bwip-js include mostly 7-bit ascii characters, with a small subset of iso-8859-1 8-bit chars. You will need to load a custom font to render your text correctly.

melnik10 commented 2 years ago

@metafloor Thank you. https://peckconsulting.s3.amazonaws.com/fontconverter/fontconverter.html I converted my ttf to js module.

bwipjs.loadFont('arial', 100, arialNormalFont) bwipjs.toCanvas( canvas, { bcid: params.type, scale: params.scale, height: params.height, includetext: params.includeText, textxalign: 'center', text: text, textcolor: '000000', textfont: 'arial', monochrome: true, textsize: (params.textSize ? params.textSize : 10), textyalign: 'below', parsefnc: true });

I am getting the same error.

metafloor commented 2 years ago

Wow. Really old bug that was never handled correctly in the 2.0 release. Postscript works in UTF-8 and the bwip-js code never mapped from UTF-8 to UTF-16 (actualy UCS-2 since surrogates are not supported) when rendering the glyphs. Here is the picture you were probably hoping for:

image

I have some additional work to do with this bug, so look for a release this weekend.

BTW, I am assuming you have a scanner configured to read UTF-8? Can you please verify the barcode in the image is decoding correctly. Thanks.

melnik10 commented 2 years ago

Thanks a lot. I will wait. I'll check your barcode.

metafloor commented 2 years ago

Forgot to post this. v3.0.5 is on npm/github with the updated code.