|
From: Maurice L. <mj...@ga...> - 2002-09-20 06:41:42
|
In writing the new store-strings-as-strings-in-plmeta capability, I came
across some code in plmtex() that has been giving me fits. Not only does it
have precision problems, but it's inconsistently written, so that under some
circumstances a quantity is rounded, and under others, it's truncated.
The big picture: to really get the string store capability (in plmeta)
correct, I need to write it out at the normalized device coordinate level,
i.e. (floating point) bounds from 0 -> 1. Only at the render level is
it converted to physical (mm) and then device (pixel) coordinates. So
my task was to generalize the monster if-else in plmtex() as well as the
code in plptex, plxytx, plztx and insert a new layer just above plstr()
that does all its stuff in normalized device coords.
Aside: this is a good prototype for things to come, since we eventually
want to do more things at the normalized device coordinate level.
So it looks like fixing plmtex() is going to involve some off-by-one pixel
changes to the output, by what I'm seeing in the ps output. Just a heads-up
b/c I know others (especially Alan) will be affected by this change. I'll try
to time it with another change I have planned that may affect low order bit
precision as well.
A look at the if-else in plmtex() reveals:
if (plP_stsearch(side, 'b')) {
vert = 0;
xdv = plsc->vpdxmi + (plsc->vpdxma - plsc->vpdxmi) * pos;
ymm = plP_dcmmy(plsc->vpdymi) - disp * chrht;
x = plP_dcpcx(xdv);
^^^^^^^^^^^^^^^ rounded to PLINT
refx = x - shift * plsc->xpmm;
^^^^^^^^^^^^^^^^^^^ precision problem! truncated, not rounded
y = refy = plP_mmpcy(ymm);
}
else if (plP_stsearch(side, 't')) {
vert = 0;
xdv = plsc->vpdxmi + (plsc->vpdxma - plsc->vpdxmi) * pos;
ymm = plP_dcmmy(plsc->vpdyma) + disp * chrht;
x = plP_dcpcx(xdv);
^^^^^^^^^^^^^^^ rounded to PLINT
refx = x - shift * plsc->xpmm;
^^^^^^^^^^^^^^^^^^^ precision problem! truncated & added
y = refy = plP_mmpcy(ymm);
}
else if (plP_stindex(side, "LV") != -1 || plP_stindex(side, "lv") != -1) {
vert = 0;
xmm = plP_dcmmx(plsc->vpdxmi) - disp * chrht;
ydv = plsc->vpdymi + (plsc->vpdyma - plsc->vpdymi) * pos;
x = plP_mmpcx(xmm);
^^^^^^^^^^^^^^^ rounded to PLINT
refx = x - plP_mmpcx(shift);
^^^^^^^^^^^^^^^^ rounded! Both inconsistent with the
above code AND a precision problem! Because you should add first, then round,
rather than the other way around.
y = refy = plP_dcpcy(ydv);
}
else if (plP_stindex(side, "RV") != -1 || plP_stindex(side, "rv") != -1) {
vert = 0;
xmm = plP_dcmmx(plsc->vpdxma) + disp * chrht;
ydv = plsc->vpdymi + (plsc->vpdyma - plsc->vpdymi) * pos;
x = plP_mmpcx(xmm);
^^^^^^^^^^^^^^ ditto
refx = x - plP_mmpcx(shift);
^^^^^^^^^^^^^^^^^ ditto
y = refy = plP_dcpcy(ydv);
}
else if (plP_stsearch(side, 'l')) {
vert = 1;
xmm = plP_dcmmx(plsc->vpdxmi) - disp * chrht;
ydv = plsc->vpdymi + (plsc->vpdyma - plsc->vpdymi) * pos;
x = refx = plP_mmpcx(xmm);
y = plP_dcpcy(ydv);
^^^^^^^^^^^^^^ rounded
refy = y - shift * plsc->ypmm;
^^^^^^^^^^^^^^^^^^^ truncated & added
}
else if (plP_stsearch(side, 'r')) {
vert = 1;
xmm = plP_dcmmx(plsc->vpdxma) + disp * chrht;
ydv = plsc->vpdymi + (plsc->vpdyma - plsc->vpdymi) * pos;
x = refx = plP_mmpcx(xmm);
y = plP_dcpcy(ydv);
^^^^^^^^^^^^^^ rounded
refy = y - shift * plsc->ypmm;
^^^^^^^^^^^^^^^^^^^ truncated & added
}
The correct way should be to add the offset (in the proper coordinate system),
then round.
--
Maurice LeBrun mj...@ga...
Research Organization for Information Science and Technology of Japan (RIST)
|