Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve support of sub/superscript #755

Merged
merged 3 commits into from
Aug 8, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,4 @@ fontFaceDeclsTest.odt
test.odt
simple.odt
simpleFrame.odt
webodf/tests/label-alignment-list.odt
webodf/tests/label-width-and-position-list.odt
webodf/tests/*.odt
3 changes: 2 additions & 1 deletion ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

### Improvements

* Add support for double line-through in Firefox (Chrome/Safari + IE don't support this feature) ([#755](https://github.com/kogmbh/WebODF/pull/755))
* Add support for double line-through in Firefox (Chrome/Safari + IE don't support this feature) ([#758](https://github.com/kogmbh/WebODF/pull/758))
* Add support for subscript & superscript ([#755](https://github.com/kogmbh/WebODF/pull/755))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also add Section title ### Improvements


### Fixes

Expand Down
1 change: 1 addition & 0 deletions webodf/lib/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@
"odf.Style2CSS": [
"core.CSSUnits",
"odf.OdfUtils",
"odf.StyleParseUtils",
"odf.StyleTree",
"xmldom.XPath"
],
Expand Down
80 changes: 56 additions & 24 deletions webodf/lib/odf/Style2CSS.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ odf.Style2CSS = function Style2CSS() {
* @type {!string}*/
webodfhelperns = "urn:webodf:names:helper",
domUtils = new core.DomUtils(),
styleParseUtils = new odf.StyleParseUtils(),

/**@const
@type{!Object.<string,string>}*/
Expand Down Expand Up @@ -397,17 +398,42 @@ odf.Style2CSS = function Style2CSS() {
parentStyleNode = xpath.getODFElementsWithXPath(/**@type{!Element}*/(odfRoot), xp, odf.Namespaces.lookupNamespaceURI)[0];
return parentStyleNode;
}

/**
* Parse the style:text-position property
* http://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os-part1.html#__RefHeading__1420212_253892949
*
* Examples:
* "sub"
* "super 20%"
* "10% 20%"
* "-15% 50%"
*
* @param {!string} position
* @return {!{verticalTextPosition: !string, fontHeight: (!string|undefined)}}
*/
function parseTextPosition(position) {
var parts = styleParseUtils.parseAttributeList(position);
return {
verticalTextPosition: parts[0],
fontHeight: parts[1]
};
}
/**
* @param {!Element} props
* @return {!string}
*/
function getTextProperties(props) {
var rule = '', fontName, fontSize, value,
var rule = '',
fontName,
fontSize,
value,
textDecorationLine = '',
textDecorationStyle = '',
textPosition,
fontSizeRule = '',
sizeMultiplier = 1,
parentStyle;
textFamilyStyleNode;

rule += applySimpleMapping(props, textPropertySimpleMapping);

Expand Down Expand Up @@ -453,35 +479,41 @@ odf.Style2CSS = function Style2CSS() {
rule += 'font-family: ' + (value || fontName) + ';';
}

parentStyle = /**@type{!Element}*/(props.parentNode);
fontSize = getFontSize(parentStyle);
// This is actually the font size of the current style.
if (!fontSize) {
return rule;
value = props.getAttributeNS(stylens, 'text-position');
if (value) {
textPosition = parseTextPosition(value);
rule += 'vertical-align: ' + textPosition.verticalTextPosition + '\n; ';
if (textPosition.fontHeight) {
sizeMultiplier = parseFloat(textPosition.fontHeight) / 100;
}
}

while (parentStyle) {
fontSize = getFontSize(parentStyle);
if (fontSize) {
// If the current style's font size is a non-% value, then apply the multiplier to get the child style (with the %)'s
// actual font size. And now we can stop crawling up the style ancestry since we have a concrete font size.
if (fontSize.unit !== '%') {
fontSizeRule = 'font-size: ' + (fontSize.value * sizeMultiplier) + fontSize.unit + ';';
break;
if (props.hasAttributeNS(fons, "font-size") || sizeMultiplier !== 1) {
// This is actually the font size of the current style.
textFamilyStyleNode = /**@type{!Element}*/(props.parentNode);
while (textFamilyStyleNode) {
fontSize = getFontSize(textFamilyStyleNode);
if (fontSize) {
// If the current style's font size is a non-% value, then apply the multiplier to get the child style (with the %)'s
// actual font size. And now we can stop crawling up the style ancestry since we have a concrete font size.
if (fontSize.unit !== '%') {
fontSizeRule = 'font-size: ' + (fontSize.value * sizeMultiplier) + fontSize.unit + ';';
break;
}
// If we got a % font size for the current style, then update the multiplier with it's 'normalized' multiplier
sizeMultiplier *= (fontSize.value / 100);
}
// If we got a % font size for the current style, then update the multiplier with it's 'normalized' multiplier
sizeMultiplier *= (fontSize.value / 100);
// Crawl up the style ancestry
textFamilyStyleNode = getParentStyleNode(textFamilyStyleNode);
}
// If there was nothing in the ancestry that specified a concrete font size, just apply the multiplier onto the page's default font size.
if (!fontSizeRule) {
fontSizeRule = 'font-size: ' + parseFloat(defaultFontSize) * sizeMultiplier + cssUnits.getUnits(defaultFontSize) + ';';
}
// Crawl up the style ancestry
parentStyle = getParentStyleNode(parentStyle);
}

// If there was nothing in the ancestry that specified a concrete font size, just apply the multiplier onto the page's default font size.
if (!fontSizeRule) {
fontSizeRule = 'font-size: ' + parseFloat(defaultFontSize) * sizeMultiplier + cssUnits.getUnits(defaultFontSize) + ';';
}

rule += fontSizeRule;

return rule;
}
/**
Expand Down
21 changes: 21 additions & 0 deletions webodf/lib/odf/StyleParseUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,4 +182,25 @@ odf.StyleParseUtils = function () {
return e;
}
this.getPropertiesElement = getPropertiesElement;


/**
* Split a space-separated attribute list into it's list items. Ignores leading & trailing
* whitespace, and collapses excessive internal whitespace. If the input text is null, undefined
* or pure whitespace, an empty array will be returned.
*
* @param {?string|undefined} text
* @return {!Array.<!string>}
*/
/*jslint regexp: true*/
function parseAttributeList(text) {
if (text) {
text = text.replace(/^\s*(.*?)\s*$/g, "$1"); // Trim leading + trailing whitespace
}
// Calling split on an empty string returns a [""]. Avoid this by only attempting to split if the
// string is non-zero-length
return text && text.length > 0 ? text.split(/\s+/) : [];
}
/*jslint regexp: false*/
this.parseAttributeList = parseAttributeList;
};
38 changes: 34 additions & 4 deletions webodf/tests/odf/StyleParseUtilsTests.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@ odf.StyleParseUtilsTests = function StyleParseUtilsTests(runner) {
}

function testParseLength() {
t.styleParseUtils = new odf.StyleParseUtils();

doTestParseLength(null, undefined);
doTestParseLength(undefined, undefined);
doTestParseLength("very long", undefined);
Expand Down Expand Up @@ -78,15 +76,47 @@ odf.StyleParseUtilsTests = function StyleParseUtilsTests(runner) {
doTestParseLength("0pc", 0);
}

function parseAttributeList_IgnoresLeadingAndTrailingSpace() {
t.result = t.styleParseUtils.parseAttributeList(" a b c ");
r.shouldBe(t, "t.result", "['a', 'b', 'c']");
}

function parseAttributeList_CollapsesExcessiveSpace() {
t.result = t.styleParseUtils.parseAttributeList(" a bc def ");
r.shouldBe(t, "t.result", "['a', 'bc', 'def']");
}

function parseAttributeList_WhenInputIsUndefined_ReturnsEmptyArray() {
t.result = t.styleParseUtils.parseAttributeList(null);
r.shouldBe(t, "t.result", "[]");

t.result = t.styleParseUtils.parseAttributeList(undefined);
r.shouldBe(t, "t.result", "[]");
}

function parseAttributeList_WhenInputIsBlankString_ReturnsEmptyArray() {
t.result = t.styleParseUtils.parseAttributeList("");
r.shouldBe(t, "t.result", "[]");

t.result = t.styleParseUtils.parseAttributeList(" ");
r.shouldBe(t, "t.result", "[]");
}

this.setUp = function () {
t = {};
t = {
styleParseUtils: new odf.StyleParseUtils()
};
};
this.tearDown = function () {
t = {};
};
this.tests = function () {
return r.name([
testParseLength
testParseLength,
parseAttributeList_IgnoresLeadingAndTrailingSpace,
parseAttributeList_CollapsesExcessiveSpace,
parseAttributeList_WhenInputIsUndefined_ReturnsEmptyArray,
parseAttributeList_WhenInputIsBlankString_ReturnsEmptyArray
]);
};
this.asyncTests = function () {
Expand Down
125 changes: 125 additions & 0 deletions webodf/tests/odf/layouttests.xml
Original file line number Diff line number Diff line change
Expand Up @@ -421,4 +421,129 @@
</check>
</layoutchecks>
</test>
<test name="fontsize">
<input>
<office:document-styles>
<office:styles>
<style:default-style style:family="text"><style:text-properties fo:font-size="10px"/></style:default-style>
<style:style style:name="percentSizeParent" style:family="text"><style:text-properties fo:font-size="20px"/></style:style>
</office:styles>
<office:automatic-styles>
<style:style style:name="nosize" style:family="text"><style:text-properties/></style:style>
<style:style style:name="ptSize" style:family="text"><style:text-properties fo:font-size="20pt"/></style:style>
<style:style style:name="pxSize" style:family="text"><style:text-properties fo:font-size="20px"/></style:style>
<style:style style:name="percentSize" style:parent-style-name="percentSizeParent" style:family="text">
<style:text-properties fo:font-size="50%"/>
</style:style>
</office:automatic-styles>
</office:document-styles>
<office:text>
<text:p>
<text:span text:style-name="nosize">nosize</text:span>
<text:span text:style-name="ptSize">ptSize</text:span>
<text:span text:style-name="pxSize">pxSize</text:span>
<text:span text:style-name="percentSize">percentSize</text:span>
</text:p>
</office:text>
</input>
<layoutchecks>
<check xpath="(.//text:span)[1]">
<fontSize value="10px"/>
</check>
<check xpath="(.//text:span)[2]">
<fontSize value="27px"/>
</check>
<check xpath="(.//text:span)[3]">
<fontSize value="20px"/>
</check>
<check xpath="(.//text:span)[4]">
<fontSize value="10px"/>
</check>
</layoutchecks>
</test>

<test name="superscript">
<input>
<office:document-styles>
<office:styles>
<style:default-style style:family="text"><style:text-properties fo:font-size="10px"/></style:default-style>
</office:styles>
<office:automatic-styles>
<style:style style:name="super" style:family="text"><style:text-properties style:text-position="super"/></style:style>
<style:style style:name="superWithPercent" style:family="text"><style:text-properties style:text-position="super 80%"/></style:style>
<style:style style:name="superPercent" style:family="text"><style:text-properties style:text-position="30%"/></style:style>
<style:style style:name="superPercentWithPercent" style:family="text"><style:text-properties style:text-position="30% 80%"/></style:style>
<style:style style:name="superWithFontSize" style:family="text"><style:text-properties fo:font-size="30px" style:text-position="super 50%"/></style:style>
</office:automatic-styles>
</office:document-styles>
<office:text>
<text:p>
<text:span text:style-name="super">super</text:span>
<text:span text:style-name="superWithPercent">superWithPercent</text:span>
<text:span text:style-name="superPercent">superPercent</text:span>
<text:span text:style-name="superPercentWithPercent">superPercentWithPercent</text:span>
<text:span text:style-name="superWithFontSize">superWithFontSize</text:span>
</text:p>
</office:text>
</input>
<layoutchecks>
<check xpath="(.//text:span)[1]">
<verticalAlign value="super"/>
<fontSize value="10px"/>
</check>
<check xpath="(.//text:span)[2]">
<verticalAlign value="super"/>
<fontSize value="8px"/>
</check>
<check xpath="(.//text:span)[3]">
<verticalAlign value="30%"/>
<fontSize value="10px"/>
</check>
<check xpath="(.//text:span)[4]">
<verticalAlign value="30%"/>
<fontSize value="8px"/>
</check>
<check xpath="(.//text:span)[5]">
<verticalAlign value="super"/>
<fontSize value="15px"/>
</check>
</layoutchecks>
</test>


<test name="subscript">
<input>
<office:document-styles>
<office:styles>
<style:default-style style:family="text"><style:text-properties fo:font-size="10px"/></style:default-style>
</office:styles>
<office:automatic-styles>
<style:style style:name="subscript" style:family="text"><style:text-properties style:text-position="sub"/></style:style>
<style:style style:name="subscriptWithPercent" style:family="text"><style:text-properties style:text-position="sub 80%"/></style:style>
<style:style style:name="subscriptPercent" style:family="text"><style:text-properties style:text-position="-30%"/></style:style>
</office:automatic-styles>
</office:document-styles>
<office:text>
<text:p>
<text:span text:style-name="subscript">sub</text:span>
<text:span text:style-name="subscriptWithPercent">subWithPercent</text:span>
<text:span text:style-name="subscriptPercent">subPercent</text:span>
</text:p>
</office:text>
</input>
<layoutchecks>
<check xpath="(.//text:span)[1]">
<verticalAlign value="sub"/>
<fontSize value="10px"/>
</check>
<check xpath="(.//text:span)[2]">
<verticalAlign value="sub"/>
<fontSize value="8px"/>
</check>
<check xpath="(.//text:span)[3]">
<verticalAlign value="-30%"/>
<fontSize value="10px"/>
</check>
</layoutchecks>
</test>
</layouttests>
2 changes: 1 addition & 1 deletion webodf/tools/karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ module.exports = function (config) {
'lib/odf/Formatting.js',
'lib/odf/StyleTree.js',
'lib/odf/ListStylesToCss.js',
'lib/odf/StyleParseUtils.js',
'lib/odf/Style2CSS.js',
'lib/gui/ZoomHelper.js',
'lib/ops/Canvas.js',
Expand Down Expand Up @@ -147,7 +148,6 @@ module.exports = function (config) {
'lib/gui/UndoStateRules.js',
'lib/gui/TrivialUndoManager.js',
'lib/odf/CommandLineTools.js',
'lib/odf/StyleParseUtils.js',
'lib/odf/GraphicProperties.js',
'lib/odf/PageLayoutProperties.js',
'lib/odf/ParagraphProperties.js',
Expand Down