Post without Account — your post will be reviewed, and if appropriate, posted under Anonymous. You can also use this link to report any problems registering or logging in.

RT 98543 - miterlimit() return a value?

  • 2 Replies
  • 1538 Views
*

Offline Phil

  • Global Moderator
  • Sr. Member
  • *****
  • 437
    • View Profile
RT 98543 - miterlimit() return a value?
« October 21, 2016, 04:00:30 PM »
Subject:    miterlimit() return a value?
Date:    Tue, 02 Sep 2014 11:29:58 -0400
To:    bug-PDF-API2 [...] rt.cpan.org
From:    Phil M Perry

PDF::API2 v2.022   Perl 5.16.3  Windows 7   severity: Wishlist

In Content.pm, most methods that set some value also return whatever the current (updated) value is, regardless of whether the method call sets a new value. miterlimit()/meterlimit() is an exception to this. Certainly, once the user has called it to set a value, there is one available to return, although there may not be a clearly defined official default value (2 or 4?). If there is a default value, I would suggest that miterlimit() return the current value if given with no argument.

In all these cases, it may not be all that useful to return the newly set value, as the calling program presumably already knows this value (it just passed it to the method). What might be more useful would be to return the OLD setting, before it's overwritten by the NEW setting. Right now, code needs to call a method twice if it wants to preserve the old setting -- once without an argument to return the old setting, and then once with an argument to set the new setting. With the change, a single call could do it: OLD = method(NEW). Would this break any existing code?
#
Subject:    [rt.cpan.org #98543]
Date:    Sun, 24 Jan 2016 13:07:28 -0500
To:    bug-PDF-API2 [...] rt.cpan.org
From:    Phil M Perry

I understand that miterlimit() (formerly meterlimit()) is something of a special case, as it's not explicitly set by PDF::API2. According to the PDF 1.7 spec (PDF32000_2008.pdf), the PDF default value is 10.0. I don't know if that's different from earlier PDF versions. As for other settings, what does the community think about always returning the OLD setting whenever a setting is changed? Would this break any existing code? It would be nice to not have to make two calls: one to retrieve the old setting, and one to change the setting.

Note that not all settings are returned from calls -- only 21 of them (stream, poststream, font, fontset, fontsize, charspace, hscale (formerly hspace), wordspace, lead, rise, render, matrix, textmatrix, textlinematrix, fillcolor, strokecolor, translate, scale, skew, rotate, and apiistext. I don't know if there is any rhyme or reason behind this set, but perhaps a better starting point would be to ask why old settings are not returned for transform_rel, matrix_update, linewidth, linecap, linejoin, miterlimit, linedash, flatness, clip, shade, and textstate.
#
Wed Feb 17 15:48:20 2016 steve [...] deefs.net - Correspondence added

Most of the content calls return the content object, allowing calls to be chained.
#
Wed Feb 17 15:48:20 2016 The RT System itself - Status changed from 'new' to 'open'
#
Wed Feb 17 15:48:21 2016 steve [...] deefs.net - Status changed from 'open' to 'rejected'
#
Subject:    [rt.cpan.org #98543]
Date:    Fri, 19 Feb 2016 09:45:32 -0500
To:    bug-PDF-API2 [...] rt.cpan.org
From:    Phil M Perry

Quote
Most of the content calls return the content object, allowing calls to be chained.
Many don't. There seems to be no rhyme or reason to which calls return $self object, and which don't (of which some should be returning a setting value). I think there should be a conversation about what changes should be made to return an object or a setting value in a consistent manner, so that the user doesn't need to read the code to see what's going on and to find out if calls can be chained or settings are returned. It's not a high priority, but shouldn't be in the junk pile either.

*

Offline Phil

  • Global Moderator
  • Sr. Member
  • *****
  • 437
    • View Profile
Re: RT 98543 - miterlimit() return a value?
« Reply #1: November 15, 2016, 12:39:42 PM »
OK, the miter limit does appear to have a default value of 10.0. Therefore, I plan to return the current value, as do many other calls. This brings up a few issues that I'd like to get community feedback on:

1. Is there any point to returning the new value of a setting, rather than the old, when setting something? For example,
Code: [Select]
# char space defaults to 0
$cs = $content->charspace();
print "old char space = $cs\n";  # prints old char space = 0

$cs = $content->charspace(5);
print "new char space = $cs\n";  # prints new char space = 5
Um, yeah, I just set char space to 5. What's the point of telling me that?

Wouldn't it be more useful to always return the old setting, whether or not you're changing it? You could still read the old value:
Code: [Select]
# char space defaults to 0
$cs = $content->charspace();
print "old char space = $cs\n";  # prints old char space = 0
but you could combine retrieving the old value with setting the new one, in one call:
Code: [Select]
# char space defaults to 0
$cs = $content->charspace(5);    # set char space to 5
print "old char space = $cs\n";  # prints old char space = 0

Existing code most likely is making two separate calls, to get the old value and then to set the new one, and ignoring whatever is returned on the setting call (since you already know the value). Does anyone know if it is common practice to read back the newly set value by using the return value (char space of 5 in this example) and use that value for something? If not, existing code should not break.

2. In addition to miterlimit(), there are a number of other setting calls (linewidth, linecap, linejoin, linedash, flatness) which appear to not return either value (new or old). Is there any reason they shouldn't return a value? Will such a change break any properly written code? They will need default values set in new().

3. Why do some "setting" calls (transform, transform_rel, font, egstate) return $self, while others (translate, rotate, scale, skew) return nothing at all? The latter set could return their internal setting values, which are initialized in new() and set during calls. Are the former set intended to be chained, and the latter not?

4. Why do some drawing (graphics or text) calls return $self (move, close, endpath, line, hline, vline, poly, rect, rectxy, circle, ellipse, arc, curve, bogen, stroke, fill, fillstroke, clip, shade, image, formimage, font, compressFlate, textstart, textend), while others (pie, spline, distance, cr, nl) don't return anything? Are some intended to be chained together, and others not? At the least, it should be documented whether some can be chained. Even better, the calls should be consistent in their behavior.

5. There are a couple of calls which seem to have irregular behavior: matrix() returns $self if it's in graphics mode, while in text mode it returns the textmatrix. Is that known to cause any problems or confusion? textstate() returns an empty state hash if it's setting, while it returns a filled state hash if the state is being queried. Should it behave more like the other "setting" calls and return the "current" values in either case?

*

Offline Phil

  • Global Moderator
  • Sr. Member
  • *****
  • 437
    • View Profile
Re: RT 98543 - miterlimit() return a value?
« Reply #2: April 15, 2017, 03:03:56 PM »
With certain exceptions, all Content.pm public methods have been updated to make sure that $self (the content object) is explicitly returned when setting values, permitting chaining of calls. This is much more consistent behavior than the current implementation. These include:

translate, rotate, scale, skew, transform, transform_rel, linewidth, linecap, linejoin, miterlimit, linedash, flatness, egstate, move, close, endpath, line, hline, vline, poly, rect, rectxy, circle, ellipse, arc, pie, curve, spline, bogen, stroke, fill, fillstroke, clip, shade, image, formimage, font, distance, cr, nl, save, restore, compressFlate, textstart, textend

Many of these already had return $self;, but not all did.

Exceptions:
  • matrix returns the text transformation matrix in text mode, but $self in graphics mode.
  • textstate returns an empty hash if used to set value(s), and the full text state hash if used to query values.
  • textpos returns an array of the [horizontal, vertical] position that text will next be written to.
  • advancewidth returns the width (in points) needed to render the given text.
  • text (and the other text-output functions in Content::Text) returns the width used (in points) in rendering the text.

The following return $self when called to set a value, so that setting calls may be chained if desired. If they are called with empty argument lists, the indicated values are returned instead:
  • fillcolor returns an array of the last color specification given.
  • strokecolor returns an array of the last color specification given.
  • charspace returns the current character space setting.
  • wordspace returns the current word separation space setting.
  • hscale returns the current horizontal scaling.
  • lead returns the current text leading value.
  • render returns the current text rendering setting.
  • rise returns the current text baseline rise setting.
  • linewidth returns the current line width setting.
  • linecap returns the current line cap style setting.
  • linejoin returns the current line-end join style setting.
  • miterlimit returns the current line join miter limit ratio setting.
  • flatness returns the current curve flatness tolerance setting.

Special cases:
  • linedash returns $self when setting the dash pattern, and an array (consisting of an anonymous array of the dash-gap pattern, and the shift value) when querying. Since linedash() is a legitimate call to set a solid line, the call to query the dash pattern is linedash(-1).

This is implemented in the 3.003 release.

I decided that it was important to have the value-returning text functions (charspace, wordspace, hspace, lead, render, rise) behave in a similar manner to the value-returning graphics functions. Therefore, these functions have been changed to only return their current value when no argument is given, and to return $self when they are used to set the value. The (new) value is no longer returned when it is set, but that is not expected to be a major use of the functions. The same holds for fillcolor and strokecolor — they no longer return the current setting when setting the color (only when querying it with an empty argument list).

There does not appear to be a consistent way to synchronize settings changes between ExtGState and Content. Line width, line cap style, line join style, miter limit, dash pattern, and flatness can be set in both Content and ExtGState, but since they affect different contexts, there is no apparent way to transfer a setting from Content to ExtGState or vice-versa. Anyway, be careful about mixing ways of making settings changes (Content calls and ExtGState calls), and value queries, as the results may be unpredictable.

Keep in mind the way that graphical and text operations are output to PDF, and how PDF in turn processes these streams. Anything that returns the "graphics current state" (including text) may not quite match up with what PDF is actually using at that moment, due to the exact order of operations.

Extensively edited due to major code changes
« Last Edit: April 17, 2017, 10:50:41 PM by Phil »