#!/usr/bin/python
# -*- coding: utf-8 -*-
# libavg - Media Playback Engine.
# Copyright (C) 2003-2014 Ulrich von Zadow
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# Current versions can be found at www.libavg.de
#
import platform
from libavg import avg, player
from testcase import *
class WordsTestCase(AVGTestCase):
def __init__(self, testFuncName):
AVGTestCase.__init__(self, testFuncName)
def testSimpleWords(self):
def checkFont():
self.assertEqual(node.variant, "bold")
def checkUnicodeText():
node.text = u"föa"
avg.WordsNode(text=u"öäü", font="Bitstream Vera Sans")
fontList = avg.WordsNode.getFontFamilies()
try:
fontList.index("Bitstream Vera Sans")
except ValueError:
self.fail("Font not found")
variantList = avg.WordsNode.getFontVariants("Bitstream Vera Sans")
self.assert_(len(variantList) >= 4)
root = self.loadEmptyScene()
avg.WordsNode (pos=(1,1), fontsize=12, font="Bitstream Vera Sans",
text="Bitstream Vera Sans", variant="roman", parent=root)
node = avg.WordsNode(pos=(1,16), fontsize=12, font="Bitstream Vera Sans",
text="Bold", variant="bold", parent=root)
self.assertNotEqual(node.size, (0,0))
node.getGlyphPos(0)
self.start(True,
(lambda: self.compareImage("testSimpleWords"),
checkFont,
checkUnicodeText,
))
def testRedrawOnDemand(self):
def changeText(newText):
size = node.size
node.text = newText
self.assertNotEqual(node.size, size)
def changeFont():
size = node.size
node.fontsize = 18
self.assertNotEqual(node.size, size)
root = self.loadEmptyScene()
node = avg.WordsNode(font="Bitstream Vera Sans", fontsize=12, text="foo",
parent=root)
changeText("foobar")
self.start(True,
(lambda: changeText("bar"),
changeFont,
))
def testFontStyle(self):
def setStyle(node, style):
node.fontstyle = style
self.assert_(node.fontsize == 15)
fontStyle = avg.FontStyle(font="Bitstream Vera Sans", variant="Roman",
fontsize=12)
self.assert_(fontStyle.font == "Bitstream Vera Sans")
root = self.loadEmptyScene()
words = avg.WordsNode(pos=(1,1), fontstyle=fontStyle, text="Bitstream Vera Sans",
parent=root)
avg.WordsNode (pos=(1,16), fontstyle=fontStyle, variant="bold", text="Bold",
parent=root)
otherFontStyle = fontStyle
otherFontStyle.fontsize = 15
self.start(True,
(lambda: self.compareImage("testFontStyle1"),
lambda: setStyle(words, otherFontStyle),
lambda: self.compareImage("testFontStyle2"),
))
def testBaseStyle(self):
attrs = {"font": "Bitstream Vera Sans",
"variant": "Bold",
"color": "FF0000",
"aagamma": 0.5,
"fontsize": 20,
"indent": 1,
"linespacing": 2,
"alignment": "right",
"wrapmode": "char",
"justify": True,
"letterspacing": 3,
"hint": False}
defaultStyle = avg.FontStyle()
fontStyle1 = avg.FontStyle(basestyle=defaultStyle, **attrs)
for attrName in attrs.iterkeys():
self.assert_(getattr(fontStyle1, attrName) != getattr(defaultStyle, attrName))
self.assert_(getattr(fontStyle1, attrName) == attrs[attrName])
fontStyle2 = avg.FontStyle(basestyle=fontStyle1)
for attrName in attrs.iterkeys():
self.assert_(getattr(fontStyle2, attrName) == getattr(fontStyle1, attrName))
def testGlyphPos(self):
def posAlmostEqual(pos1, pos2):
return math.fabs(pos1[0]-pos2[0]) <= 2 and math.fabs(pos1[1]-pos2[1]) <= 2
node = avg.WordsNode(text="Bold", font="Bitstream Vera Sans")
self.assertEqual(node.getGlyphPos(0), (0,0))
size = node.getGlyphSize(0)
self.assert_(posAlmostEqual(size, (10, 18)))
self.assert_(posAlmostEqual(node.getGlyphPos(3), (22,0)))
size = node.getGlyphSize(3)
self.assert_(posAlmostEqual(size, (8, 18)))
self.assertException(lambda: node.getGlyphPos(4))
node.text=u"föa"
self.assert_(posAlmostEqual(node.getGlyphPos(1), (4,0)))
# print [ node.getGlyphPos(i) for i in range(3)]
self.assert_(posAlmostEqual(node.getGlyphPos(2), (12,0)))
self.assertException(lambda: node.getGlyphPos(3))
def testParaWords(self):
root = self.loadEmptyScene()
avg.LineNode(pos1=(0.5, 0), pos2=(0.5, 50), color="FF0000", parent=root)
avg.LineNode(pos1=(119.5, 0.5), pos2=(119.5, 50), color="FF0000", parent=root)
avg.LineNode(pos1=(74.5,60), pos2=(74.5, 110), color="FF0000", parent=root)
avg.WordsNode(id="para", pos=(1,1), fontsize=12, width=70,
font="Bitstream Vera Sans", text="Left-justified paragraph.",
parent=root)
avg.WordsNode(id="paracenter", pos=(120,1), fontsize=12, width=70,
font="Bitstream Vera Sans", text="Centered paragraph",
alignment="center", parent=root)
avg.WordsNode(id="pararight", pos=(75,60), fontsize=12, width=70,
font="Bitstream Vera Sans", alignment="right",
text="Right-justified paragraph.l",
parent=root)
avg.WordsNode(id="paralinespacing", pos=(80,60), fontsize=12, width=70,
font="Bitstream Vera Sans", linespacing=-4,
text="Paragraph with custom line spacing.",
parent=root)
self.start(True, [lambda: self.compareImage("testParaWords")])
def testJustify(self):
root = self.loadEmptyScene()
avg.WordsNode(pos=(1,1), fontsize=12, font="Bitstream Vera Sans",
variant="roman", justify=True, width=100,
text="Justified paragraph more than one line long.", parent=root)
self.start(True, [lambda: self.compareImage("testJustify")])
def testWrapMode(self):
def setCharMode():
node.wrapmode = 'char'
def setWordMode():
node.wrapmode = 'word'
def setWordCharMode():
node.wrapmode = 'wordchar'
root = self.loadEmptyScene()
node = avg.WordsNode(pos=(1,1), fontsize=12, font="Bitstream Vera Sans",
variant="roman", width=100,
text="""Wrapped paragraph more than one line long.
Withaverylongpackedlinewithnobreaks""",
parent=root)
self.start(True,
(lambda: self.compareImage("testWrapMode1"),
setCharMode,
lambda: self.compareImage("testWrapMode2"),
setWordMode,
lambda: self.compareImage("testWrapMode3"),
setWordCharMode,
lambda: self.compareImage("testWrapMode4"),
))
def testWordsMask(self):
def setMask():
try:
node.maskhref = "mask1.png"
except RuntimeError:
self.skip("no shader support")
player.stop()
def setColor():
node.color = "FFFF00"
def setOpacity():
node.opacity = 0.5
def setSize():
rect = avg.RectNode(pos=(39.5, 30.5), size=(80, 60))
root.appendChild(rect)
node.masksize = (160, 120)
node.opacity = 1
def setPos():
node.pos = (40, 20)
node.maskpos = (-40, -20)
def setDefaultSize():
node.masksize = (0,0)
def setCentered():
node.alignment = "center"
node.masksize = (160, 120)
node.pos = (80,20)
node.maskpos = (0, -20)
root = self.loadEmptyScene()
node = avg.WordsNode(fontsize=8, linespacing=-4, font="Bitstream Vera Sans",
variant="roman", width=160,
text="Ich bin nur ein kleiner Blindtext. Wenn ich gross bin, will ich \
Ulysses von James Joyce werden. Aber jetzt lohnt es sich noch nicht, \
mich weiterzulesen. Denn vorerst bin ich nur ein kleiner Blindtext. \
Ich bin nur ein kleiner Blindtext. Wenn ich gross bin, will ich \
Ulysses von James Joyce werden. Aber jetzt lohnt es sich noch nicht, \
mich weiterzulesen. Denn vorerst bin ich nur ein kleiner Blindtext. \
Ich bin nur ein kleiner Blindtext. Wenn ich gross bin, will ich \
Ulysses von James Joyce werden. Aber jetzt lohnt es sich noch nicht, \
mich weiterzulesen. Denn vorerst bin ich nur ein kleiner Blindtext.",
parent=root)
self.start(True,
(setMask,
lambda: self.compareImage("testWordsMask1"),
setColor,
lambda: self.compareImage("testWordsMask2"),
setOpacity,
lambda: self.compareImage("testWordsMask3"),
setSize,
lambda: self.compareImage("testWordsMask4"),
setPos,
lambda: self.compareImage("testWordsMask5"),
setDefaultSize,
lambda: self.compareImage("testWordsMask6"),
setCentered,
lambda: self.compareImage("testWordsMask7"),
))
def testHinting(self):
def checkPositions():
# node0 = root.getChild(0)
# for i in range(len(node0.text)):
# print node0.getGlyphPos(i)
noHint = root.getChild(0)
hint = root.getChild(1)
posNoHint = noHint.getGlyphPos(6)
posHint = hint.getGlyphPos(6)
self.assertNotEqual(posNoHint, posHint)
noHint.hint = True
hint.hint = False
self.assertEqual(posNoHint, hint.getGlyphPos(6))
self.assertEqual(posHint, noHint.getGlyphPos(6))
if platform.system() == "Linux":
self.skip("Linux support requires modified font config")
else:
root = self.loadEmptyScene()
avg.WordsNode(pos=(1,1), fontsize=12, font="Bitstream Vera Sans",
variant="roman", hint=False, text="Lorem ipsum dolor (no hinting)",
parent=root)
avg.WordsNode(pos=(1,15), fontsize=12, font="Bitstream Vera Sans",
variant="roman", hint=True, text="Lorem ipsum dolor (hinting)",
parent=root)
self.start(True, [checkPositions])
def testSpanWords(self):
def setTextAttrib():
self.baselineBmp = player.screenshot()
player.getElementByID("words").text = self.text
def checkSameImage():
bmp = player.screenshot()
self.assert_(self.areSimilarBmps(bmp, self.baselineBmp, 0, 0))
def createUsingDict():
player.getElementByID("words").unlink()
node = avg.WordsNode(id="words", pos=(1,1), fontsize=12, width=120,
font="Bitstream Vera Sans", variant="roman", text=self.text)
root.appendChild(node)
self.text = """
Markup:
span,
italics, bold
"""
root = self.loadEmptyScene()
node = player.createNode("""
"""
+self.text+
"""
""")
root.appendChild(node)
self.start(True,
[lambda: self.compareImage("testSpanWords"),
setTextAttrib,
lambda: self.compareImage("testSpanWords"),
checkSameImage,
createUsingDict,
lambda: self.compareImage("testSpanWords"),
checkSameImage,
])
def testDynamicWords(self):
def changeText():
oldwidth = words.width
words.text = "blue"
self.assertNotEqual(words.width, oldwidth)
words.color = "404080"
words.x += 10
def changeHeight():
words.height = 28
def activateText():
words.active = True
def deactivateText():
words.active = False
def changeFont():
words.font = "Bitstream Vera Sans"
words.height = 0
words.fontsize = 30
def changeFont2():
words.fontsize = 18
def changeTextWithInvalidTag():
try:
words.text = "This bombs"
except:
words.text = "except"
self.assertEqual(words.text, "except")
root = self.loadEmptyScene()
words = avg.WordsNode(pos=(1,1), fontsize=12, font="Bitstream Vera Sans",
text="foo", parent=root)
self.start(True,
(lambda: self.compareImage("testDynamicWords1"),
changeText,
changeHeight,
changeFont,
lambda: self.compareImage("testDynamicWords2"),
deactivateText,
lambda: self.compareImage("testDynamicWords3"),
activateText,
changeFont2,
lambda: self.compareImage("testDynamicWords4"),
changeTextWithInvalidTag
))
def testI18NWords(self):
def changeUnicodeText():
words.text = "Arabic nonsense: ﯿﭗ"
def setNBSP():
words.width=100
words.text=(u"blindtext1\u00A0blindtext2\u00Ablindtext3 "+
u"blindtext4\u00A0blindtext\u00A0blindtext\u00A0")
root = self.loadEmptyScene()
avg.WordsNode(pos=(1,1), fontsize=14, font="Bitstream Vera Sans",
text="一二三四五六七八九", parent=root)
words = avg.WordsNode(pos=(1,24), fontsize=12, font="Bitstream Vera Sans",
text="foo", parent=root)
root.appendChild(
player.createNode("""
&
"""))
avg.WordsNode(pos=(12,48), fontsize=12, font="Bitstream Vera Sans", text="&",
rawtextmode=True, parent=root)
self.start(True,
(lambda: self.compareImage("testI18NWords1"),
changeUnicodeText,
lambda: self.compareImage("testI18NWords2"),
setNBSP,
lambda: self.compareImage("testI18NWords3"),
))
def testRawText(self):
def createDynNodes():
self.dictdnode = avg.WordsNode(text='<test dyndict&',
rawtextmode=True, pos=(1,65), font='Bitstream Vera Sans',
variant='roman', fontsize=12)
root.appendChild(self.dictdnode)
self.xmldnode = player.createNode("""
""")
root.appendChild(self.xmldnode)
def switchRawMode():
self.dictdnode.rawtextmode = False
valNode.rawtextmode = True
attribNode.rawtextmode = True
def bombIt():
def cantRun():
self.xmldnode.rawtextmode = False
self.assert_(0)
self.assertException(cantRun)
def assignNewTexts():
text = u'&ùùààxx>'
self.dictdnode.rawtextmode = True
self.dictdnode.text = text
self.xmldnode.text = text
valNode.text = text
attribNode.text = text
root = self.loadEmptyScene()
attribNode = avg.WordsNode(text="ùnicòdé bold",
fontsize=12, pos=(1,5), font="Bitstream Vera Sans", parent=root)
valNode = player.createNode("""
bold ùnicòdé <""")
root.appendChild(valNode)
root.appendChild(
player.createNode("""
&
"""))
self.start(True,
(lambda: self.compareImage("testRawText1"),
createDynNodes,
lambda: self.compareImage("testRawText2"),
switchRawMode,
lambda: self.compareImage("testRawText3"),
bombIt,
assignNewTexts,
lambda: self.compareImage("testRawText4"),
))
def testWordsBR(self):
root = self.loadEmptyScene()
avg.WordsNode(pos=(1,1), fontsize=12, font="Bitstream Vera Sans", variant="roman",
text="paragraph 1
paragraph 2", parent=root)
self.start(True,
[lambda: self.compareImage("testWordsBR")])
def testLetterSpacing(self):
def setSpacing():
player.getElementByID("words1").letterspacing=-2
player.getElementByID("words2").letterspacing=-2
root = self.loadEmptyScene()
avg.WordsNode(id="words1", pos=(1,1), fontsize=12, font="Bitstream Vera Sans",
variant="roman",
text="""normal
packed
spaced""",
parent=root)
avg.WordsNode(id="words2", pos=(1,20), fontsize=12, font="Bitstream Vera Sans",
variant="roman", letterspacing=2, text="spaced", parent=root)
self.start(True,
(lambda: self.compareImage("testLetterSpacing1"),
setSpacing,
lambda: self.compareImage("testLetterSpacing2")
))
def testPositioning(self):
def click(pos):
self.fakeClick(int(pos[0]), int(pos[1]))
def testInside(bInside):
ok = bInside == self.clicked
self.clicked = False
return ok
def onMouse(event):
self.clicked = True
root = self.loadEmptyScene()
avg.LineNode(pos1=(4, 20.5), pos2=(157, 20.5), color="FF0000", parent=root)
avg.LineNode(pos1=(4.5, 20.5), pos2=(4.5, 110), color="FF0000", parent=root)
avg.LineNode(pos1=(156.5, 20.5), pos2=(156.5, 110), color="FF0000", parent=root)
avg.LineNode(pos1=(80.5, 20.5), pos2=(80.5, 110), color="FF0000", parent=root)
avg.WordsNode(id="left", pos=(4,20), fontsize=12, font="Bitstream Vera Sans",
variant="roman", text="Norm", parent=root)
avg.WordsNode(pos=(45,20), fontsize=12, font="Bitstream Vera Sans",
variant="roman", text="orm", parent=root)
avg.WordsNode(pos=(75,20), fontsize=12, font="Bitstream Vera Sans",
variant="roman", text="ÖÄÜ", parent=root)
avg.WordsNode(pos=(4,40), fontsize=12, font="Bitstream Vera Sans",
variant="oblique", text="Jtalic", parent=root)
avg.WordsNode(id="right", pos=(156,60), fontsize=12, alignment="right",
font="Bitstream Vera Sans", variant="roman", text="Right-aligned",
parent=root)
avg.WordsNode(id="center", pos=(80,80), fontsize=12, alignment="center",
font="Bitstream Vera Sans", variant="roman", text="Centered",
parent=root)
for id in ["left", "center", "right"]:
player.getElementByID(id).subscribe(avg.Node.CURSOR_DOWN, onMouse)
self.clicked = False
leftWidth = player.getElementByID("left").getMediaSize()[0]
centerWidth = player.getElementByID("center").getMediaSize()[0]
rightWidth = player.getElementByID("right").getMediaSize()[0]
self.start(True,
(lambda: self.compareImage("testPositioning"),
lambda: click((4,20)),
lambda: self.assert_(testInside(True)),
lambda: click((3,20)),
lambda: self.assert_(testInside(False)),
lambda: click((3+leftWidth,20)),
lambda: self.assert_(testInside(True)),
lambda: click((4+leftWidth,20)),
lambda: self.assert_(testInside(False)),
lambda: click((81-centerWidth/2,80)),
lambda: self.assert_(testInside(True)),
lambda: click((80-centerWidth/2,80)),
lambda: self.assert_(testInside(False)),
lambda: click((80+centerWidth/2,80)),
lambda: self.assert_(testInside(True)),
lambda: click((81+centerWidth/2,80)),
lambda: self.assert_(testInside(False)),
lambda: click((156-rightWidth,60)),
lambda: self.assert_(testInside(True)),
lambda: click((155-rightWidth,60)),
lambda: self.assert_(testInside(False)),
lambda: click((155,60)),
lambda: self.assert_(testInside(True)),
lambda: click((156,60)),
lambda: self.assert_(testInside(False)),
))
def testInvalidColor(self):
def testColor(col):
avg.WordsNode(color=col)
def assignValidColor():
testColor('123456')
def assignInvalidColor1():
testColor('1234567')
def assignInvalidColor2():
testColor('xxx')
def assignInvalidColor3():
testColor('xxxxxx')
self.loadEmptyScene()
self.start(True,
(self.assertException(assignInvalidColor1),
self.assertException(assignInvalidColor2),
self.assertException(assignInvalidColor3),
))
def testFontDir(self):
avg.WordsNode.addFontDir('extrafonts')
root = self.loadEmptyScene()
avg.WordsNode(font="testaddfontdir", fontsize=50, text="ABAAA", parent=root)
self.start(True,
(lambda: self.compareImage("testFontDir"),))
def testGetNumLines(self):
textNode = avg.WordsNode(text="paragraph 1
paragraph 2
paragraph 3")
self.assertEqual(textNode.getNumLines(), 3)
textNode.text = ""
self.assertEqual(textNode.getNumLines(), 0)
def testGetLineExtents(self):
textNode = avg.WordsNode(fontsize = 100,
font = "Bitstream Vera Sans",
text = "bla
blabli
blabliblabla")
self.assertEqual(textNode.getLineExtents(0), (184,117))
self.assertEqual(textNode.getLineExtents(1), (303,117))
def testGetCharIndexFromPos(self):
textNode = avg.WordsNode(fontsize=30,
font = "Bitstream Vera Sans",
text = "A B C D E F G H Ä Ö Ü ? Ì Á Í Å Ø ∏ ~ ç Ç Å",
width = 300)
for k in (1,2,3,23,42):
pos = textNode.getGlyphPos(k)
char = textNode.getCharIndexFromPos(pos)
self.assertEqual(char, k)
def testGetTextAsDisplayed(self):
orgText = "A
B C D E F G H Ä Ö Ü ? Ì Á
Í Å Ø ∏ ~ ç Ç Å"
orgTextWithout = "A\nB C D E F G H Ä Ö Ü ? Ì Á\nÍ Å Ø ∏ ~ ç Ç Å"
textNode = avg.WordsNode(fontsize=30,
font = "Bitstream Vera Sans",
text = orgText,
width = 300)
self.assertEqual(orgTextWithout, textNode.getTextAsDisplayed())
def testSetWidth(self):
root = self.loadEmptyScene()
text = "42 " * 42
textNode = avg.WordsNode(
parent=root,
fontsize = 10,
font = "Bitstream Vera Sans",
text = text)
def testSize(p1, p2):
self.assert_(abs(p1.x - p2.x) < 5)
self.assert_(abs(p1.y - p2.y) < 50)
testSize(textNode.size, avg.Point2D(630,13))
testSize(textNode.getMediaSize(), avg.Point2D(630,13))
mediaSize = textNode.getMediaSize()
def changeSize():
textNode.width = 50
testSize(textNode.size, avg.Point2D(50,182))
testSize(textNode.getMediaSize(), avg.Point2D(45,182))
self.assertNotEqual(mediaSize, textNode.getMediaSize())
self.start(True,
[lambda: changeSize()])
def testTooWide(self):
root = self.loadEmptyScene()
text = "42 " * 42 * 20
avg.WordsNode(parent=root, text=text)
self.assertException(
lambda: self.start((None, None))
)
def testWordsGamma(self):
def setGamma():
node.aagamma = 4
root = self.loadEmptyScene()
for i, gamma in enumerate((2, 1.5, 1)):
node = avg.WordsNode(pos=(1,i*20), fontsize=12, font="Bitstream Vera Sans",
variant="roman", aagamma=gamma, text="lorem ipsum dolor",
parent=root)
self.start(True,
(lambda: self.compareImage("testWordsGamma1"),
setGamma,
lambda: self.compareImage("testWordsGamma2"),
))
def wordsTestSuite(tests):
availableTests = (
"testSimpleWords",
"testRedrawOnDemand",
"testFontStyle",
"testBaseStyle",
"testGlyphPos",
"testParaWords",
"testJustify",
"testWrapMode",
"testWordsMask",
"testHinting",
"testSpanWords",
"testDynamicWords",
"testI18NWords",
"testRawText",
"testWordsBR",
"testLetterSpacing",
"testPositioning",
"testInvalidColor",
"testFontDir",
"testGetNumLines",
"testGetLineExtents",
"testGetCharIndexFromPos",
"testGetTextAsDisplayed",
"testSetWidth",
"testTooWide",
"testWordsGamma",
)
return createAVGTestSuite(availableTests, WordsTestCase, tests)