10.3 Line Styles

  • 10.3.1 Line Style Protocol and Line Style Suboptions
  • 10.3.2 Contrasting Dash Patterns
  • A line or other path is a one-dimensional object. However in order to be visible, the rendering of a line must occupy some non-zero area on the display hardware. A line style represents the advice of CLIM to the rendering substrate on how to perform the rendering. [annotate]

    [line style, Concept← A Glossary]
    [line style, Concept← A Glossary]
    [line style, Concept← 10.3 Line Styles, line-style-p]
    [line style, Concept← 10.1 Medium Components, (setf medium-line-style)]

    line-style   [Protocol Class]
              

    The protocol class for line styles. If you want to create a new class that behaves like a line style, it should be a subclass of line-style. All instantiable subclasses of line-style must obey the line style protocol. [annotate]

    [annotate]

    line-style-p  object [Protocol Predicate]
              

    Returns true if object is a line style, otherwise returns false. [annotate]

    [annotate]

    standard-line-style   [Class]
              

    An instantiable class that implements line styles. A subclass of line-style. This is the class that make-line-style instantiates. Members of this class are immutable. [annotate]

    [annotate]

    make-line-style  &key unit thickness joint-shape cap-shape dashes [Function]
              

    Returns an object of class standard-line-style with the supplied characteristics. The arguments and their default values are described in Section 10.3.1. [annotate]

    [annotate]

    10.3.1 Line Style Protocol and Line Style Suboptions

    Each of these suboptions has a corresponding reader that can be used to extract a particular component from a line style. The generic functions decribed below comprise the line style protocol; all subclasses of line-style must implement methods for these generic functions. [annotate]

    :line-unit   [Option]
    line-style-unit  line-style [Generic Function]
              

    Gives the unit used for measuring line thickness and dash pattern length for the line style. Possible values are :normal, :point, or :coordinate. The meaning of these options is: [annotate]

    • :normal---thicknesses and lengths are given in a relative measure in terms of the usual or "normal" line thickness. The normal line thickness is the thickness of the "comfortably visible thin line", In some window systems, the phrase "thinnest visible line" is used. This is not appropriate for CLIM, which intends to be device independent. (For instance, the thinnest visible line on a 400 d.p.i. laser printer is a function of the user's viewing distance from the paper.) Another attribute of a "normal" line is that its thickness should approximately match the stroke thickness of "normal" text, where again the exact measurements are the province of the rendering engine, not of CLIM. which is a property of the underlying rendering substrate. This is the default. [annotate]
      Note: How to convert this unit to :COORDINATE? It is important for device-independent output recording. [edit]-- Alexey Dejneka 2002-11-21 04:29Z
       
      Note: Normal means, that thickness is used as is, without any modifications. See comment below regarding how coordinate is used. [edit]-- Daniel Kochmanski 2018-08-23 10:23Z
       
    • :point---thicknesses and lengths are given in an absolute measure in terms of printer's points (approximately 1/72 of an inch). This measure was chosen so that CLIM implementors who interface CLIM to an underlying rendering engine (the window system) may legitimately choose to make it render as 1 pixel on current (1990) display devices. [annotate]
    • :coordinate---this means that the same units should be used for line thickness as are used for coordinates. In this case, the line thickness is scaled by the medium's current transformation, whereas :normal and :point do not scale the line thickness. [annotate]
      Note:

      We are transforming size, not a position. Therefore thickness 2 should be transformed as [dx;dy] = [0;2] and the distance measured again (thanks to that we take into account i.e rotations, scaling, skewing and it works with any transformation):

      (multiple-value-call #'(lambda (x y) (sqrt (+ (expt x 2) (expt y 2)))) 
         (clim:transform-distance medium-transformation 0 2))

      Although more complicated approach could be taken (namely taking thickness 2 as a distance according to line orientation, i.e [dx;dy] = [sqrt(2);sqrt(2)] for a line skewed by pi/4 [45°]) I think that the first approach is fine and has an undeniable advantage that it will have a uniform result for all lines with same thickness and unit (despite different orientations) and other curves if we decide, that we want to support thickness in (say) Bezier curves.

      [edit]-- Daniel Kochmanski 2018-08-23 09:21Z
       
      Note:

      Although it says "the thickness is scaled", it rather should be that the shape of the resulting image is to be scaled. Or the "pen" or "brush" used along the path.

      For example, you can use

      (draw-line* medium 0 0 0 0 
                         :line-thickness 50
                         :line-style-unit :coordinate
                         :line-cap-shape :round)

      to get a circle of diameter 50 with regard to whatever transformation happens to be set up on the medium.

      You would expect that when you say

      (with-scaling (medium 2 1)
        (draw-line* medium 0 0 0 0 
                           :line-thickness 50
                           :line-style-unit :coordinate
                           :line-cap-shape :round))

      you get an ellispe.

      [edit]-- Gilbert Baumann 2022-06-28 17:53Z
       

    [annotate]

    Note: That makes perfect sense, thank you. [edit]-- Daniel Kochmanski 2024-03-25 09:41Z
     

    :line-thickness   [Option]
    line-style-thickness  line-style [Generic Function]
              

    The thickness, in the units indicated by line-style-unit, of the lines or arcs drawn by a drawing function. The thickness must be a real number. The default is 1, which combined with the default unit of :normal, means that the default line drawn is the "comfortably visible thin line". [annotate]

    [annotate]

    :line-joint-shape   [Option]
    line-style-joint-shape  line-style [Generic Function]
              

    Specifies the shape of joints between segments of unfilled figures. The possible shapes are :miter, :bevel, :round, and :none; the default is :miter. Note that the joint shape is implemented by the host window system, so not all platforms will necessarily fully support it. [annotate]


    Figure 10.1: Line joint shapes.

    [annotate]

    :line-cap-shape   [Option]
    line-style-cap-shape  line-style [Generic Function]
              

    Specifies the shape for the ends of lines and arcs drawn by a drawing function, one of :butt, :square, :round, or :no-end-point; the default is :butt. Note that the cap shape is implemented by the host window system, so not all platforms will necessarily fully support it. [annotate]


    Figure 10.2: Line cap shapes.

    [annotate]

    :line-dashes   [Option]
    line-style-dashes  line-style [Generic Function]
              

    Controls whether lines or arcs are drawn as dashed figures, and if so, what the dashing pattern is. Possible values are: [annotate]

    • nil---lines are drawn solid, with no dashing. This is the default. [annotate]
    • t---lines are drawn dashed, with a dash pattern that is unspecified and may vary with the rendering engine. This allows the underlying display substrate to provide a default dashed line for the programmer whose only requirement is to draw a line that is visually distinguishable from the default solid line. [annotate]
    • A sequence---specifies a sequence, usually a vector, controlling the dash pattern of a drawing function. It is an error if the sequence does not contain an even number of elements. The elements of the sequence are lengths (as real numbers) of individual components of the dashed line or arc. The odd elements specify the length of inked components, the even elements specify the gaps. All lengths are expressed in the units described by line-style-unit. [annotate]

    (See also make-contrasting-dash-patterns.) [annotate]

    [annotate]

    10.3.2 Contrasting Dash Patterns

    make-contrasting-dash-patterns  n &optional k [Function]
              

    If k is not supplied, this returns a vector of n dash patterns with recognizably different appearance. Elements of the vector are guaranteed to be acceptable values for :dashes, and do not include nil, but their class is not otherwise specified. The vector is a fresh object that may be modified. [annotate]

    If k is supplied, it must be an integer between 0 and n - 1 (inclusive), in which case make-contrasting-dash-patterns returns the k'th dash-pattern rather than returning a vector of dash-patterns. [annotate]

    If the implementation does not have n different contrasting dash patterns, make-contrasting-dash-patterns signals an error. This will not happen unless n is greater than eight. [annotate]

    [annotate]

    contrasting-dash-pattern-limit  port [Generic Function]
              

    Returns the number of contrasting dash patterns that can be rendered on any medium on the port port. Implementations are encouraged to make this as large as possible, but it must be at least 8. All classes that obey the port protocol must implement a method for this generic function. [annotate]

    [annotate]