You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This is a design question rather than a bug report, and it wants a maintainer's decision before
anything is written. Three defects and three user reports below all follow from the same split,
so I would rather ask once than patch each symptom.
Style\Border and Style\Outline both describe the stroke of a shape. Both are written as a:ln in PowerPoint2007 (writeBorder(), AbstractDecoratorWriter.php:63, and writeOutline(), :234) and as draw:stroke / svg:stroke-* in ODPresentation. Which class a given object gets is
decided by history, not by the model:
carries Border
carries Outline
AbstractShape — so every shape
Shape\AutoShape
Shape\Chart\Legend
Shape\Chart\Axis
Shape\Chart\Marker
Shape\Chart\Gridlines
a table Cell (four of them, via Borders)
Shape\Chart\Series
Outline was added in c25b553 (2016, #169) to give a chart series a line width and colour. Border already carried a line width, a colour, a dash style and a compound style at that point.
Neither class covers CT_LineProperties
a:ln is one type: w, cap, cmpd, algn, then a fill group (a:noFill | a:solidFill | a:gradFill | a:pattFill), then a dash group, then join, arrow ends, a:extLst.
Border has lineWidth, lineStyle, dashStyle, Color. It cannot describe a gradient or
pattern line, because its colour is a Color and not a Fill.
Outline has width and a Fill. It cannot describe a dash or a compound line, because it
has neither field.
Between them they cover the type; separately, neither does. writeBorder() emits w, cap, cmpd, algn and a:prstDash; writeOutline() emits w and a fill and nothing else.
LibreOffice keeps the same information in one struct — oox/inc/drawingml/lineproperties.hxx:
structLineProperties {
FillProperties maLineFill; // what this library calls Outline
DashStopVector maCustomDash;
std::optional<sal_Int32> moLineWidth, moPresetDash, moLineCompound, moLineCap, moLineJoint;
};
and LineProperties::getLineStyle() has to read both halves to answer one question:
if (maLineFill.moFillType.value() == XML_noFill) return LineStyle_NONE;
if (moPresetDash && *moPresetDash != XML_solid) return LineStyle_DASH;
return LineStyle_SOLID;
Whether a line exists is a property of the fill — this library's Outline. Whether it is solid or
dashed is a property of the dash — this library's Border. Neither PHP class can see the other.
What follows from the split, measured on master
1. A LINE_DOUBLE shape is written to ODP as no line at all. Content.php:1298 (writeLineStyle()) switches on getLineStyle() and maps everything that is
not LINE_SINGLE or LINE_NONE to draw:stroke="none". So LINE_DOUBLE, LINE_THICKTHIN, LINE_THINTHICK and LINE_TRI — four of the six constants — silently delete the line. ODF's draw:stroke takes only none, solid and dash, so a compound line genuinely has no ODF
spelling; falling back to solid would at least keep the line.
2. The same width means different sizes.getLineWidth() and getWidth() have no documented
unit, and every writer picked its own. Measured with a single Border::setLineWidth(10) on one RichText, written to both formats:
output
in points
PowerPoint2007
<a:ln w="95250">
7.5pt (read as pixels)
ODPresentation
svg:stroke-width="0.353cm"
10pt (read as points)
Outline is inconsistent within one file. One chart, Outline::setWidth(10) on the X axis and
on the series:
ObjectsChart.php:888 (the chart wall) uses pixels as well, :415 (gridlines) uses points. #703 fixed one of these sites in the PowerPoint2007 writer and the others were never revisited —
which is what a value with no owning contract does.
3. Border::lineStyle conflates two things, one level further down. LINE_SINGLE = sng, LINE_DOUBLE = dbl, LINE_THICKTHIN, LINE_THINTHICK, LINE_TRI are ST_CompoundLine values, and writeBorder() writes them to cmpd. LINE_NONE = none is not a
valid cmpd value at all — it is a sentinel that the writer turns into a:noFill
(AbstractDecoratorWriter.php:71-73, :83-84). So one field carries both what shape the line
has and whether there is a line, which is the same conflation the two classes produce.
What users have run into
How to customize the color and linestyle of the axisX and axisY #292 — to colour an axis line, the reporter had to patch the library: add an Outline
property to Shape\Chart\Axis and a writeOutline() call to writeAxis(). Every shape already
had getBorder(); Axis is not a shape, so it had none.
Format axis line #255 — "our style requires that there is no visible Y axis line", and the request was
literally getAxisY()->setLine([outline object]), "similar to the implementation for
Gridlines". The user's word for the concept is neither of ours.
圆角矩形创建,无法设置边框线条宽度以及颜色 #884 — AutoShape inherits getBorder() from AbstractShape and owns getOutline()
separately. The border it hands out is live: it takes a width and a colour and gives them back.
No writer ever reads it. The reporter found the inherited getter first, which is the plausible
one, and concluded the feature was missing.
Proposal
The three consequences above are independent of the model question and could be fixed today: LINE_DOUBLE → draw:stroke="solid" in ODP, and one unit for Outline::getWidth() across the
four ODP sites. The second one changes the rendering of existing decks, which is why it is here
and not in a PR.
For the model itself, three options as I see them, in the order I would rank them:
A. Border grows a Fill; Outline becomes a deprecated view of it. Border::getFill(): Fill alongside the existing getColor(): ?Color, with the colour kept as the
convenience accessor it already is. The four chart classes gain getBorder()/setBorder(), and getOutline()/setOutline() stay as @deprecated delegates returning a Border-backed view, so
no existing call breaks in 1.x. writeOutline() becomes a call to writeBorder(). Removal at 2.0.
This direction is the cheaper one: Border is already on AbstractShape and is the one users
reach for by name.
B. The reverse — Outline grows the dash and the compound and Border is deprecated. Same end
state, but the deprecation lands on the class with far more call sites, including every table cell.
C. Keep both, document the split, fix only the three defects. Cheapest, and leaves AutoShape
handing out a live border that nothing reads.
I am happy to write A as a PR if that is the direction, in the order: the two defect fixes first as
their own PRs (they stand alone), then the Fill on Border, then the chart classes.
What waits on the answer: #884, and any documentation of AutoShape's line, which today has no
correct way to describe itself.
This is a design question rather than a bug report, and it wants a maintainer's decision before
anything is written. Three defects and three user reports below all follow from the same split,
so I would rather ask once than patch each symptom.
Style\BorderandStyle\Outlineboth describe the stroke of a shape. Both are written asa:lnin PowerPoint2007 (writeBorder(),AbstractDecoratorWriter.php:63, andwriteOutline(),:234) and asdraw:stroke/svg:stroke-*in ODPresentation. Which class a given object gets isdecided by history, not by the model:
BorderOutlineAbstractShape— so every shapeShape\AutoShapeShape\Chart\LegendShape\Chart\AxisShape\Chart\MarkerShape\Chart\GridlinesCell(four of them, viaBorders)Shape\Chart\SeriesOutlinewas added in c25b553 (2016, #169) to give a chart series a line width and colour.Borderalready carried a line width, a colour, a dash style and a compound style at that point.Neither class covers
CT_LinePropertiesa:lnis one type:w,cap,cmpd,algn, then a fill group (a:noFill|a:solidFill|a:gradFill|a:pattFill), then a dash group, then join, arrow ends,a:extLst.BorderhaslineWidth,lineStyle,dashStyle,Color. It cannot describe a gradient orpattern line, because its colour is a
Colorand not aFill.Outlinehaswidthand aFill. It cannot describe a dash or a compound line, because ithas neither field.
Between them they cover the type; separately, neither does.
writeBorder()emitsw,cap,cmpd,algnanda:prstDash;writeOutline()emitswand a fill and nothing else.LibreOffice keeps the same information in one struct —
oox/inc/drawingml/lineproperties.hxx:and
LineProperties::getLineStyle()has to read both halves to answer one question:Whether a line exists is a property of the fill — this library's
Outline. Whether it is solid ordashed is a property of the dash — this library's
Border. Neither PHP class can see the other.What follows from the split, measured on
master1. A
LINE_DOUBLEshape is written to ODP as no line at all.Content.php:1298(writeLineStyle()) switches ongetLineStyle()and maps everything that isnot
LINE_SINGLEorLINE_NONEtodraw:stroke="none". SoLINE_DOUBLE,LINE_THICKTHIN,LINE_THINTHICKandLINE_TRI— four of the six constants — silently delete the line. ODF'sdraw:stroketakes onlynone,solidanddash, so a compound line genuinely has no ODFspelling; falling back to
solidwould at least keep the line.2. The same width means different sizes.
getLineWidth()andgetWidth()have no documentedunit, and every writer picked its own. Measured with a single
Border::setLineWidth(10)on oneRichText, written to both formats:<a:ln w="95250">svg:stroke-width="0.353cm"Outlineis inconsistent within one file. One chart,Outline::setWidth(10)on the X axis andon the series:
styleAxisX0.353cmpointsToCentimeters(),ObjectsChart.php:375styleSeries00.265cmpixelsToCentimeters(),ObjectsChart.php:824ObjectsChart.php:888(the chart wall) uses pixels as well,:415(gridlines) uses points.#703 fixed one of these sites in the PowerPoint2007 writer and the others were never revisited —
which is what a value with no owning contract does.
3.
Border::lineStyleconflates two things, one level further down.LINE_SINGLE=sng,LINE_DOUBLE=dbl,LINE_THICKTHIN,LINE_THINTHICK,LINE_TRIareST_CompoundLinevalues, andwriteBorder()writes them tocmpd.LINE_NONE=noneis not avalid
cmpdvalue at all — it is a sentinel that the writer turns intoa:noFill(
AbstractDecoratorWriter.php:71-73,:83-84). So one field carries both what shape the linehas and whether there is a line, which is the same conflation the two classes produce.
What users have run into
Outlineproperty to
Shape\Chart\Axisand awriteOutline()call towriteAxis(). Every shape alreadyhad
getBorder();Axisis not a shape, so it had none.literally
getAxisY()->setLine([outline object]), "similar to the implementation forGridlines". The user's word for the concept is neither of ours.
AutoShapeinheritsgetBorder()fromAbstractShapeand ownsgetOutline()separately. The border it hands out is live: it takes a width and a colour and gives them back.
No writer ever reads it. The reporter found the inherited getter first, which is the plausible
one, and concluded the feature was missing.
Proposal
The three consequences above are independent of the model question and could be fixed today:
LINE_DOUBLE→draw:stroke="solid"in ODP, and one unit forOutline::getWidth()across thefour ODP sites. The second one changes the rendering of existing decks, which is why it is here
and not in a PR.
For the model itself, three options as I see them, in the order I would rank them:
A.
Bordergrows aFill;Outlinebecomes a deprecated view of it.Border::getFill(): Fillalongside the existinggetColor(): ?Color, with the colour kept as theconvenience accessor it already is. The four chart classes gain
getBorder()/setBorder(), andgetOutline()/setOutline()stay as@deprecateddelegates returning aBorder-backed view, sono existing call breaks in 1.x.
writeOutline()becomes a call towriteBorder(). Removal at 2.0.This direction is the cheaper one:
Borderis already onAbstractShapeand is the one usersreach for by name.
B. The reverse —
Outlinegrows the dash and the compound andBorderis deprecated. Same endstate, but the deprecation lands on the class with far more call sites, including every table cell.
C. Keep both, document the split, fix only the three defects. Cheapest, and leaves
AutoShapehanding out a live border that nothing reads.
I am happy to write A as a PR if that is the direction, in the order: the two defect fixes first as
their own PRs (they stand alone), then the
FillonBorder, then the chart classes.What waits on the answer: #884, and any documentation of
AutoShape's line, which today has nocorrect way to describe itself.