Bug 549861 - add missing files from reland patch. r=bustage

This commit is contained in:
John Daggett 2013-05-20 12:47:32 +09:00
Родитель 3eb1fdd857
Коммит 77f5e06d8f
35 изменённых файлов: 1554 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,48 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* John Daggett <jdaggett@mozilla.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsIDOMCSSRule.idl"
[scriptable, uuid(f4cb1776-389d-4f52-a4d8-68bea5bd00c1)]
interface nsIDOMCSSFontFeatureValuesRule : nsIDOMCSSRule
{
attribute DOMString fontFamily;
// raises(DOMException) on setting
attribute DOMString valueText;
// raises(DOMException) on setting
};

Просмотреть файл

@ -0,0 +1,81 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "gfxFontFeatures.h"
#include "nsUnicharUtils.h"
#include "nsHashKeys.h"
using namespace mozilla;
gfxFontFeatureValueSet::gfxFontFeatureValueSet()
{
mFontFeatureValues.Init(10);
}
bool
gfxFontFeatureValueSet::GetFontFeatureValuesFor(const nsAString& aFamily,
uint32_t aVariantProperty,
const nsAString& aName,
nsTArray<uint32_t>& aValues)
{
nsAutoString family(aFamily), name(aName);
ToLowerCase(family);
ToLowerCase(name);
FeatureValueHashKey key(family, aVariantProperty, name);
aValues.Clear();
FeatureValueHashEntry *entry = mFontFeatureValues.GetEntry(key);
if (entry) {
NS_ASSERTION(entry->mValues.Length() > 0,
"null array of font feature values");
aValues.AppendElements(entry->mValues);
return true;
}
return false;
}
void
gfxFontFeatureValueSet::AddFontFeatureValues(const nsAString& aFamily,
const nsTArray<gfxFontFeatureValueSet::FeatureValues>& aValues)
{
nsAutoString family(aFamily);
ToLowerCase(family);
uint32_t i, numFeatureValues = aValues.Length();
for (i = 0; i < numFeatureValues; i++) {
const FeatureValues& fv = aValues.ElementAt(i);
uint32_t alternate = fv.alternate;
uint32_t j, numValues = fv.valuelist.Length();
for (j = 0; j < numValues; j++) {
const ValueList& v = fv.valuelist.ElementAt(j);
nsAutoString name(v.name);
ToLowerCase(name);
FeatureValueHashKey key(family, alternate, name);
FeatureValueHashEntry *entry = mFontFeatureValues.PutEntry(key);
entry->mKey = key;
entry->mValues = v.featureSelectors;
}
}
}
bool
gfxFontFeatureValueSet::FeatureValueHashEntry::KeyEquals(
const KeyTypePointer aKey) const
{
return aKey->mPropVal == mKey.mPropVal &&
aKey->mFamily.Equals(mKey.mFamily) &&
aKey->mName.Equals(mKey.mName);
}
PLDHashNumber
gfxFontFeatureValueSet::FeatureValueHashEntry::HashKey(
const KeyTypePointer aKey)
{
return HashString(aKey->mFamily) + HashString(aKey->mName) +
aKey->mPropVal * uint32_t(0xdeadbeef);
}

Просмотреть файл

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
@font-face {
font-family: libertine;
src: url(../fonts/LinLibertine_Re-4.7.5.woff) format("woff");
}
body {
font-family: libertine, sans-serif;
font-size: 800%;
line-height: 1.2em;
}
div { margin: 0 20px; }
span {
-moz-font-feature-settings: "ss05"; /* crossed W */
}
</style>
</head>
<body lang="en">
<div><span id="test1">W</span> <span id="test2">W</span> <span id="test3">W</span></div>
<div><span id="test4">W</span> <span id="test5">W</span> <span id="test6">W</span></div>
<div><span id="test7">W</span> <span id="test8">W</span> <span id="test9">W</span></div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,116 @@
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
@font-face {
font-family: libertine;
src: url(../fonts/LinLibertine_Re-4.7.5.woff) format("woff");
}
@font-face {
font-family: fontA;
src: url(../fonts/LinLibertine_Re-4.7.5.woff) format("woff");
-moz-font-feature-settings: "ss05" on;
}
@font-face {
font-family: fontB;
src: url(../fonts/LinLibertine_Re-4.7.5.woff) format("woff");
-moz-font-feature-settings: "ss05" off;
}
@font-feature-values libertine {
@styleset {
crossed-doubleu: 5;
somethingElse: 4;
}
}
@font-feature-values fontA {
@styleset { aLtW: 5; }
}
@font-feature-values fontB {
@styleset { crossedW: 5; several: 1 3 5; }
@styleset { altW: 4; }
}
@font-feature-values fontB {
@styleset {
AlTw: 5;
defined-for-fontB: 5;
scriptJ: 3;
}
}
body {
font-family: libertine, sans-serif;
font-size: 800%;
line-height: 1.2em;
}
/* -moz-font-feature-settings: "ss05"; crossed W */
div { margin: 0 20px; }
#test1 {
font-variant-alternates: styleset(crossed-doubleu);
}
#test2 {
/* testing case-insensitivity of styleset name */
font-family: fontB;
font-variant-alternates: styleset(altW);
}
#test3 {
/* testing case-insensitivity of styleset name */
font-family: fontB;
font-variant-alternates: styleset(ALTW);
}
#test4 {
/* testing escapes in styleset name */
font-family: fontB;
font-variant-alternates: styleset(\41 ltW);
}
#test5 {
/* testing font-specificity of feature value rule */
font-family: fontA;
font-variant-alternates: styleset(defined-for-fontB);
}
#test6 {
/* testing one feature doesn't affect another */
font-variant-alternates: styleset(somethingElse);
-moz-font-feature-settings: "ss05" on;
}
#test7 {
/* testing font-specificity of feature value rule */
font-family: fontA;
font-variant-alternates: styleset(scriptJ);
-moz-font-feature-settings: "ss06";
}
#test8 {
/* testing that an undefined value doesn't affect the results */
font-family: fontB;
font-variant-alternates: styleset(scriptJ, somethingUndefined, defined-for-fontB);
}
#test9 {
/* testing matching of font name with escape */
font-family: font\62 ;
font-variant-alternates: styleset(defined-for-fontB);
}
</style>
</head>
<body lang="en">
<div><span id="test1">W</span> <span id="test2">W</span> <span id="test3">W</span></div>
<div><span id="test4">W</span> <span id="test5">W</span> <span id="test6">W</span></div>
<div><span id="test7">W</span> <span id="test8">W</span> <span id="test9">W</span></div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,71 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Annotations test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
body {
margin: 20px;
font-size: 800%;
font-family: Hiragino Maru Gothic ProN, Meiryo;
}
/* for platforms without these fonts the default glyphs will show */
@font-face {
font-family: testMeiryo-circled;
src: local(Meiryo);
-moz-font-feature-settings: "nalt" 4;
}
@font-face {
font-family: testMeiryo-black-circled;
src: local(Meiryo);
-moz-font-feature-settings: "nalt" 5;
}
@font-face {
font-family: testMeiryo-rounded-box;
src: local(Meiryo);
-moz-font-feature-settings: "nalt" 9;
}
@font-face {
font-family: testHiraginoMaru-circled;
src: local(HiraMaruProN-W4), local(Hiragino Maru Gothic ProN W4);
-moz-font-feature-settings: "nalt" 1;
}
@font-face {
font-family: testHiraginoMaru-black-circled;
src: local(HiraMaruProN-W4), local(Hiragino Maru Gothic ProN W4);
-moz-font-feature-settings: "nalt" 4;
}
@font-face {
font-family: testHiraginoMaru-rounded-box;
src: local(HiraMaruProN-W4), local(Hiragino Maru Gothic ProN W4);
-moz-font-feature-settings: "nalt" 10;
}
#test1 {
font-family: testHiraginoMaru-circled, testMeiryo-circled;
}
#test2 {
font-family: testHiraginoMaru-black-circled, testMeiryo-black-circled;
}
#test3 {
font-family: testHiraginoMaru-rounded-box, testMeiryo-rounded-box;
}
</style>
</head>
<body>
<div><span id="test1">1</span> <span id="test2">2</span> <span id="test3">3</span></div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,51 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Annotations test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
body {
margin: 20px;
font-size: 800%;
font-family: Hiragino Maru Gothic ProN, Meiryo;
}
/* for platforms without these fonts the default glyphs will show */
@font-feature-values Hiragino Maru Gothic ProN {
@annotation { circled: 1; }
@annotation { black-circled: 4; }
@annotation { black-box: 8; }
@annotation { black-rounded-box: 10; }
}
@font-feature-values Meiryo {
@annotation {
circled: 4;
black-circled: 5;
black-box: 7;
black-rounded-box: 9;
}
}
#test1 {
font-variant-alternates: annotation(circled);
}
#test2 {
font-variant-alternates: annotation(black-circled);
}
#test3 {
font-variant-alternates: annotation(black-rounded-box);
}
</style>
</head>
<body>
<div><span id="test1">1</span> <span id="test2">2</span> <span id="test3">3</span></div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
@font-face {
font-family: libertine;
src: url(../fonts/LinLibertine_Re-4.7.5.woff) format("woff");
-moz-font-feature-settings: "liga" on, "hlig" on;
}
body {
font-family: libertine, sans-serif;
font-size: 400%;
line-height: 2em;
/* font feature settings property should override font setting */
-moz-font-feature-settings: "liga" off, "hlig" off;
}
</style>
</head>
<body lang="en">
fastest firefox
</body>
</html>

Просмотреть файл

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
@font-face {
font-family: libertine;
src: url(../fonts/LinLibertine_Re-4.7.5.woff) format("woff");
font-feature-settings: "liga" on, "hlig" on;
}
body {
font-family: libertine, sans-serif;
font-size: 400%;
line-height: 2em;
/* font variant property should override font setting */
font-variant-ligatures: no-common-ligatures no-historical-ligatures;
}
</style>
</head>
<body lang="en">
fastest firefox
</body>
</html>

Просмотреть файл

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
@font-face {
font-family: libertine;
src: url(../fonts/LinLibertine_Re-4.7.5.woff) format("woff");
font-feature-settings: "liga" on, "hlig" on;
}
body {
font-family: libertine, sans-serif;
font-size: 400%;
line-height: 2em;
/* font variant property should override font setting but font feature
settings property should override that */
font-variant-ligatures: no-common-ligatures no-historical-ligatures;
font-feature-settings: "liga" on, "hlig" on;
}
</style>
</head>
<body lang="en">
fastest firefox
</body>
</html>

Просмотреть файл

@ -0,0 +1,26 @@
<!DOCTYPE HTML>
<html>
<head>
<style type="text/css">
@font-face {
font-family: libertine;
src: url(../fonts/LinLibertine_Re-4.7.5.woff) format("woff");
}
body {
margin: 10px;
font-family: libertine, sans-serif;
font-size: 600%;
line-height: 1.2em;
/* font-feature-settings should take precedence over font-kerning,
so kerning should be DISabled here */
font-feature-settings: "kern" off;
font-kerning: normal;
}
</style>
</head>
<body lang="en">
<div>Ta To</div>
<div>AVA</div>
<div>AWAY</div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,26 @@
<!DOCTYPE HTML>
<html>
<head>
<style type="text/css">
@font-face {
font-family: libertine;
src: url(../fonts/LinLibertine_Re-4.7.5.woff) format("woff");
}
body {
margin: 10px;
font-family: libertine, sans-serif;
font-size: 600%;
line-height: 1.2em;
/* font-feature-settings should take precedence over font-kerning,
so kerning should be ENabled here. */
font-feature-settings: "kern" on;
font-kerning: none;
}
</style>
</head>
<body lang="en">
<div>Ta To</div>
<div>AVA</div>
<div>AWAY</div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,23 @@
<!DOCTYPE HTML>
<html>
<head>
<style type="text/css">
@font-face {
font-family: libertine;
src: url(../fonts/LinLibertine_Re-4.7.5.woff) format("woff");
font-feature-settings: "kern" off;
}
body {
margin: 10px;
font-family: libertine, sans-serif;
font-size: 600%;
line-height: 1.2em;
}
</style>
</head>
<body lang="en">
<div>Ta To</div>
<div>AVA</div>
<div>AWAY</div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,23 @@
<!DOCTYPE HTML>
<html>
<head>
<style type="text/css">
@font-face {
font-family: libertine;
src: url(../fonts/LinLibertine_Re-4.7.5.woff) format("woff");
}
body {
margin: 10px;
font-family: libertine, sans-serif;
font-size: 600%;
line-height: 1.2em;
font-kerning: auto;
}
</style>
</head>
<body lang="en">
<div>Ta To</div>
<div>AVA</div>
<div>AWAY</div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,23 @@
<!DOCTYPE HTML>
<html>
<head>
<style type="text/css">
@font-face {
font-family: libertine;
src: url(../fonts/LinLibertine_Re-4.7.5.woff) format("woff");
}
body {
margin: 10px;
font-family: libertine, sans-serif;
font-size: 600%;
line-height: 1.2em;
font-feature-settings: "kern" on;
}
</style>
</head>
<body lang="en">
<div>Ta To</div>
<div>AVA</div>
<div>AWAY</div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,23 @@
<!DOCTYPE HTML>
<html>
<head>
<style type="text/css">
@font-face {
font-family: libertine;
src: url(../fonts/LinLibertine_Re-4.7.5.woff) format("woff");
}
body {
margin: 10px;
font-family: libertine, sans-serif;
font-size: 600%;
line-height: 1.2em;
font-feature-settings: "kern" off;
}
</style>
</head>
<body lang="en">
<div>Ta To</div>
<div>AVA</div>
<div>AWAY</div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,23 @@
<!DOCTYPE HTML>
<html>
<head>
<style type="text/css">
@font-face {
font-family: libertine;
src: url(../fonts/LinLibertine_Re-4.7.5.woff) format("woff");
}
body {
margin: 10px;
font-family: libertine, sans-serif;
font-size: 600%;
line-height: 1.2em;
font-kerning: none;
}
</style>
</head>
<body lang="en">
<div>Ta To</div>
<div>AVA</div>
<div>AWAY</div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,23 @@
<!DOCTYPE HTML>
<html>
<head>
<style type="text/css">
@font-face {
font-family: libertine;
src: url(../fonts/LinLibertine_Re-4.7.5.woff) format("woff");
}
body {
margin: 10px;
font-family: libertine, sans-serif;
font-size: 600%;
line-height: 1.2em;
font-kerning: normal;
}
</style>
</head>
<body lang="en">
<div>Ta To</div>
<div>AVA</div>
<div>AWAY</div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,24 @@
<!DOCTYPE HTML>
<html>
<head>
<style type="text/css">
@font-face {
font-family: gentium;
/* font that has an old-style 'kern' table rather than GPOS 'kern' feature */
src: url(../fonts/sil/GenR102.ttf);
}
body {
margin: 10px;
font-family: gentium;
font-size: 600%;
line-height: 1.2em;
font-kerning: none;
}
</style>
</head>
<body lang="en">
<div>Ta To</div>
<div>AVA</div>
<div>AWAY</div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,23 @@
<!DOCTYPE HTML>
<html>
<head>
<style type="text/css">
@font-face {
font-family: gentium;
src: url(../fonts/sil/GenR102.ttf);
}
body {
margin: 10px;
font-family: gentium;
font-size: 600%;
line-height: 1.2em;
font-kerning: normal;
}
</style>
</head>
<body lang="en">
<div>Ta To</div>
<div>AVA</div>
<div>AWAY</div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,20 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<title>font-variant-alternates test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="../fonts/gsubtest/gsubtest-features.js"></script>
<script type="text/javascript" src="font-variant-features.js"></script>
<link rel="stylesheet" href="font-variant-features.css" type="text/css"/>
<style type="text/css">
</style>
</head>
<body>
<div id="content"></div>
<script type="text/javascript">
document.getElementById("content").appendChild(createFeatureTestTable(gPropertyData, "font-variant-alternates", true, false));
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,20 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<title>font-variant-alternates test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="../fonts/gsubtest/gsubtest-features.js"></script>
<script type="text/javascript" src="font-variant-features.js"></script>
<link rel="stylesheet" href="font-variant-features.css" type="text/css"/>
<style type="text/css">
</style>
</head>
<body>
<div id="content"></div>
<script type="text/javascript">
document.getElementById("content").appendChild(createFeatureTestTable(gPropertyData, "font-variant-alternates", false, false));
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,16 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<title>font-variant-caps test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="../fonts/gsubtest/gsubtest-features.js"></script>
<script type="text/javascript" src="font-variant-features.js"></script>
<link rel="stylesheet" href="font-variant-features.css" type="text/css"/>
</head>
<body>
<div id="content"></div>
<script type="text/javascript">
document.getElementById("content").appendChild(createFeatureTestTable(gPropertyData, "font-variant-caps", true, false));
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,16 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<title>font-variant-caps test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="../fonts/gsubtest/gsubtest-features.js"></script>
<script type="text/javascript" src="font-variant-features.js"></script>
<link rel="stylesheet" href="font-variant-features.css" type="text/css"/>
</head>
<body>
<div id="content"></div>
<script type="text/javascript">
document.getElementById("content").appendChild(createFeatureTestTable(gPropertyData, "font-variant-caps", false, false));
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,16 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<title>font-variant test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="../fonts/gsubtest/gsubtest-features.js"></script>
<script type="text/javascript" src="font-variant-features.js"></script>
<link rel="stylesheet" href="font-variant-features.css" type="text/css"/>
</head>
<body>
<div id="content"></div>
<script type="text/javascript">
document.getElementById("content").appendChild(createFeatureTestTable(gPropertyData, "all", false, true));
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,16 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<title>font-variant-east-asian test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="../fonts/gsubtest/gsubtest-features.js"></script>
<script type="text/javascript" src="font-variant-features.js"></script>
<link rel="stylesheet" href="font-variant-features.css" type="text/css"/>
</head>
<body>
<div id="content"></div>
<script type="text/javascript">
document.getElementById("content").appendChild(createFeatureTestTable(gPropertyData, "font-variant-east-asian", true, false));
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,16 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<title>font-variant-east-asian test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="../fonts/gsubtest/gsubtest-features.js"></script>
<script type="text/javascript" src="font-variant-features.js"></script>
<link rel="stylesheet" href="font-variant-features.css" type="text/css"/>
</head>
<body>
<div id="content"></div>
<script type="text/javascript">
document.getElementById("content").appendChild(createFeatureTestTable(gPropertyData, "font-variant-east-asian", false, false));
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,63 @@
body { margin: 10px; }
@font-face {
font-family: gsub-test;
src: url(../fonts/gsubtest/gsubtest-lookup3.otf);
}
td.prop {
font-family: Menlo, monospace;
font-weight: normal;
text-align: left;
font-size: 80%;
}
td.features {
font-family: gsub-test;
}
.invalid {
color: red;
}
@font-feature-values gsub-test {
@styleset { ok-alt-a: 1 3 5; ok-alt-b: 19; }
@character-variant { ok-1: 78 2; }
@character-variant { ok-3: 23; }
@character-variant { not-good: 0 2; }
@annotation { ok-4: 1; }
@annotation { bogus-font-doesnt-support: 23; }
@annotation { circled: 1; }
@character-variant { multi-def: 4; }
@annotation { multi-def: 3; }
@styleset { multi-def2: 3 4 5; }
@styleset { MULTI-def2: 2 6; }
@styleset { out-of-bounds1: 0; out-of-bounds2: 100; }
}
@font-feature-values bogus-family {
@styleset { bogus: 3 4 7; }
}
@font-feature-values GSUB-tEsT {
@styleset { mixed-case: 3 4 7; }
}
@font-feature-values gSuB-tEsT {
@styleset { 3blah: 1 3; }
}
@font-feature-values gSuB-tEsT {
@styleset { moxie: 14; }
@styleset { 3blah: 1; }
}
@font-feature-values gSUB-TeST {
@styleset { moxie2: 14; }
@bongo { blah: 1; }
}
@font-feature-values gSUB-TEst {
@bongo { blah2: 1; }
@styleset { moxie3: 14; }
}

Просмотреть файл

@ -0,0 +1,220 @@
// data associated with gsubtest test font for testing font features
// prefix
gPrefix = "";
// equivalent properties
// setting prop: value should match the specific feature settings listed
//
// each of these tests evaluate whether a given feature is enabled as required
// and also whether features that shouldn't be enabled are or not.
var gPropertyData = [
// font-variant-caps
// valid values
{ prop: "font-variant-caps", value: "normal", features: {"smcp": 0} },
{ prop: "font-variant-caps", value: "small-caps", features: {"smcp": 1, "c2sc": 0} },
{ prop: "font-variant-caps", value: "all-small-caps", features: {"smcp": 1, "c2sc": 1, "pcap": 0} },
{ prop: "font-variant-caps", value: "petite-caps", features: {"pcap": 1, "smcp": 0} },
{ prop: "font-variant-caps", value: "all-petite-caps", features: {"c2pc": 1, "pcap": 1, "smcp": 0} },
{ prop: "font-variant-caps", value: "titling-caps", features: {"titl": 1, "smcp": 0} },
{ prop: "font-variant-caps", value: "unicase", features: {"unic": 1, "titl": 0} },
// invalid values
{ prop: "font-variant-caps", value: "normal small-caps", features: {"smcp": 0}, invalid: true },
{ prop: "font-variant-caps", value: "small-caps potato", features: {"smcp": 0}, invalid: true },
{ prop: "font-variant-caps", value: "small-caps petite-caps", features: {"smcp": 0, "pcap": 0}, invalid: true },
{ prop: "font-variant-caps", value: "small-caps all-small-caps", features: {"smcp": 0, "c2sc": 0}, invalid: true },
{ prop: "font-variant-caps", value: "small-cap", features: {"smcp": 0}, invalid: true },
// font-variant-east-asian
// valid values
{ prop: "font-variant-east-asian", value: "jis78", features: {"jp78": 1, "jp04": 0} },
{ prop: "font-variant-east-asian", value: "jis83", features: {"jp83": 1, "jp04": 0} },
{ prop: "font-variant-east-asian", value: "jis90", features: {"jp90": 1, "jp04": 0} },
{ prop: "font-variant-east-asian", value: "jis04", features: {"jp04": 1, "jp78": 0} },
{ prop: "font-variant-east-asian", value: "simplified", features: {"smpl": 1, "jp04": 0} },
{ prop: "font-variant-east-asian", value: "traditional", features: {"trad": 1, "jp04": 0} },
{ prop: "font-variant-east-asian", value: "full-width", features: {"fwid": 1, "jp04": 0} },
{ prop: "font-variant-east-asian", value: "proportional-width", features: {"pwid": 1, "jp04": 0} },
{ prop: "font-variant-east-asian", value: "ruby", features: {"ruby": 1, "jp04": 0} },
{ prop: "font-variant-east-asian", value: "jis78 full-width", features: {"jp78": 1, "fwid": 1, "jp83": 0} },
{ prop: "font-variant-east-asian", value: "jis78 full-width ruby", features: {"jp78": 1, "fwid": 1, "jp83": 0, "ruby": 1} },
{ prop: "font-variant-east-asian", value: "simplified proportional-width", features: {"smpl": 1, "pwid": 1, "jp83": 0} },
{ prop: "font-variant-east-asian", value: "ruby simplified", features: {"ruby": 1, "smpl": 1, "trad": 0} },
// invalid values
{ prop: "font-variant-east-asian", value: "ruby normal", features: {"ruby": 0}, invalid: true },
{ prop: "font-variant-east-asian", value: "jis90 jis04", features: {"jp90": 0, "jp04": 0}, invalid: true },
{ prop: "font-variant-east-asian", value: "simplified traditional", features: {"smpl": 0, "trad": 0}, invalid: true },
{ prop: "font-variant-east-asian", value: "full-width proportional-width", features: {"fwid": 0, "pwid": 0}, invalid: true },
{ prop: "font-variant-east-asian", value: "ruby simplified ruby", features: {"ruby": 0, "smpl": 0, "jp04": 0}, invalid: true },
{ prop: "font-variant-east-asian", value: "jis78 ruby simplified", features: {"ruby": 0, "smpl": 0, "jp78": 0}, invalid: true },
// font-variant-ligatures
// valid values
{ prop: "font-variant-ligatures", value: "normal", features: {"liga": 1, "dlig": 0} },
{ prop: "font-variant-ligatures", value: "common-ligatures", features: {"liga": 1, "clig": 1, "dlig": 0, "hlig": 0, "calt": 1} },
{ prop: "font-variant-ligatures", value: "no-common-ligatures", features: {"liga": 0, "clig": 0, "dlig": 0, "hlig": 0, "calt": 1} },
{ prop: "font-variant-ligatures", value: "discretionary-ligatures", features: {"liga": 1, "clig": 1, "dlig": 1, "hlig": 0, "calt": 1} },
{ prop: "font-variant-ligatures", value: "no-discretionary-ligatures", features: {"liga": 1, "clig": 1, "dlig": 0, "hlig": 0, "calt": 1} },
{ prop: "font-variant-ligatures", value: "historical-ligatures", features: {"liga": 1, "clig": 1, "dlig": 0, "hlig": 1, "calt": 1} },
{ prop: "font-variant-ligatures", value: "no-historical-ligatures", features: {"liga": 1, "clig": 1, "dlig": 0, "hlig": 0, "calt": 1} },
{ prop: "font-variant-ligatures", value: "contextual", features: {"liga": 1, "clig": 1, "dlig": 0, "hlig": 0, "calt": 1} },
{ prop: "font-variant-ligatures", value: "no-contextual", features: {"liga": 1, "clig": 1, "dlig": 0, "hlig": 0, "calt": 0} },
{ prop: "font-variant-ligatures", value: "common-ligatures no-discretionary-ligatures", features: {"liga": 1, "clig": 1, "dlig": 0, "hlig": 0, "calt": 1} },
{ prop: "font-variant-ligatures", value: "historical-ligatures no-common-ligatures", features: {"clig": 0, "liga": 0, "dlig": 0, "hlig": 1, "calt": 1} },
{ prop: "font-variant-ligatures", value: "no-historical-ligatures discretionary-ligatures", features: {"liga": 1, "clig": 1, "dlig": 1, "hlig": 0, "calt": 1} },
{ prop: "font-variant-ligatures", value: "common-ligatures no-discretionary-ligatures historical-ligatures no-contextual", features: {"clig": 1, "dlig": 0, "hlig": 1, "liga": 1, "calt": 0} },
// invalid values
{ prop: "font-variant-ligatures", value: "common-ligatures normal", features: {"liga": 1, "clig": 1, "dlig": 0}, invalid: true },
{ prop: "font-variant-ligatures", value: "common-ligatures no-common-ligatures", features: {"liga": 1, "clig": 1, "dlig": 0}, invalid: true },
{ prop: "font-variant-ligatures", value: "common-ligatures common-ligatures", features: {"liga": 1, "clig": 1, "dlig": 0}, invalid: true },
{ prop: "font-variant-ligatures", value: "no-historical-ligatures historical-ligatures", features: {"liga": 1, "clig": 1, "dlig": 0, "hlig": 0}, invalid: true },
{ prop: "font-variant-ligatures", value: "no-contextual contextual", features: {"liga": 1, "clig": 1, "dlig": 0, "hlig": 0}, invalid: true },
{ prop: "font-variant-ligatures", value: "no-discretionary-ligatures discretionary-ligatures", features: {"liga": 1, "clig": 1, "dlig": 0}, invalid: true },
{ prop: "font-variant-ligatures", value: "common-ligatures no-discretionary-ligatures no-common-ligatures", features: {"liga": 1, "clig": 1, "dlig": 0}, invalid: true },
// font-variant-numeric
// valid values
{ prop: "font-variant-numeric", value: "normal", features: {"lnum": 0, "tnum": 0, "pnum": 0, "onum": 0} },
{ prop: "font-variant-numeric", value: "lining-nums", features: {"lnum": 1, "onum": 0, "pnum": 0} },
{ prop: "font-variant-numeric", value: "oldstyle-nums", features: {"lnum": 0, "onum": 1, "pnum": 0} },
{ prop: "font-variant-numeric", value: "proportional-nums", features: {"lnum": 0, "onum": 0, "pnum": 1, "tnum": 0} },
{ prop: "font-variant-numeric", value: "proportional-nums oldstyle-nums", features: {"lnum": 0, "onum": 1, "pnum": 1, "tnum": 0} },
{ prop: "font-variant-numeric", value: "tabular-nums", features: {"tnum": 1, "onum": 0, "pnum": 0} },
{ prop: "font-variant-numeric", value: "diagonal-fractions", features: {"frac": 1, "afrc": 0, "pnum": 0} },
{ prop: "font-variant-numeric", value: "stacked-fractions", features: {"frac": 0, "afrc": 1, "pnum": 0} },
{ prop: "font-variant-numeric", value: "slashed-zero", features: {"zero": 1, "pnum": 0} },
{ prop: "font-variant-numeric", value: "ordinal", features: {"ordn": 1, "pnum": 0} },
{ prop: "font-variant-numeric", value: "lining-nums diagonal-fractions", features: {"frac": 1, "afrc": 0, "lnum": 1} },
{ prop: "font-variant-numeric", value: "tabular-nums stacked-fractions", features: {"frac": 0, "afrc": 1, "tnum": 1} },
{ prop: "font-variant-numeric", value: "tabular-nums slashed-zero stacked-fractions", features: {"frac": 0, "afrc": 1, "tnum": 1, "zero": 1} },
{ prop: "font-variant-numeric", value: "proportional-nums slashed-zero diagonal-fractions oldstyle-nums ordinal", features: {"frac": 1, "afrc": 0, "tnum": 0, "pnum": 1, "onum": 1, "ordn": 1, "zero": 1} },
// invalid values
{ prop: "font-variant-numeric", value: "lining-nums normal", features: {"lnum": 0, "onum": 0}, invalid: true },
{ prop: "font-variant-numeric", value: "lining-nums oldstyle-nums", features: {"lnum": 0, "onum": 0}, invalid: true },
{ prop: "font-variant-numeric", value: "lining-nums normal slashed-zero ordinal", features: {"lnum": 0, "onum": 0, "zero": 0}, invalid: true },
{ prop: "font-variant-numeric", value: "proportional-nums tabular-nums", features: {"pnum": 0, "tnum": 0}, invalid: true },
{ prop: "font-variant-numeric", value: "diagonal-fractions stacked-fractions", features: {"frac": 0, "afrc": 0}, invalid: true },
{ prop: "font-variant-numeric", value: "slashed-zero diagonal-fractions slashed-zero", features: {"frac": 0, "afrc": 0, "zero": 0}, invalid: true },
{ prop: "font-variant-numeric", value: "lining-nums slashed-zero diagonal-fractions oldstyle-nums", features: {"frac": 0, "afrc": 0, "zero": 0, "onum": 0}, invalid: true },
// font-variant-position
// valid values
{ prop: "font-variant-position", value: "normal", features: {"subs": 0, "sups": 0} },
{ prop: "font-variant-position", value: "super", features: {"subs": 0, "sups": 1} },
{ prop: "font-variant-position", value: "sub", features: {"subs": 1, "sups": 0} },
// invalid values
{ prop: "font-variant-position", value: "super sub", features: {"subs": 0, "sups": 0}, invalid: true },
];
// note: the code below requires an array "gFeatures" from :
// layout/reftests/fonts/gsubtest/gsubtest-features.js
// The font defines feature lookups for all OpenType features for a
// specific set of PUA codepoints, as listed in the gFeatures array.
// Using these codepoints and feature combinations, tests can be
// constructed to detect when certain features are enabled or not.
// return a created table containing tests for a given property
//
// Ex: { prop: "font-variant-ligatures", value: "common-ligatures", features: {"liga": 1, "clig": 1, "dlig": 0, "hlig": 0} }
//
// This means that for the property 'font-variant-ligatures' with the value 'common-ligatures', the features listed should
// either be explicitly enabled or disabled.
// propData is the prop/value list with corresponding feature assertions
// whichProp is either "all" or a specific subproperty (i.e. "font-variant-position")
// isRef is true when this is the reference
// debug outputs the prop/value pair along with the tests
function createFeatureTestTable(propData, whichProp, isRef, debug)
{
var table = document.createElement("table");
if (typeof(isRef) == "undefined") {
isRef = false;
}
if (typeof(debug) == "undefined") {
debug = false;
}
var doAll = (whichProp == "all");
for (var i in propData) {
var data = propData[i];
if (!doAll && data.prop != whichProp) continue;
var row = document.createElement("tr");
var invalid = false;
if ("invalid" in data) {
invalid = true;
row.className = "invalid";
}
var cell = document.createElement("td");
cell.className = "prop";
var styledecl = gPrefix + data.prop + ": " + data.value + ";";
cell.innerHTML = styledecl;
row.appendChild(cell);
if (debug) {
table.appendChild(row);
}
row = document.createElement("tr");
if (invalid) {
row.className = "invalid";
}
cell = document.createElement("td");
cell.className = "features";
if (!isRef) {
cell.style.cssText = styledecl;
}
for (var f in data.features) {
var feature = data.features[f];
var cp, unsupported = "F".charCodeAt(0);
var basecp = gFeatures[f];
if (typeof(basecp) == "undefined") {
cp = unsupported;
} else {
switch(feature) {
case 0:
cp = basecp;
break;
case 1:
cp = basecp + 1;
break;
case 2:
cp = basecp + 2;
break;
case 3:
cp = basecp + 3;
break;
default:
cp = basecp + 1;
break;
}
}
var span = document.createElement("span");
span.innerHTML = (isRef ? "P " : "&#x" + cp.toString(16) + "; ");
span.title = f + "=" + feature;
cell.appendChild(span);
}
row.appendChild(cell);
table.appendChild(row);
}
return table;
}

Просмотреть файл

@ -0,0 +1,16 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<title>font-variant-ligatures test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="../fonts/gsubtest/gsubtest-features.js"></script>
<script type="text/javascript" src="font-variant-features.js"></script>
<link rel="stylesheet" href="font-variant-features.css" type="text/css"/>
</head>
<body>
<div id="content"></div>
<script type="text/javascript">
document.getElementById("content").appendChild(createFeatureTestTable(gPropertyData, "font-variant-ligatures", true, false));
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,16 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<title>font-variant-ligatures test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="../fonts/gsubtest/gsubtest-features.js"></script>
<script type="text/javascript" src="font-variant-features.js"></script>
<link rel="stylesheet" href="font-variant-features.css" type="text/css"/>
</head>
<body>
<div id="content"></div>
<script type="text/javascript">
document.getElementById("content").appendChild(createFeatureTestTable(gPropertyData, "font-variant-ligatures", false, false));
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,16 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<title>font-variant-numeric test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="../fonts/gsubtest/gsubtest-features.js"></script>
<script type="text/javascript" src="font-variant-features.js"></script>
<link rel="stylesheet" href="font-variant-features.css" type="text/css"/>
</head>
<body>
<div id="content"></div>
<script type="text/javascript">
document.getElementById("content").appendChild(createFeatureTestTable(gPropertyData, "font-variant-numeric", true, false));
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,16 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<title>font-variant-numeric test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="../fonts/gsubtest/gsubtest-features.js"></script>
<script type="text/javascript" src="font-variant-features.js"></script>
<link rel="stylesheet" href="font-variant-features.css" type="text/css"/>
</head>
<body>
<div id="content"></div>
<script type="text/javascript">
document.getElementById("content").appendChild(createFeatureTestTable(gPropertyData, "font-variant-numeric", false, false));
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,16 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<title>font-variant-position test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="../fonts/gsubtest/gsubtest-features.js"></script>
<script type="text/javascript" src="font-variant-features.js"></script>
<link rel="stylesheet" href="font-variant-features.css" type="text/css"/>
</head>
<body>
<div id="content"></div>
<script type="text/javascript">
document.getElementById("content").appendChild(createFeatureTestTable(gPropertyData, "font-variant-position", true, false));
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,16 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<title>font-variant-position test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="../fonts/gsubtest/gsubtest-features.js"></script>
<script type="text/javascript" src="font-variant-features.js"></script>
<link rel="stylesheet" href="font-variant-features.css" type="text/css"/>
</head>
<body>
<div id="content"></div>
<script type="text/javascript">
document.getElementById("content").appendChild(createFeatureTestTable(gPropertyData, "font-variant-position", false, false));
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,356 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset=utf-8>
<title>@font-feature-values rule parsing tests</title>
<link rel="author" title="John Daggett" href="mailto:jdaggett@mozilla.com">
<link rel="help" href="http://www.w3.org/TR/css3-fonts/#font-feature-values" />
<meta name="assert" content="tests that valid @font-feature-values rules parse and invalid ones don't" />
<!-- https://bugzilla.mozilla.org/show_bug.cgi?id=549861 -->
<script type="text/javascript" src="/resources/testharness.js"></script>
<script type="text/javascript" src="/resources/testharnessreport.js"></script>
<style type="text/css">
</style>
</head>
<body>
<div id="log"></div>
<pre id="display"></pre>
<style type="text/css" id="testbox"></style>
<script type="text/javascript">
var gPrefix = "";
var kFontFeatureValuesRuleType = 14;
function ruleName() { return "@" + gPrefix + "font-feature-values"; }
function makeRule(f, v) {
return ruleName() + " " + f + " { " + v + " }";
}
function _()
{
var i, decl = [];
for (i = 0; i < arguments.length; i++) {
decl.push(arguments[i]);
}
return makeRule("bongo", decl.join(" "));
}
// note: because of bugs in the way family names are serialized,
// 'serializationSame' only implies that the value definition block
// is the same (i.e. not including the family name list)
var testrules = [
/* basic syntax */
{ rule: ruleName() + ";", invalid: true },
{ rule: ruleName() + " bongo;", invalid: true },
{ rule: ruleName().replace("values", "value") + " {;}", invalid: true },
{ rule: ruleName().replace("feature", "features") + " {;}", invalid: true },
{ rule: makeRule("bongo", ""), serializationNoValueDefn: true },
{ rule: makeRule("bongo", ";"), serializationNoValueDefn: true },
{ rule: makeRule("bongo", ",;"), serializationNoValueDefn: true },
{ rule: makeRule("bongo", ";,"), serializationNoValueDefn: true },
{ rule: makeRule("bongo", ",;,"), serializationNoValueDefn: true },
{ rule: makeRule("bongo", "@styleset;"), serializationNoValueDefn: true },
{ rule: makeRule("bongo", "@styleset,;"), serializationNoValueDefn: true },
{ rule: makeRule("bongo", "@styleset abc;"), serializationNoValueDefn: true },
{ rule: makeRule("bongo", "@styleset { abc }"), serializationNoValueDefn: true },
{ rule: makeRule("bongo", "@styleset { ;;abc }"), serializationNoValueDefn: true },
{ rule: makeRule("bongo", "@styleset { abc;; }"), serializationNoValueDefn: true },
{ rule: makeRule("bongo", "@styleset { abc: }"), serializationNoValueDefn: true },
{ rule: makeRule("bongo", "@styleset { abc,: }"), serializationNoValueDefn: true },
{ rule: makeRule("bongo", "@styleset { abc:, }"), serializationNoValueDefn: true },
{ rule: makeRule("bongo", "@styleset { abc:,; }"), serializationNoValueDefn: true },
{ rule: makeRule("bongo", "@styleset { a,b }"), serializationNoValueDefn: true },
{ rule: makeRule("bongo", "@styleset { a;b }"), serializationNoValueDefn: true },
{ rule: makeRule("bongo", "@styleset { a:;b: }"), serializationNoValueDefn: true },
{ rule: makeRule("bongo", "@styleset { a:,;b: }"), serializationNoValueDefn: true },
{ rule: makeRule("bongo", "@styleset { a:1,;b: }"), serializationNoValueDefn: true },
{ rule: makeRule("bongo", "@styleset { abc 1 2 3 }"), serializationNoValueDefn: true },
{ rule: makeRule("bongo", "@styleset { abc:, 1 2 3 }"), serializationNoValueDefn: true },
{ rule: makeRule("bongo", "@styleset { abc:; 1 2 3 }"), serializationNoValueDefn: true },
{ rule: makeRule("bongo", "@styleset { abc:; 1 2 3 }"), serializationNoValueDefn: true },
{ rule: makeRule("bongo", "@styleset { abc: 1 2 3a }"), serializationNoValueDefn: true },
{ rule: makeRule("bongo", "@styleset { abc: 1 2 3, def: 1; }"), serializationNoValueDefn: true },
{ rule: makeRule("bongo", "@blah @styleset { abc: 1 2 3; }"), serializationNoValueDefn: true },
{ rule: makeRule("bongo", "@blah } @styleset { abc: 1 2 3; }"), serializationNoValueDefn: true },
{ rule: makeRule("bongo", "@blah , @styleset { abc: 1 2 3; }"), serializationNoValueDefn: true },
{ rule: ruleName() + " bongo { @styleset { abc: 1 2 3; }", serialization: _("@styleset { abc: 1 2 3; }") },
{ rule: ruleName() + " bongo { @styleset { abc: 1 2 3 }", serialization: _("@styleset { abc: 1 2 3; }") },
{ rule: ruleName() + " bongo { @styleset { abc: 1 2 3;", serialization: _("@styleset { abc: 1 2 3; }") },
{ rule: ruleName() + " bongo { @styleset { abc: 1 2 3", serialization: _("@styleset { abc: 1 2 3; }") },
{ rule: _("@styleset { ok-1: 1; }"), serializationSame: true },
{ rule: _("@annotation { ok-1: 3; }"), serializationSame: true },
{ rule: _("@stylistic { blah: 3; }"), serializationSame: true },
{ rule: makeRule("bongo", "\n@styleset\n { blah: 3; super-blah: 4 5;\n more-blah: 5 6 7;\n }"), serializationSame: true },
{ rule: makeRule("bongo", "\n@styleset\n {\n blah:\n 3\n;\n super-blah:\n 4\n 5\n;\n more-blah:\n 5 6\n 7;\n }"), serializationSame: true },
/* limits on number of values */
{ rule: _("@stylistic { blah: 1; }"), serializationSame: true },
{ rule: _("@styleset { blah: 1 2 3 4; }"), serializationSame: true },
{ rule: _("@character-variant { blah: 1 2; }"), serializationSame: true },
{ rule: _("@swash { blah: 1; }"), serializationSame: true },
{ rule: _("@ornaments { blah: 1; }"), serializationSame: true },
{ rule: _("@annotation { blah: 1; }"), serializationSame: true },
/* values ignored when used */
{ rule: _("@styleset { blah: 0; }"), serializationSame: true },
{ rule: _("@styleset { blah: 120 124; }"), serializationSame: true },
{ rule: _("@character-variant { blah: 0; }"), serializationSame: true },
{ rule: _("@character-variant { blah: 111; }"), serializationSame: true },
{ rule: _("@character-variant { blah: 111 13; }"), serializationSame: true },
/* invalid value name */
{ rulesrc: ["styleset { blah: 1 }"], serializationNoValueDefn: true },
{ rulesrc: ["stylistic { blah: 1 }"], serializationNoValueDefn: true },
{ rulesrc: ["character-variant { blah: 1 }"], serializationNoValueDefn: true },
{ rulesrc: ["swash { blah: 1 }"], serializationNoValueDefn: true },
{ rulesrc: ["ornaments { blah: 1 }"], serializationNoValueDefn: true },
{ rulesrc: ["annotation { blah: 1 }"], serializationNoValueDefn: true },
{ rulesrc: ["@bongo { blah: 1 }"], serializationNoValueDefn: true },
{ rulesrc: ["@bongo { blah: 1 2 3 }"], serializationNoValueDefn: true },
{ rulesrc: ["@bongo { blah: 1 2 3; burp: 1;;; }"], serializationNoValueDefn: true },
/* values */
{ rulesrc: ["@styleset { blah: -1 }"], serializationNoValueDefn: true },
{ rulesrc: ["@styleset { blah: 1 -1 }"], serializationNoValueDefn: true },
{ rulesrc: ["@styleset { blah: 1.5 }"], serializationNoValueDefn: true },
{ rulesrc: ["@styleset { blah: 15px }"], serializationNoValueDefn: true },
{ rulesrc: ["@styleset { blah: red }"], serializationNoValueDefn: true },
{ rulesrc: ["@styleset { blah: (1) }"], serializationNoValueDefn: true },
{ rulesrc: ["@styleset { blah:(1) }"], serializationNoValueDefn: true },
{ rulesrc: ["@styleset { blah:, 1 }"], serializationNoValueDefn: true },
{ rulesrc: ["@styleset { blah: <1> }"], serializationNoValueDefn: true },
{ rulesrc: ["@styleset { blah: 1! }"], serializationNoValueDefn: true },
{ rulesrc: ["@styleset { blah: 1,, }"], serializationNoValueDefn: true },
{ rulesrc: ["@styleset { blah: 1 1 1 1; }"], serializationSame: true },
/* limits on number of values */
{ rulesrc: ["@stylistic { blah: 1 2 }"], serializationNoValueDefn: true },
{ rulesrc: ["@character-variant { blah: 1 2 3 }"], serializationNoValueDefn: true },
{ rulesrc: ["@swash { blah: 1 2 }"], serializationNoValueDefn: true },
{ rulesrc: ["@ornaments { blah: 1 2 }"], serializationNoValueDefn: true },
{ rulesrc: ["@annotation { blah: 1 2 }"], serializationNoValueDefn: true },
{ rulesrc: ["@styleset { blah: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19; }"], serializationSame: true },
/* family names */
{ rule: makeRule("bongo", "@styleset { blah: 1; }"), serializationSame: true },
{ rule: makeRule("\"bongo\"", "@styleset { blah: 1; }"), serializationSame: true },
{ rule: makeRule("'bongo'", "@styleset { blah: 1; }"), serializationSame: true },
{ rule: makeRule("\\62 ongo", "@styleset { blah: 1; }"), serializationSame: true },
{ rule: makeRule("bongo, super bongo, bongo the supreme", "@styleset { blah: 1; }"), serializationSame: true },
{ rule: makeRule("bongo,, super bongo", "@styleset { blah: 1; }"), invalid: true },
{ rule: makeRule("bongo,*", "@styleset { blah: 1; }"), invalid: true },
{ rule: makeRule("bongo, sans-serif", "@styleset { blah: 1; }"), invalid: true },
{ rule: makeRule("serif, sans-serif", "@styleset { blah: 1; }"), invalid: true },
{ rule: makeRule("'serif', 'sans-serif'", "@styleset { blah: 1; }"), serializationSame: true },
{ rule: makeRule("bongo, \"super bongo\", 'bongo the supreme'", "@styleset { blah: 1; }"), serializationSame: true },
{ rule: makeRule("毎日カレーを食べたい!", "@styleset { blah: 1; }"), serializationSame: true },
{ rule: makeRule("毎日カレーを食べたい!, 納豆嫌い", "@styleset { blah: 1; }"), serializationSame: true },
{ rule: makeRule("bongo, \"super\" bongo, bongo the supreme", "@styleset { blah: 1; }"), invalid: true },
{ rule: makeRule("--bongo", "@styleset { blah: 1; }"), invalid: true },
/* ident tests */
{ rule: _("@styleset { blah: 1; blah: 1; }"), serializationSame: true },
{ rule: _("@styleset { blah: 1; de-blah: 1; blah: 2; }"), serializationSame: true },
{ rule: _("@styleset { \\tra-la: 1; }"), serialization: _("@styleset { tra-la: 1; }") },
{ rule: _("@styleset { b\\lah: 1; }"), serialization: _("@styleset { blah: 1; }") },
{ rule: _("@styleset { \\62 lah: 1; }"), serialization: _("@styleset { blah: 1; }") },
{ rule: _("@styleset { \\:blah: 1; }"), serialization: _("@styleset { \\:blah: 1; }") },
{ rule: _("@styleset { \\;blah: 1; }"), serialization: _("@styleset { \\;blah: 1; }") },
{ rule: _("@styleset { complex\\20 blah: 1; }"), serialization: _("@styleset { complex\\ blah: 1; }") },
{ rule: _("@styleset { complex\\ blah: 1; }"), serializationSame: true },
{ rule: _("@styleset { Håkon: 1; }"), serializationSame: true },
{ rule: _("@styleset { Åквариум: 1; }"), serializationSame: true },
{ rule: _("@styleset { \\1f449\\1f4a9\\1f448: 1; }"), serialization: _("@styleset { 👉💩👈: 1; }") },
{ rule: _("@styleset { 魅力: 1; }"), serializationSame: true },
{ rule: _("@styleset { 毎日カレーを食べたい!: 1; }"), serializationSame: true },
/* from http://en.wikipedia.org/wiki/Metal_umlaut */
{ rule: _("@styleset { TECHNICIÄNS\\ ÖF\\ SPÅCE\\ SHIP\\ EÅRTH\\ THIS\\ IS\\ YÖÜR\\ CÄPTÅIN\\ SPEÄKING\\ YÖÜR\\ ØÅPTÅIN\\ IS\\ DEA̋D: 1; }"), serializationSame: true },
{ rulesrc: ["@styleset { 123blah: 1; }"], serializationNoValueDefn: true },
{ rulesrc: ["@styleset { :123blah 1; }"], serializationNoValueDefn: true },
{ rulesrc: ["@styleset { :123blah: 1; }"], serializationNoValueDefn: true },
{ rulesrc: ["@styleset { ?123blah: 1; }"], serializationNoValueDefn: true },
{ rulesrc: ["@styleset { \"blah\": 1; }"], serializationNoValueDefn: true },
{ rulesrc: ["@styleset { complex blah: 1; }"], serializationNoValueDefn: true },
{ rulesrc: ["@styleset { complex\\ blah: 1; }"], serializationNoValueDefn: true }
];
// test that invalid value declarations don't affect the parsing of surrounding
// declarations. So before + invalid + after should match the serialization
// given in s.
var gSurroundingTests = [
// -- invalid, valid ==> valid
{ before: "", after: "@ornaments { whatchamacallit-1: 23; thingy-dingy: 3; }", s: _("@ornaments { whatchamacallit-1: 23; thingy-dingy: 3; }") },
// -- valid, invalid ==> valid
{ before: "@ornaments { whatchamacallit-1: 23; thingy-dingy: 7; }", after: "", s: _("@ornaments { whatchamacallit-1: 23; thingy-dingy: 7; }") },
// -- valid, invalid, valid ==> valid, valid
{ before: "@ornaments { whatchamacallit-1: 23; thingy-dingy: 3; }", after: "@character-variant { whatchamacallit-2: 23 4; }", s: _("@ornaments { whatchamacallit-1: 23; thingy-dingy: 3; } @character-variant { whatchamacallit-2: 23 4; }") },
// -- invalid, valid, invalid ==> valid
{ between: "@ornaments { whatchamacallit-1: 23; thingy-dingy: 4; }", s: _("@ornaments { whatchamacallit-1: 23; thingy-dingy: 4; }") }
];
/* strip out just values, along with empty value blocks (e.g. @swash { })*/
function valuesText(ruletext)
{
var t = ruletext.replace(/@[a-zA-Z0-9\-]+[ \n]*{[ \n]*}/g, "");
t = t.replace(/[ \n]+/g, " ");
t = t.replace(/^[^{]+{[ \n]*/, "");
t = t.replace(/[ \n]*}[^}]*$/, "");
t = t.replace(/[ \n]*;/g, ";");
return t;
}
function testParse(rulesrc)
{
var sheet = document.styleSheets[1];
var rule = _.apply(this, rulesrc);
while(sheet.cssRules.length > 0)
sheet.deleteRule(0);
try {
sheet.insertRule(rule, 0);
} catch (e) {
return e.toString();
}
if (sheet.cssRules.length == 1 && sheet.cssRules[0].type == kFontFeatureValuesRuleType) {
return sheet.cssRules[0].cssText.replace(/[ \n]+/g, " ");
}
return "";
}
function testOneRule(testrule) {
var sheet = document.styleSheets[1];
var rule;
if ("rulesrc" in testrule) {
rule = _.apply(this, testrule.rulesrc);
} else {
rule = testrule.rule;
}
var parseErr = false;
var expectedErr = false;
var invalid = false;
if ("invalid" in testrule && testrule.invalid) invalid = true;
while(sheet.cssRules.length > 0)
sheet.deleteRule(0);
try {
sheet.insertRule(rule, 0);
} catch (e) {
expectedErr = (e.name == "SyntaxError"
&& e instanceof DOMException
&& e.code == DOMException.SYNTAX_ERR
&& invalid);
parseErr = true;
}
test(function() {
assert_true(!parseErr || expectedErr, "unexpected syntax error");
if (!parseErr) {
assert_equals(sheet.cssRules.length, 1, "bad rule count");
assert_equals(sheet.cssRules[0].type, kFontFeatureValuesRuleType, "bad rule type");
}
}, "basic parse tests - " + rule);
var sanitizedRule = rule.replace(/[ \n]+/g, " ");
if (parseErr) {
return;
}
// should result in one @font-feature-values rule constructed
// serialization matches expectation
// -- note: due to inconsistent font family serialization problems,
// only the serialization of the values is tested currently
var ruleValues = valuesText(rule);
var serialized = sheet.cssRules[0].cssText;
var serializedValues = valuesText(serialized);
var haveSerialization = true;
if (testrule.serializationSame) {
test(function() {
assert_equals(serializedValues, ruleValues, "canonical cssText serialization doesn't match");
}, "serialization check - " + rule);
} else if ("serialization" in testrule) {
var s = valuesText(testrule.serialization);
test(function() {
assert_equals(serializedValues, s, "non-canonical cssText serialization doesn't match - ");
}, "serialization check - " + rule);
} else if (testrule.serializationNoValueDefn) {
test(function() {
assert_equals(serializedValues, "", "cssText serialization should have no value defintions - ");
}, "no value definitions in serialization - " + rule);
haveSerialization = false;
if ("rulesrc" in testrule) {
test(function() {
var j, rulesrc = testrule.rulesrc;
// invalid value definitions shouldn't affect the parsing of valid
// definitions before or after an invalid one
for (var j = 0; j < gSurroundingTests.length; j++) {
var t = gSurroundingTests[j];
var srulesrc = [];
if ("between" in t) {
srulesrc = srulesrc.concat(rulesrc);
srulesrc = srulesrc.concat(t.between);
srulesrc = srulesrc.concat(rulesrc);
} else {
if (t.before != "")
srulesrc = srulesrc.concat(t.before);
srulesrc = srulesrc.concat(rulesrc);
if (t.after != "")
srulesrc = srulesrc.concat(t.after);
}
var result = testParse(srulesrc);
assert_equals(valuesText(result), valuesText(t.s), "invalid declarations should not affect valid ones - ");
}
}, "invalid declarations don't affect valid ones - " + rule);
}
}
// if serialization non-empty, serialization should round-trip to itself
if (haveSerialization) {
var roundTripText = testParse([serializedValues]);
test(function() {
assert_equals(valuesText(roundTripText), serializedValues,
"serialization should round-trip to itself - ");
}, "serialization round-trip - " + rule);
}
}
function testFontFeatureValuesRuleParsing() {
var i;
for (i = 0; i < testrules.length; i++) {
var testrule = testrules[i];
var rule;
if ("rulesrc" in testrule) {
rule = _.apply(this, testrule.rulesrc);
} else {
rule = testrule.rule;
}
testOneRule(testrule);
//test(function() { testOneRule(testrule); }, "parsing " + rule);
}
}
testFontFeatureValuesRuleParsing();
</script>
</body></html>