[Drawkit] DrawKit b6 now available
Allan Daly
allandaly at me.com
Wed Jul 15 18:39:16 PDT 2009
Wow, Graham. This is an impressive list of changes and updates. Thanks
for posting this.
It compiles fine and seems to work well in my app out of the box with
no changes needed.
-Allan
On Jul 14, 2009, at 7:47 PM, Graham Cox wrote:
> Finally, I got around to updating the site with the latest source.
>
> http://apptree.net/drawkitmain.htm
>
> Note that this version has quite a large number of changes (due to
> the long time between updates - sorry about that) but by and large
> should require very few changes to your client code. Do let me know
> if you have any problems either with the downloads or with building.
>
> Particular areas that you'll need to test are text and object
> metadata - they are the parts that have changed most significantly.
>
> The release notes are copied below.
>
> --Graham
>
> Release 1.0 beta 6
> July 15th, 2009
>
> 1. Objects that can be passed to a renderer must now implement the
> DKRenderable formal protocol. DKDrawableObject does, so no change is
> required. However it allows other kinds of objects to be passed to a
> style/renderer for special purposes if necessary while reducing the
> likelihood of introducing bugs by doing so. The previous informal
> protocol for this purpose is deprecated. The protocol is defined in
> DKRasterizerProtocol.h
>
> 2. Style scripting support, which has been deprecated for several
> releases now, has gone.
>
> 3. Additional objects storage class, DKBSPDirectObjectStorage,
> added. This uses a similar algorithm to DKBSPObjectStorage, but
> instead of indexing it stores the objects directly. This seems to
> yield significant speed advantages, though more profiling is needed
> to quantify this. The storage itself is not archived as part of the
> drawing - only its objects are, and the currently set preferred
> class for the storage is honoured on dearchiving. Files saved with
> Beta 5 did archive the storage and they will be automatically
> converted when read. Re-saving the file will update to the newer
> approach.
>
> 4. Code that draws and iterates over drawables is gradually being
> updated to take advantage of the benefits of the storage model. In
> most cases this means that fewer objects need to be iterated over
> for many operations, yielding noticable performance benefits. In
> addition, time-critical code that uses NSEnumerator is replaced by
> the much faster CFArrayApplyFunction methodology. This works on 10.4
> and earlier, unlike ObjC-2.0 fast enumeration. Upshot: Teh Snappy™.
> Maybe.
>
> 5. Locked layers are no longer auto-activated by default. This
> reflects the typical usage patterns for locked layers as background
> content or for tracing.
>
> 6. DKLayerGroup now correctly propagates hit-testing recursively
> down through a layer hierarchy.
>
> 7. Select/Edit tool now implements an alternative dragging
> methodology in an effort to boost performance substantially when
> dragging a large number of objects at once. This method uses a
> single drag image as a proxy for the objects being dragged, then
> repositions the real objects on mouse up. This approach can be
> turned off (thus using the old method), turned on for all objects or
> used when a certain threshold object count is exceeded. This is done
> by calling [DKSelectAndEditTool setDragProxyThreshold:] with values
> of 0, 1 and the required threshold respectively. The default in this
> release is to use the alternative method for 50 or more objects. The
> main downside of this approach is that the interleaving of the
> dragged objects with non-dragged objects during the drag cannot be
> preserved. The Z-order is maintained and restored at the end of the
> drag. In practice the performance benefit will probably outweigh
> this minor inconvenience. Currently the drag image will noticeably
> pixellate at higher zooms also.
>
> 8. Select/Edit tool now treats locked objects slightly differently.
> A drag that starts in a locked object selects it as usual, but now
> continues in the selection rect dragging mode. This gives more
> useful behaviour: objects overlaid on some locked background object
> can now be drag-selected as normal even if the drag started in the
> background object.
>
> 9. DKLayerGroup and DKViewController add methods to permit the
> implementation of a "Hide Others" and "Show All" command for
> operating on layers if desired.
>
> 10. Added some additional properties to DKHatching: line roughness
> and "wobblyness" which together can be used to create some
> additional effects.
>
> 11. Bugfix: objects resulting from combinatorial operations now
> preserve any attached user data from the source object.
>
> 12. Metadata keys in both DKLayer and DKDrawableObject are now case-
> insensitive. Existing files will have their keys converted if
> necessary, at the possible risk of data loss if you have keys that
> differ only in case. The case insensitivity is achieved by always
> converting all key strings to lowercase. If you set a key in the
> user info dictionary directly, rather than using the metadata
> methods, you need to ensure this otherwise your data won't be
> findable.
>
> 13. Drawable Objects now support the concept of ghosting, which
> draws the object using a light grey thin outline rather than its
> attached style. Otherwise the object behaves as a normal visible
> object. Ghosting is a good alternative to hiding objects in many
> applications. DKObjectDrawingLayer supports high-level commands for
> ghosting and unghosting items in the selection. Some renderers, such
> as DKTextAdornment, are ghosting aware, though most don't need to be
> as ghosting typically bypasses the style altogether. The grey
> ghosting colour is settable as a global preference using +
> [DKDrawableObject setGhostColour:]; You can also override an
> object's -drawGhostedContent method to customise the ghosted
> appearance.
>
> 14. Bugfix: Layer Bring Forward/Bring To Front/Send Backward/Send
> To Back commands now operate without ambiguity within their
> immediate containing group only (which for the case of a flat layer
> list is the drawing, as before). The earlier implementation was
> buggy when additional layer groups were present.
>
> 15. Intersection operation now preserves the style and metadata from
> the lower object rather than the upper. This better reflects real-
> world usage of this operation to extract a shape from a larger one
> using an overlaid "cookie cutter".
>
> 16. Bugfix: -hexString in NSColor category makes a more accurate job
> of rounding the colour component values when determining the hex
> value. This prevents light greys for example incorrectly coming out
> as white.
>
> 17. "Break Apart" operation now available for shapes without
> converting to a path first. Metadata is preserved as is the true
> class of the object.
>
> 18. DKTextShape and DKTextPath modified in behaviour such that
> deliberate changes to the text made by the user "stick" properly
> when saving the file. The change involves mutating the existing
> style, if it's a registered style, into an identical one but lacking
> text attributes. This allows the text to be set both by the user
> directly, and also by applying a style having text attributes, but
> without any user-made changes getting reverted when a file
> containing such objects is reloaded. A memory leak and a KVO error
> bug was also fixed in the DKTextShape object.
>
> 19. Text on a path now lays out the full attributed string exactly
> as it would be drawn by the standard text system, so it is possible
> to vary attributes such as font, underlining, superscripting, colour
> and shadow within the string.
>
> 20. DKDrawableObject now supports a global table used to map classes
> when performing interconversions from one type of object to another
> (e.g. path -> shape). By customising this table, your app can
> substitute a subclass to be used when performing an interconversion
> that normally would make an object of the base class. All
> conversions done by DK now go through this table, but by default no
> substitution is performed (and in fact the table is nil).
>
> 21. The NSBezierPath+Geometry category has been split into a new
> category NSBezierPath+Text which contains all the text-on-path and
> text-wrap-in-shape methods.
>
> 22. DKTextPath now has a contextual menu that mirrors the one used
> by DKTextShape. Both have been cleaned up.
>
> 23. DKDrawablePath creation allows modal creation loops to be
> interrupted (ended) by hitting any key on the keyboard as well as
> the previously supported methods. This makes it easier to "get out
> of" a modal loop if you were not expecting to be in one. Also some
> additional feedback via the floating info window was added for
> several of the path loops that previously didn't have anything.
>
> 24. Text on a path now supports underline and strikethrough
> attributes. Currently these are based on the metrics returned by
> NSFont and some tweaking - the positioning differs very slightly
> from text laid out by the system and the discrepancy varies with the
> font. It's unclear why the system is not using the metrics it is
> given. Currently, the NSUnderlineByWordMask flag is not supported.
>
> 25. Text on a path now renders any text shadow the same way that
> NSTextView etc do. This is to give consistency beyween text blocks
> laid out by the system and text on paths. However this way of
> drawing shadows is a bit dumb - it changes according to the view
> zoom scale. You can use the earlier behaviour for text on a path by
> setting DK_TEXT_SHADOW_COMPATIBLE to 1 and recompiling. There's no
> way to change how the system draws text shadows though.
>
> 26. Locked path objects no longer show the control knobs and bars
> since they can't be moved anyway. On-path knobs are shown as before
> using the locked style. This reduces visual clutter.
>
> 27. DKGuideLayer now manages its cursor to provide useful feedback
> when dragging, deleting and placing. When creating a new guide by
> dragging from a ruler, the guide layer is now made active which
> brings its cursors into play. While dragging a guide, the up/down or
> left/right curosr is shown. When not dragging, the open hand cursor
> is shown. When a guide is dragged into the "delete" zone (the
> margins, typically), the disappearing item cursor is shown and when
> a guide is deleted the 'poof' animation is shown. If locked the
> layer shows the arrow. Guide layers also now maintain the deletion
> area independently of the drawing's interior. By default this is set
> to be the same as the drawing's interior but you can set it to some
> other rect if you want (the most likely alternative is the entire
> drawing).
>
> 28. DKDrawing no longer calls DKStyleRegistry's loadDefaults from
> its own loadDefaults. This was assuming too much about what an app's
> needs are here. If you are relying on this, you need to call the
> registry's loadDefaults yourself from the application delegate's -
> applicationDidFinishLaunching: method. The same applies to the call
> to the registry's saveDefaults.
>
> 29. Layers can get directly notified when they, or a group
> containing them, was added to the root drawing. The intention is to
> perform additional setup with knowledge of the drawing such as its
> size. The method is -wasAddedToDrawing:
>
> 30. The persistence mechanism for DKDrawingTool made more general.
> Instead of -saveDefaults assuming that we are interested in the
> style, we leave it up to the tool object, using the new methods -
> persistentData and -shouldLoadPersistentData: DKObjectCreationTool
> now handles the style as before using this mechanism, but other tool
> classes can do something different. The change is fully backward
> compatible. In addition DKObjectCreationTool now correctly attempts
> to remerge the style with the registry as it should to ensure that
> two copies of the same style don't end up in the system (and then
> transferred to drawings). While a bug that was leaking into saved
> documents, it's self-correcting in that such documents will fix
> themselves up when they do their own remerge on being opened.
>
> 31. Removed misguided attempt at caching point hit-testing on
> drawables - led to problems with hit-testing reliability.
>
> 32. DKStroke drops the unimplemented properties pathScaleFactor and
> strokePosition, but gains lateralOffset, which is a better and more
> general solution (and one that is actually implemented).
>
> 33. DKDrawing now allows a delegate. Currently the only delegate
> methods posible are to hook into before and after drawing the content.
>
> 34. Ruler visibility is now persistent - new instances of
> DKDrawingView initially set the rulers according to the most recent
> state seen. If never set, the default is now hidden, not shown.
>
> 35. [NSBezierPath bezierPathByInterpolatingPath:] is now functional.
>
> 36. GCZoomView now implements all of the scrollwheel control flags
> as class methods, so they are applied to all instances in a given
> application. This makes more sense and allows them to be easily
> linked with user defaults. DKDrawingView defines some standard user
> defaults keys for enabling and setting the sense of scroll wheel
> operations. These are loaded as needed but never set - your app can
> expose these settings in its preferences if it wants to.
>
> 37. Menu items for "Hide/Show Grid" and "Hide/Show Guides" now use
> the actual set name of the layers in question, rather than assuming
> "Grid" and "Guides".
>
> 38. Default layer cache settings for DKObjectOwnerLayer are now
> settable. Saved cache settings are ignored. The default is no
> caching. Note that in real-world testing, using a PDF-based cache
> was found to be often slower than drawing the objects directly,
> especially with partitioned storage. CGLayer cacheing is still
> faster, but suffers from pixellation effects.
>
> 39. There is now a formal protocol - DKDrawableContainer - that
> defines the methods a container must implement if it claims to "own"
> or "contain" any drawable. Existing objects that were acting as
> containers, namely DKObjectOwnerLayer and DKShapeGroup, now formally
> adopt this protocol. There is no functional difference but the
> formal protocol both ensures correctness for containers and makes
> clear what methods a container needs to support.
>
> 40. Archiving of DKImageShape and interaction with image data
> manager reworked to give a much more robust and straightforward
> implementation. As before, wherever possible original image data is
> stored in a document archive and used to recreate image shapes as
> needed. Only one copy of the data is saved no matter how many image
> shapes share it, keeping file sizes down, and since the images are
> recreated from the original data when dearchived, quality is kept as
> high as possible. The difference now is that the image shape also
> retains a reference to the data and makes sure that this gets copied
> to new image data managers as they are needed. It can also create
> its own image even if no manager is available, and will update it
> when the opportunity arises. The result is far less chance of an
> image shape being unable to instantiate itself even when archived in
> a non-standard way or from within a custom container. Note that
> older archives will remain operational and will update to the
> revised archive scheme if saved.
>
> 41. Hit-testing of very narrow or offset paths made much more
> reliable using a temporary stroke attribute that isn't visible to
> the user. Allows tools such as insert/remove path point to work even
> on offset paths, or paths with very thin strokes that can be hard to
> hit. Additionally, hatches are treated as 'solid' for the purpose of
> hit-testing
>
> 42. New algorithm for generating the offset or parallel path, more
> accurate, also allows for differing treatments of corners (mitre,
> round or bevel). The use of paralleloidPathWithOffset2 now calls
> this new code using the path's current line join style.
>
> 43. An enhancement to the message forwarding performed by
> DKObjectDrawingLayer allows multiple selections to be handled
> automatically where the actual action is implemented by the object,
> rather than the layer. Previously, forwarding from the layer to an
> object was only done if exactly one selected object could respond to
> the message. This meant that any actions pertaining to a set of
> selected objects had to be implemented strictly by the layer. For
> certain operations, such as conversions, this was inconvenient, and
> disallowed such operations t be performed on more than one object at
> a time. Now this can be handled for multiple selected objects
> automatically, even when the action is handled only by the object.
> For backward compatibility, this feature is turned off by default,
> and is not saved in an archive. It can be enabled using -
> setMultipleSelectionAutoForwarding:YES. The layer will temporarily
> buffer selection changes when invoking multiple commands in this way
> such that the user will "see" the same selection behaviour as if the
> message had been handled by the layer itself.
>
> 44. The DK project now includes a unit test target. Over time more
> tests will be added; right now only a test for the BSP storage sub-
> system is included. However, the test is fairly thorough and as a
> result a couple of subtle bugs were found and corrected in the
> tested classes.
>
> 45. DKDrawkitInspectorBase was changed so that it passes nil to -
> redisplayContentForSelection: when the document resigned main.
> Previously it passed the "current" selection but this is stale when
> a document is closing.
>
> 46. The select/edit tool now posts a mouse up event if appropriate
> when an object is dragged out of a drawing. This is necessary
> because the normal drag handling swallows the mouse up, but without
> one the tool controller can be left in an unbalanced state. This
> fixes the issue of the undo manager going on strike following this
> kind of drag.
>
> 47. DKShapeGroup can now optionally clip its contents to the group's
> path. By default this is off, but easily enabled using a new
> contextual menu item. When enabled, the selection highlight reveals
> the path.
>
> 48. When interactively creating bezier paths and irregular polygons,
> the delete key can now be used to "back up" by one element (in other
> words, deleting the current point being positioned).
>
> 49. DKDrawingDocument factors the creation of a print drawing view
> into an overridable method allowing easy customisation of the print
> view.
>
> 50. DKStyleRegistry no longer enables style notifications by
> default. A new method, +setStyleNotificationsEnabled:, allows you to
> turn this on or off, but it's now up to your app to do this. It's
> only needed if you're using the built-in menu handling, otherwise
> leaving it off speeds up various operations. Also, DKCategoryManager
> uses a different approach in -replaceContentsWithData: which greatly
> improves its speed.
>
> 51. Double-click detection changed to be slightly earlier so that it
> is invoked even when a handle or other partcode of an object is hit.
> Previously it was only called when the "entire object" partcode was
> hit, so looking for particular partcodes in the double-click method
> didn't work.
>
> 52. A new vertical alignment constant for text-on-a-path
> automatically centres the text on the path based on the cap height
> of the font the text is drawn in. This visually centres the text on
> the path rather than placing its baseline there. DKTextAdornment
> implements this for text on path layouts which is therefore
> inherited by DKTextPath and DKTextShape.
>
> 53. DKStyle has some additional class methods for pasteboard
> operations: +canInitWithPasteboard: and +stylePasteboardTypes
>
> 54. DKRasterizers now broadcast notifications before and after every
> property change, so that non-style clients can easily get notified
> when any property of the reasterizer changes. This is used by
> DKTextPath, DKTextShape for example, which uses an internal
> adornment without a style.
>
> 55. DKTextADornment now uses a much more versatile method for
> handling substitution of metadata values into the text stream. Now,
> the adornment uses a DKTextSubstitutor (new object) to store the
> "master" string which replaces the earlier label. The user is able
> to simply embed metadata keys into this string by using a special
> delimiter (%% in the default implementation). When the string is
> displayed the metadata value is substituted for the embedded key.
> The property -identifier is deprecated and older adornment objects
> automatically convert themselves to the new method in a manner that
> preserves their original layout. DKTextShape and DKTextPath have
> been modified slightly so that when editing the text, it is the
> master string that is passed to the editor. Existing methods of
> DKTextAdornment automatically deal with the new design - for example
> -setLabel: passes the text as the master string. The main advantages
> of this change are that a) values can be substitued anywhere within
> the text label, not just appended, and b) that any number of
> embedded keys can be used at once. Note that the ablity to
> introspect object properties by keypath remains - just prefix the
> key with a '$' as before, e.g. %%$object.key.path
>
> 56. DKTextAdornment now supports a "knockout" text effect which
> places a filled and/or stroked outline of the text behind the glyphs.
>
> 57. DKTextAdornment now supports capitalization operations when
> displaying text.
>
> 58. DKTextADornment now adds a number of its special effects
> properties as attributes to the normal -textAttributes dictionary,
> but using keys which are unique to DK, so they can be placed
> alongside standard Cocoa text attributes. These attributes include
> the knockout parameters, the vertical alignment parameters and the
> capitalization settings. These attributes are thus cut-and-pastable
> as part of a style between objects that are aware of them including
> DKTextShape and DKTextPath.
>
> 59. DKShapeGroup now checks an object's validity when ungrouping. If
> the ungrouping causes the object to become invalid, it is discarded
> rather than be allowed to cause problems. An object is defined to be
> invalid if it contributes nothing visible to the drawing, so this
> has no effect on what you see but allows groups to work more
> robustly. To support this, DKDrawableShape now disallows an invalid
> path when ungrouping, and deliberately forces itself
> into an invalid state if this occurs. This was a rare occurrence and
> won't affect the average user.
>
> 60. DKDrawing adds +dearchivingHelper and +setDearchivingHelper: to
> augment or replace the standard dearchiving delegate. This allows
> applications using DK to deal with obsolete or replacement classes
> of their own when dearchiving a drawing. In general it's a good idea
> to subclass DKUnarchivingHelper if you plan to do this, since that
> already deals with earlier Drawkit object evolution.
>
> 61. DKCategoryManager also now supports a dearchiving helper.
> DKUnarchivingHelper has moved to its own source file from DKDrawing,
> and the internal -changeCount state it was holding has been removed
> (it was not used anywhere) so the same helper instance can be reused
> in multiple places if required.
>
> 62. Hit-testing of text objects much improved in terms of accuracy
> and performance. When hit-testing, the real text isn't drawn but
> "greeked" text is instead, which doesn't mind about the heavy
> scaling and bitmap destination context used, and draws faster. The
> actual greeking effect is implemented by DKGreekingLayoutManager, a
> new class, used as necessary by DKTextAdornment. Greeked text can
> also be drawn by DKTextAdornment in normal use also, but since
> there's very little need for this it currently isn't a persistent or
> observable property.
>
> 63. DKDrawableObject now explicitly declares the userInfo property
> as a mutable dictionary. Other parts of DK were already assuming
> this to be the case. If you are storing any other object type here,
> you need to revise your code to store the object in the userInfo
> dictionary using a suitable key. The metadata API that built on this
> has been revised so that the metadata is stored as an additional
> dictionary within the userInfo dicitonary, rather than as individual
> items. Code may need to be revised that was accessing the userInfo
> directly as the metadata dictionary - a new method, -metadata,
> returns the appropriate dictionary. This change permits more
> flexibility when extending a class without compromising the metadata.
>
> 64. DKDrawableObject can now accept a delegate object. DK doesn't
> use it except to send it messages if it responds to the
> DKDrawableObjectDelegate informal protocol. This is basically
> reserved for the use of applications.
>
> 65. Memory leak fixed in DKDrawing export methods.
>
> 66. Bugs fixed with computational geometry on paths. Note that the
> optional OMNI methods have been found to exhibit an accumulative
> rounding error which may make them unsuitable when dealing with long
> paths. Thus in this version they are disabled by default, and the
> slightly slower, but more accurate DK methods are used.
>
> 67. When copying native objects on the pasteboard, an info object is
> also stored which can be used to get information about the objects
> on the clipboard without having to dearchive them. The data type is
> kDKDrawableObjectInfoPasteboardType. Currently the only info
> provided is a count of the objects and a breakdown of the classes
> and the numbers of each. The use of a special helper info object
> allows this to be expanded simply in the future as needed. Since the
> count is frequently used to update menus, etc, this is a lot more
> efficient.
>
> 68. When a DKDrawingView automatically creates the drawing "back
> end", it now also loads the DKDrawing defaults, which puts in place
> the standard registered tools. This is an added convenience further
> reducing the necessary setup for a working DK installation. Even
> with no UI at all, tool keyboard equivalents function for selecting
> standard tools.
>
> 69. "Smart" repeated pasting and duplication of objects now works as
> it was always meant to, by 'predicting' the appropriate offset for
> the paste.
>
> 70. A drawing's image manager is no longer archived. It's not
> necessary because each object using image data archives the data,
> and archiving ensures only a single copy of the same data is placed
> in the file. The image manager is still needed to handle multiple
> copies of the same image, but it is noe rebuilt on the fly. As an
> added bugfix, this change prevents data from images that have been
> deleted altogether from remaining in the image manager and
> subsequently getting archived, which was just adding unused content
> to the file unnecessarily.
>
> 71. Clean-up of a number of memory leaks and incorrectly named
> methods based on Clang static analyser (thanks to Brad for doing
> this). Some methods were renamed as a result so they fall into line
> with proper conventions for memory management - i.e. those including
> 'create' or 'new' return retained objects or else renamed so that
> they do not imply this. Some minor code revision of apps using these
> methods may be needed.
>
> _______________________________________________
> Drawkit mailing list
> Drawkit at lists.apptree.net
> http://lists.apptree.net/listinfo.cgi/drawkit-apptree.net
More information about the Drawkit
mailing list