Issue 105655 - printing files with FontWork very slowwww
Summary: printing files with FontWork very slowwww
Status: CLOSED FIXED
Alias: None
Product: Draw
Classification: Application
Component: code (show other issues)
Version: OOo 3.1.1
Hardware: Unknown Windows XP
: P3 Trivial (vote)
Target Milestone: OOo 3.3
Assignee: wolframgarten
QA Contact: issues@graphics
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-10-06 15:55 UTC by cno
Modified: 2010-01-19 12:18 UTC (History)
5 users (show)

See Also:
Issue Type: DEFECT
Latest Confirmation in: ---
Developer Difficulty: ---


Attachments
file with 32 fontwork objects (27.31 KB, application/vnd.oasis.opendocument.graphics)
2009-10-06 15:57 UTC, cno
no flags Details
file with one fontwork objects (138.13 KB, application/vnd.oasis.opendocument.text)
2009-10-06 15:57 UTC, cno
no flags Details

Note You need to log in before you can comment on or make changes to this issue.
Description cno 2009-10-06 15:55:19 UTC
Report from a Dutch user:
  - file with fontwork objects (32 ...) takes about a quarter of an hour to get
it printed, ate 100% of one of the four cores, and made a printjob of 15071 KB.

Report from me:
  - file with fontwork takes minutes to print

Both files will be attached
Comment 1 cno 2009-10-06 15:57:10 UTC
Created attachment 65182 [details]
file with 32 fontwork objects
Comment 2 cno 2009-10-06 15:57:39 UTC
Created attachment 65183 [details]
file with one fontwork objects
Comment 3 Armin Le Grand 2009-10-06 16:35:29 UTC
AW: Took a quick look. All FontWork objects with 3D will get converted to a
BitmapEx containing the 3D scene in printer resolution. That resolution is
limited to 1000000 square pixels per scene (can be adjusted in the
configuration), so maybe the printer resolution uses this, but it's needed ro
quality. This will explain some of the runtime and memory needs.
I then broke the process in the debugger and saw, that the most time is spent in
RemoveTransparenciesFromMetaFile.

AW->PL:  Directly breaked at RemoveTransparenciesFromMetaFile in
ImplQPrinter::PrePrintPage; getting there from print needed 5 seconds, while
getting over it took 5 minutes 12 seconds. You had a look at
RemoveTransparenciesFromMetaFile recently, what's going on there?
BTW: Printing works correctly and after the method, it's only another second to
get the print output.
Comment 4 philipp.lohmann 2009-10-06 16:57:22 UTC
pl->aw: RemoveTransparenciesFromMetaFile loops over the MetaFile, finds
contiguous regions that contain transparent actions and replaces those actions
with plain bitmaps (by rendering the MetaActions in each region to a
VirtualDevice and exchanging them in the output MetaFile with a DrawBitmap
action). It also has a tiling strategy as to not produce overly large single
bitmaps (as e.g. many printers have physical limits for bitmap sizes). Thorsten
invented that method, so I'll set him on CC.
Comment 5 thb 2009-10-07 09:07:13 UTC
Now, I didn't invent it, but I was basically the last one changing substantial
parts of it, yeah. Looking at the odg, it generates a metafile with 216797
actions, which seems a bit over the top for the 32 font works - given that this
is ok, everything needed to significantly improve performance amounts to
(another) rewrite of that method. As the comments state, the algorithm used
there has a worst-case time complexity of O(n^3). 

There are short-cuts in place already that handle simple
transparency-over-background cases already; in this case, the mtf though seems
to contain gazillions of overlapping, transparent objects, which, at that point
& with most of the high-level information thrown away, can only be handled the
hard way.

So the quick fix is to reduce the amount of meta actions (if possible), the root
cause fix would mean re-thinking the transparency emulation algorithm (one
could, when doing that anyway, also re-consider the split up only along
axis-aligned boxes; other print engines e.g. use polygonal clips (needs level2),
which tends to result in smaller bitmap areas), or, and that would be my
recommendation, go for pdf-based printing & delegate transparency handling to
the printer driver, where it belongs.
Comment 6 thb 2009-10-07 09:08:15 UTC
pl was missing from Cc, @pl: see my previous comment.
Comment 7 cno 2009-10-07 09:31:00 UTC
I agree 32 fontworks is a bit too much to be considered a 'normal', average
document.
But take the second one. Takes 35 seconds to print for me ...
Also changing windows (alt-tab) shows clear delay (appr. 3 seconds) to show the
document.
Thanks for all you attention to this issue,
Cor
Comment 8 thb 2009-10-07 09:50:12 UTC
@cornouws: nah, 32 font works should not be a problem; my "over the top"
statement referred to the amount of meta actions this generates internally
(which of course should also work, but in this case, seems to trigger the
near-worst-case scenario in the algorithm).
Comment 9 cno 2009-10-07 10:02:36 UTC
@thb: thnx, clear now!
Comment 10 wolframgarten 2009-10-07 10:31:11 UTC
Reassigned.
Comment 11 clippka 2009-10-07 10:46:29 UTC
changing target as this is an annoying problem.
Comment 12 Armin Le Grand 2009-10-07 10:51:24 UTC
AW: I have no idea what i should do with this task. I have nothing to do with
printing or to do it using MetaFiles at all. I have to do with MetaFile
creation, though.
I can clearly state that for 3D FontWork objects, a single BitmapEx as MetaFile
action gets created, nothing else. So i have no idea what might create 216797
actions all together, but i will take a look...
Comment 13 philipp.lohmann 2009-10-07 12:07:21 UTC
thb: PDF based printing is a rather CUPS centric point of view. This will not
help us at all for 90% of the user base.
Comment 14 thb 2009-10-07 12:45:15 UTC
@pl: indeed. and xps is likely not something to bet on _yet_ ... :/
Comment 15 cno 2009-10-07 13:31:43 UTC
<possibly dumb remark>
I was just looking at #75154 and reading the last comment 
could the number of colors in OOo have anything to do with performance on some
areas?
</possibly dumb remark>
Comment 16 Armin Le Grand 2009-10-07 13:59:31 UTC
AW: Checked the various object types which were used in the document, e.g. first
line left to right, calling them (a) to (d). Check can be done by anyone by
converting the object to MetaFile (context menu) and then breaking it.

(a) creates 3554 polygon objects on breaking the Metafile. Reason is the fat
line geometry (line width != 0). There are actions in the MetaFile for fat line,
but using them will lose the edge roundings (for which we have NO actions in the
MetaFile). No transparent objects created.

(b) creates 2800 polygon objects. Problem is the same, but doubles with shadow.
No transparent objects, though.

(c) creates a single, transparent BitmapEx object.

(d) creates 220 draw objects, one transparent BitmapEx for the colored shape and
the rest projected polygons for the 3D shadow. That 3D shadow shapes are not
merged to a single shape (ORed) since this operation isalso expensive and would
slow down paint extremely.

So all in all the problem is not only transparency, but also fat line geometry.
Unfortunately there is no MetaFile action for edge rounding, and it's not easy
to add one (problems involved here should be known).

Besides all the object count, the repaint is still good when the whole page
content is converted to Metafile.

AW->THB: There MUST be a way to better create those transparencies, even with a
lot of objects. In one line, there are only two transparent BitmapEx shapes, not
overlapping each other. Creating a bitmap for each of these areas does not
explain the time currently spent.
Comment 17 thb 2009-10-07 16:08:27 UTC
@aw: ok, let me find some time somewhere & have a deeper look ...
Comment 18 thb 2009-10-08 08:03:55 UTC
Ok. So right off, there's no easy way. I first noticed that the shadows for
fontwork type (d) consist of quite a few separate polygons; disabling that
shadow though does not help - _every_ other object on the page needs to be
considered, too; so the ~200k actions really count here.

And that's because calculating those axis-aligned connected components is a
_wicked_ problem. It would be much easier to calculate polygonal areas, which we
deliberately decided against back in the day, as this would have required
bitmasks in postscript.

The algorithm performs so badly in this case, because for every addition to a
connected component region, it's area grows in quite ill-natured ways - it
requires checking the new area against _all_ other existing connected components
(which can be quite a lot, when you consider the fat line emulation and some
intermediate states there). There's likely no way around this, and it's also
necessary to check _every_ metaaction, since it's potentially possible that
they'll, all together, somehow intersect with a transparent action. Armin, Andre
& myself once spent various days pondering this problem.

So I have to repeat my analysis - either reduce the input set, or use polygonal
regions (would also kill two birds with one stone, in that bit-masked bitmaps
would not be a "transparency"-to-be-emulated-case in the first place), or push
transparency directly to the printer. I'm sorry.
Comment 19 Armin Le Grand 2009-10-08 17:18:20 UTC
AW->THB: Has the algo have to be that complicated? Wouldn't it be enough to once
collect a List of Rects of transparent objects, and then paint all of them to
bitmaps? Why is this magic  'growing' needed...?
Comment 20 thb 2009-10-08 21:19:52 UTC
@aw: because you get visible seams otherwise. one half of the object rendered in
a bitmap, the other as a polygon. so you have to determine a self-contained set
of objects (and the complexity of that pretty much depends on what the
permissible border geometry looks like).
Comment 21 cno 2009-10-08 21:38:15 UTC
to print attachment
http://www.openoffice.org/nonav/issues/showattachment.cgi/65183/Issue105655_nl_Promo.odt
takes appr. three times as long on 3.1.1 as in 2.1/2.2/2.3.1 (some old
installations I have at hand)
This is known?
Comment 22 Armin Le Grand 2009-10-09 13:53:37 UTC
AW->cornouws: Yes, that's mainly because the geometry for fat lines needs to be
represented as decomposed geometry to include the line joins. As said, the
MetaFile does not have any possibility to handle that information.

AW: To solve this, i tried to expand the MetaFile to include such action. As a
start, i expanded LineInfo and it's streaming operators. Luckily, there is a
version info written/read in the file, so this indeed is possible.

The bad news starts when You try to use it; e.g. when saving a SVM (our own
MetaFile format, also used for OLEs), the stream operators at the MetaActions
are not used, but a class called SVMConverter. And guess what, there is NO
version information and NO way to add LineJoin info in a compatible way. Sigh :-(

All in all the MetaFile handling has VARIOUS ways to save/load them which cannot
all easily been found and not all of them can be expanded. So, a MetaFile which
went through a save/load cycle is NOT guaranteed the same MetaFile as before. Ahhh!

Investigating further if i can in any way hack the handling of the actions
META_LINE_ACTION and META_POLYLINE_ACTION in SVMConverter...
Comment 23 Armin Le Grand 2009-10-12 12:56:03 UTC
AW: Have now added a GDI_LINEJOIN_ACTION to SVMConverter whcih gets written at
META_LINE_ACTION and META_POLYLINE_ACTION when line is fat and has a join !=
ROUNDED (the default). Building without debug to check the speed, especially for
fixes like #i101491# which will be influenced by this. Looking for the number of
actions created with this change...
(Also changed OutputDevice::DrawPolyLine (the basegfx::B2DPolygon version) which
had a missing else at the end, also figured out a way to support
basegfx::B2DLINEJOIN_NONE under GDI+ without GDI+ supporting it)...
Comment 24 Armin Le Grand 2009-10-12 14:27:41 UTC
AW: It solves the printer speed problem (the amount of MetaFile actions is
reduced, i'll look into it in debug mode, but just using the bugdoc is good),
but the bugdoc from mentined #i101491# seems slower. I'll need to check that.
I'll also have to check all usages of MetaLineAction and MetaPolyLineAction in
all filters...
Comment 25 Armin Le Grand 2009-10-13 11:01:19 UTC
AW: Speed of the chart BugDoc (#i101491#) has reduced; it looks like the GDI+
FatLine paint is slower (2-3 times) than the old VCL rough polygon expansion
(without LineJoin, of course). Need to get that faster, experimenting...
Comment 26 Armin Le Grand 2009-10-13 15:19:06 UTC
AW: (a) breaks to 26, (b) to 26, (c) to 1, (d) to 219 draw objects, so the
problem with many objects is solved. Also converting to Metafile various
EdgeRounding objects works now (the LineJoins stay), but not yet over many
exports. It works for OLE now, but i have to look into various exports...
Comment 27 Armin Le Grand 2009-10-13 15:25:48 UTC
AW: I have used the bugdoc from #i101491# and looked for paint speed of fat
lines. GDI+ (on WIN32) is already used, so i needed to try to optimize that.
After some experimenting i found out that it's faster when giving integer
coordinates to GDI+ in WinSalGraphics::drawPolyLine, but this can only be done
when LineWidth is > 1.5 (else Hairlines will lose AA) and i decided to do it for
complex geometries (more than 250 points). This works pretty well and makes it a
little bit faster again, so changes up to now get acceptable.
Looking for Printing...
Comment 28 Armin Le Grand 2009-10-13 18:03:06 UTC
AW: Unfortunately all 7-10 (unknown number) of MetaFile consumers (more or less
all exporters, including SLideSHow and printing) will now no longer be able to
correctly show fat lines. The worked because the decomposed line geometry was
included (a dast and simple solution, but too expensive in extreme cases). So,
now i will have to look for all cases.
AW: SLideshow first; canvas(es) are more or less prepared for LineJoin, but the
transport is not good. Also found wrong default for MiterLimit already, too...
Comment 29 Armin Le Grand 2009-10-14 11:39:45 UTC
AW: Made DXCanvas work, VCLCanvas works out-of-the box using the actions (i was
astonished BTW; the fat lines get converted to polygons; they could get painted
directly). Looking for other canvases and if i can see something there...
Comment 30 Armin Le Grand 2009-10-14 13:24:26 UTC
AW: Added support to cairocanvas for rendering::PathJoinType::NONE. Starting a
linux build to check that (checked in code to do so).
AW: Looking for printing now...
Comment 31 Armin Le Grand 2009-10-14 17:21:53 UTC
AW: Printing solved; a helper class ImplLineConverter was used in VCL which is
the old version of line to fill polygon expansion. That version did not know
anything about LineJoins and needed to be replaced by the basegfx methods. Thus
i needed to cleanup OutputDevice::DrawLine and OutputDevice::DrawPolyLine to
behave right. Need to check further usages and correctness, e.g. with the closed
states involved...
Comment 32 Armin Le Grand 2009-10-15 10:53:24 UTC
AW: Corrected a curve subdivision for printing, checked and corrected PDF
export. Looking for more exports...
Comment 33 Armin Le Grand 2009-10-15 13:06:06 UTC
AW: Checked, HTML, XHTML, PDF and Macromedia Flash.
AW: Had to look into SWF (Macromedia Flash). The old version never took care of
LineJoins and handled dashes/dots by relying on the included decomposed
geometry. I had to adapt both points.
AW: For the LineJoin: There is support for LineJoin starting in SWF8 using
LINESTYLE2 and DefineShape4, but i did not want to go to new versions to
support, so i added a fallback. When not rounded (default is rounded, this is
supported), the geometry is prepared.
AW: For dashes/dots: Fallback was already there, but added geometry creation.
There was NO initial support for used LineInfos at the META_LINE_ACTION or the
META_POLYLINE_ACTION, added this, too.

AW: SWF done, too. Looking for other exports...
Comment 34 Armin Le Grand 2009-10-15 15:46:00 UTC
AW: EMF and WMFdone. I have filed #i105928# for further enhancements; up to now
LineInfo was not even used in any of them. They completely relied on the
MetaFile containing the decomposed LineGeometry.

Looking for EPS...
Comment 35 Armin Le Grand 2009-10-15 16:45:07 UTC
AW: EPS: Added support for basegfx::B2DLINEJOIN_NONE and forwarding of JoinStyle
in PSWriter::ImplWriteLineInfo.
AW: Looking further...
Comment 36 Armin Le Grand 2009-10-15 17:24:28 UTC
AW: For any reason GIF looked slightly strange; found the reason in the path
composition for GDI+ in WinSalGraphics::drawPolyLine where the optimization for
NoLineJoin does not have to close the polygon. Checking for other ocurrences...
AW: Okay, other ocurrences okay, next exporter...
Comment 37 Armin Le Grand 2009-10-16 11:59:18 UTC
AW: Ckecked MET (OS2 Metafile). In the original the LineJoins worked due to
contained decomposed line geometry. In the version with FatLine actions, all
linejoins get rounded. The export (eos2met.cxx) shows some support for LineInfo
(used in METWriter::METSetAndPushLineInfo), but i found NO documentation about
MET on the net anymore.

Does someone have infos...?

It may be that it supports LineJoin, so it would be nice to evtl. use it. OTOH
we would also need to import that and the format is not used by anyone anymore
(when looking in the web, we are the onnly app mentioned to be able to read it
nowadays (!))...

Leaving MET open for now, looking for others...
Comment 38 Armin Le Grand 2009-10-16 12:10:17 UTC
AW: For PBM, both (old and new) look identical, but boh lose fillings. Taking a
short look...
AW: Found PBMWriter::WritePBM where the 32bit bitmap gets reduced to 1bit by
calling Convert( BMP_CONVERSION_1BIT_THRESHOLD ), so i assume it's by purpose.
PBM checked.
Looking for next...
Comment 39 Armin Le Grand 2009-10-16 14:04:33 UTC
AW: Looking for PCT. It's losing the fat lines with the new MetaFile content,
looking...
Looked for documentation, none found. Adding standard decomposition actions for
MetaPolyLineAction and MetaLineAction. Unifying this now; adding tooling methods
to LineInfo and adapting all usages so far...
Comment 40 Armin Le Grand 2009-10-16 14:15:44 UTC
AW: Okay, PCT done and working. wmf, emf and swf adapted and tested.
AW: Next one...
Comment 41 Armin Le Grand 2009-10-16 16:23:57 UTC
AW: SVG was next. Neither at MetaPolyLineAction nor at MetaLineAction anything
besides rgb and stroke-opacity was supported. Added support for stroke-width,
stroke-dasharray and stroke-linejoin. Added support for B2DLINEJOIN_NONE. Fixed
that NO curve survived the export.
Looks good now, works and has a much better quality fo the exported SVG.
Looking for the next one...
Comment 42 Armin Le Grand 2009-10-16 18:44:30 UTC
AW: Unfortunately SVM (our own format) loses curve information since a
META_POLYLINE_ACTION is exported by using GDI_POLYLINE_ACTION which only
writes/reads the polygon points. Looking for a possibility to change this (no
version info written)...
Comment 43 Armin Le Grand 2009-10-19 10:34:46 UTC
Aw. Due to #i102224# where i already did changes to SVM format, i will have to
do a more clever change. Thinking about it and taking a 2nd look at #i102224#
changes...
Comment 44 Armin Le Grand 2009-10-19 16:31:06 UTC
AW: Have n ow included #i102224# to cvtsvm.cxx to not get problems later. For
the original, the Subdivided polygon gets written. For transporting the curve, i
have now added a GDI_EXTENDEDPOLYGON_ACTION which can write/read a whole
PolyPolygon with curve information. The trick is to read it; a counter to the
last polygon-centric input MetaFileAction is remembered (e.g. at import of
GDI_POLYLINE_ACTION). On import of GDI_EXTENDEDPOLYGON_ACTION this is then
matched and the action maybe replaced. To write it is necessary to create a
GDI_EXTENDEDPOLYGON_ACTION directly after a GDI_POLYLINE_ACTION.
Looking for other actions where curve information is lost...
Comment 45 Armin Le Grand 2009-10-19 16:57:15 UTC
AW: Have now extended META_POLYLINE_ACTION, META_CHORD_ACTION,
META_POLYGON_ACTION and META_POLYPOLYGON_ACTION to export an
extra-GDI_EXTENDEDPOLYGON_ACTION. All others will not work since they export
some action (e.g. GDI_GRADIENTEX_COMMENT action) and directly stream the
contained polygons using the polygon stream operator (which does not support
curve information). No way to extend these embedded polygons when they are
curves. Testing the supported actions and compatibility with older versions...
Comment 46 Armin Le Grand 2009-10-19 17:10:04 UTC
AW: Works as expected, but i need to extend the break method in svx. It needs to
support the LineJoin and also the change to LineWidth 0...
Comment 47 Armin Le Grand 2009-10-19 18:58:55 UTC
AW: DashDot also not supported up to now, need to add this, too. Added another
action (GDI_LINEDASHDOT_ACTION) and save/load functionality. Added support for
it in ImpSdrGDIMetaFileImport (for Break MTF support). Added various stuff to
ImpSdrGDIMetaFileImport for deeper LineJoin/DashDot/LineWidth support.
Checking...
Comment 48 cno 2009-10-20 21:06:52 UTC
@aw / ... a final request:  pls set the target of this issue.
Comment 49 Armin Le Grand 2009-10-21 12:48:00 UTC
AW->cornouws: Traget is on 3.x, so it will get 3.3 when finished before 3.3
deadline :-) Okay, setting to 3.3.
Comment 50 Armin Le Grand 2009-10-21 15:39:29 UTC
AW: Corrected some errors in ImpSdrGDIMetaFileImport. Added support for DashDot,
too, but it's currently not used since the MetaFile creator decomposes DashDots
using basegfx::tools::applyLineDashing. I opt not to change this to have a not
too bad roundtrip for saving new MetaFiles and loading them with older OOo
versions. The splitted line is more data than the decomposed line pattern, but
by far not so much more as the filled line geometry.

For SVM: RoundTrip inside new version is good now (including breaking the
MetaFile). Loading with older OOo loses EdgeRoundings. Loading from older OOo is
lossless since the FillGeometry is included (but Break is more bad, of course).

SVM is done so far, looing for next...
Comment 51 Armin Le Grand 2009-10-22 10:58:04 UTC
AW: Back to MET (was open for now). It's only used from OOo nowadays (even when
looking in the net, interestingly OOo is the ONLY app mentioned who can
read/write this), so it's definitely deprecated. Nonetheless, i will add the
standard expansion fron LineInfo tooling class...
Comment 52 Armin Le Grand 2009-10-22 12:16:32 UTC
AW: MET already handles LineWidth and DashDot, so i can simply let it as it is.
AW: Evaluating exports again:

Slideshow: Works
Printing: Works

HTML: Works
XHTML: Does the same as the original; seems broken somehow.
PDF: Works well. Note: Do NOT use FoxitReader, it has a display error with the
EdgeRounding
SWF: Works
BMP: Works
EMF: Works. Note: Is not viewable with WIN32 default viewer, needs to be
inserted to a new page. Same with original. Breaking up works well, too (much
better than in original)
EPS: Works well, no quality lost compared to original.
GIF: Works well
JPEG: Works well
MET: Loses LineJoin (as expected), but smaller. Maybe a todo...
PBM: Works
PCT: Works. Note: wrong display in PSP version 7.04
PGM: Works well
PNG: Works well
PPM: Works well
RAS: Works well
SVG: Works well. Used Inkscape for testing, quality is much improved
SVM: Works well. Especially round-trip with breaking much improved. Keeps
beziers, LineJoins and DashDot (last one still broken down for compatibility).
Loading with old version loses LineJoins, this is not avoidable. This is the
most critical one since this is the format the OLE MteaFiles are transported
(e.g. Chart).
TIFF: Works well
WMF: Works well
XPM: Works well
PWP: Cannot read, but it's a pixel based format (AFAICFO), thus it should be
okay. Seems not to be used.

Back to SVM: It's used for OLEs, thus it's critical. This task is about reducing
MetaFile size by writing LineInfo MetaFile actions instead of the decomposed
line geometry which is potentially very big. In old versions all LineJoins and
beziers and DashDot styles for fat lines only worked because the decomposed line
goemerty was added, but this leads to various performance problems.

There is no other solution: It needs to be avoided, thus LineActions including
the LineJoin, LineWidth, DashDot and bezier information need to be written. This
solves the performance problem, but requires that ALL users of MetaFiles learn
to handle those actions correctly.
This users are the listed exporters, SlideShow, Printing and breaking up a
MetaFile in editview. I adapted all those users (see comments above).

The result is a solution fo rthe performance problems, but there is one single
caveat: Loading SVMs (e.g. contained in OLEs) with an older OOo version. There,
up to now the MetaFile only exported the LineWidth, thus LineJoin will be lost.
This is no pronlem with chart, where LineJoin was/is not editable up to now, so
all OLE line charts use LineJoin round what is the default at import.

Roundtrip is okay and loading from an older Ooo version also (since it includes
the expanded geometry).
Comment 53 Armin Le Grand 2009-10-22 12:19:06 UTC
AW: All done so far. I declare MET as deprecated and leave it as it is. Checked in.
Comment 54 Armin Le Grand 2009-11-26 11:34:04 UTC
AW: Checked in installed build, works as expected.
Comment 55 Armin Le Grand 2009-11-26 11:37:32 UTC
AW->WG: Please review.
Comment 56 wolframgarten 2009-11-26 14:19:57 UTC
Verified in CWS.
Comment 57 Armin Le Grand 2010-01-19 12:18:10 UTC
AW: Closing.