more tests

This commit is contained in:
Ryan Oldenburg 2021-05-03 15:41:38 -05:00
parent cbfccea851
commit eafd18fa7e
131 changed files with 570 additions and 121 deletions

View file

@ -332,12 +332,22 @@ proc fillText*(
text: string,
color: SomeColor,
transform: Vec2 | Mat3 = vec2(0, 0),
bounds = vec2(0, 0)
bounds = vec2(0, 0),
hAlign = haLeft,
vAlign = vaTop,
textCase = tcNormal,
wrap = true,
kerning = true
) =
let typeset = font.typeset(text, bounds)
for i in 0 ..< typeset.runes.len:
var path = font.getGlyphPath(typeset.runes[i])
path.transform(translate(typeset.positions[i]) * scale(vec2(font.scale)))
for path in font.typesetPaths(
text,
bounds,
hAlign,
vAlign,
textCase,
wrap,
kerning
):
image.fillPath(path, color, transform)
proc fillText*(
@ -345,12 +355,22 @@ proc fillText*(
font: Font,
text: string,
transform: Vec2 | Mat3 = vec2(0, 0),
bounds = vec2(0, 0)
bounds = vec2(0, 0),
hAlign = haLeft,
vAlign = vaTop,
textCase = tcNormal,
wrap = true,
kerning = true
) =
let typeset = font.typeset(text, bounds)
for i in 0 ..< typeset.runes.len:
var path = font.getGlyphPath(typeset.runes[i])
path.transform(translate(typeset.positions[i]) * scale(vec2(font.scale)))
for path in font.typesetPaths(
text,
bounds,
hAlign,
vAlign,
textCase,
wrap,
kerning
):
mask.fillPath(path, transform)
proc strokeText*(
@ -360,12 +380,22 @@ proc strokeText*(
color: SomeColor,
transform: Vec2 | Mat3 = vec2(0, 0),
strokeWidth = 1.0,
bounds = vec2(0, 0)
bounds = vec2(0, 0),
hAlign = haLeft,
vAlign = vaTop,
textCase = tcNormal,
wrap = true,
kerning = true
) =
let typeset = font.typeset(text, bounds)
for i in 0 ..< typeset.runes.len:
var path = font.getGlyphPath(typeset.runes[i])
path.transform(translate(typeset.positions[i]) * scale(vec2(font.scale)))
for path in font.typesetPaths(
text,
bounds,
hAlign,
vAlign,
textCase,
wrap,
kerning
):
image.strokePath(path, color, transform, strokeWidth)
proc strokeText*(
@ -374,10 +404,20 @@ proc strokeText*(
text: string,
transform: Vec2 | Mat3 = vec2(0, 0),
strokeWidth = 1.0,
bounds = vec2(0, 0)
bounds = vec2(0, 0),
hAlign = haLeft,
vAlign = vaTop,
textCase = tcNormal,
wrap = true,
kerning = true
) =
let typeset = font.typeset(text, bounds)
for i in 0 ..< typeset.runes.len:
var path = font.getGlyphPath(typeset.runes[i])
path.transform(translate(typeset.positions[i]) * scale(vec2(font.scale)))
for path in font.typesetPaths(
text,
bounds,
hAlign,
vAlign,
textCase,
wrap,
kerning
):
mask.strokePath(path, transform, strokeWidth)

View file

@ -235,6 +235,26 @@ type
pairValueCount: uint16
pairValueRecords: seq[PairValueRecord]
Class2Record = object
valueRecord1: ValueRecord
valueRecord2: ValueRecord
Class1Record = object
class2Records: seq[Class2Record]
ClassRangeRecord = object
startGlyphID: uint16
endGlyphID: uint16
class: uint16
ClassDef = object
classFormat: uint16
startGlyphID: uint16
glyphCount: uint16
classValueArray: seq[uint16]
classRangeCount: uint16
classRangeRecords: seq[ClassRangeRecord]
PairPos = ref object
posFormat: uint16
coverageOffset: uint16
@ -243,6 +263,13 @@ type
pairSetCount: uint16
pairSetOffsets: seq[uint16]
pairSets: seq[PairSet]
classDef1Offset: uint16
classDef2Offset: uint16
class1Count: uint16
class2Count: uint16
class1Records: seq[Class1Record]
classDef1: ClassDef
classDef2: ClassDef
coverage: Coverage
Lookup = object
@ -865,6 +892,66 @@ proc parsePairSet(
buf, i + j * pairValueRecordSize, valueFormat1, valueFormat2
)
proc parseClass2Record(
buf: string, offset: int, valueFormat1, valueFormat2: uint16
): Class2Record =
result.valueRecord1 = parseValueRecord(buf, offset, valueFormat1)
result.valueRecord2 = parseValueRecord(buf, offset, valueFormat2)
proc parseClass1Record(
buf: string, offset: int, valueFormat1, valueFormat2, class2Count: uint16
): Class1Record =
var i = offset
let class2RecordSize = (
countSetBits(valueFormat1) + countSetBits(valueFormat2)
) * 2
result.class2Records.setLen(class2Count.int)
for j in 0 ..< class2Count.int:
result.class2Records[j] =
parseClass2Record(buf, i, valueFormat1, valueFormat2)
i += class2RecordSize
proc parseClassRangeRecord(buf: string, offset: int): ClassRangeRecord =
buf.eofCheck(offset + 6)
result.startGlyphID = buf.readUint16(offset + 0).swap()
result.endGlyphID = buf.readUint16(offset + 2).swap()
result.class = buf.readUint16(offset + 4).swap()
proc parseClassDef(buf: string, offset: int): ClassDef =
var i = offset
buf.eofCheck(i + 2)
result.classFormat = buf.readUint16(i + 0).swap()
i += 2
case result.classFormat:
of 1:
buf.eofCheck(i + 4)
result.startGlyphID = buf.readUint16(i + 0).swap()
result.glyphCount = buf.readUint16(i + 2).swap()
i += 4
buf.eofCheck(i + result.glyphCount.int * 2)
result.classValueArray = buf.readUint16Seq(i + 0, result.glyphCount.int)
of 2:
buf.eofCheck(i + 2)
result.classRangeCount = buf.readUint16(i + 0).swap()
i += 2
result.classRangeRecords.setLen(result.classRangeCount.int)
for j in 0 ..< result.classRangeCount.int:
result.classRangeRecords[j] = parseClassRangeRecord(buf, i)
i += sizeof(ClassRangeRecord)
else:
failUnsupported()
proc parsePairPos(buf: string, offset: int): PairPos =
var i = offset
@ -902,7 +989,36 @@ proc parsePairPos(buf: string, offset: int): PairPos =
result.coverage = parseCoverage(buf, offset + result.coverageOffset.int)
of 2:
discard
result = PairPos()
result.posFormat = posFormat
buf.eofCheck(i + 14)
result.coverageOffset = buf.readUint16(i + 0).swap()
result.valueFormat1 = buf.readUint16(i + 2).swap()
result.valueFormat2 = buf.readUint16(i + 4).swap()
result.classDef1Offset = buf.readUint16(i + 6).swap()
result.classDef2Offset = buf.readUint16(i + 8).swap()
result.class1Count = buf.readUint16(i + 10).swap()
result.class2Count = buf.readUint16(i + 12).swap()
i += 14
let class2RecordSize = (
countSetBits(result.valueFormat1) + countSetBits(result.valueFormat2)
) * 2
result.class1Records.setLen(result.class1Count.int)
for j in 0 ..< result.class1Count.int:
result.class1Records[j] = parseClass1Record(
buf, i, result.valueFormat1, result.valueFormat2, result.class2Count
)
i += class2RecordSize
result.classDef1 = parseClassDef(buf, offset + result.classDef1Offset.int)
result.classDef2 = parseClassDef(buf, offset + result.classDef2Offset.int)
result.coverage = parseCoverage(buf, offset + result.coverageOffset.int)
else:
failUnsupported()
@ -1244,12 +1360,21 @@ proc getGlyphPath*(opentype: OpenType, rune: Rune): Path =
opentype.glyphPaths[rune].transform(scale(vec2(1, -1)))
opentype.glyphPaths[rune]
proc getGlyphAdvance*(opentype: OpenType, rune: Rune): float32 =
proc getLeftSideBearing*(opentype: OpenType, rune: Rune): float32 =
let glyphId = opentype.getGlyphId(rune).int
if glyphId < opentype.hmtx.hMetrics.len:
opentype.hmtx.hMetrics[glyphId].advanceWidth.float32
result = opentype.hmtx.hMetrics[glyphId].leftSideBearing.float32
else:
opentype.hmtx.hMetrics[^1].advanceWidth.float32
let index = glyphId - opentype.hmtx.hMetrics.len
if index > 0 and index < opentype.hmtx.leftSideBearings.len:
result = opentype.hmtx.leftSideBearings[index].float32
proc getAdvance*(opentype: OpenType, rune: Rune): float32 =
let glyphId = opentype.getGlyphId(rune).int
if glyphId < opentype.hmtx.hMetrics.len:
result = opentype.hmtx.hMetrics[glyphId].advanceWidth.float32
else:
result = opentype.hmtx.hMetrics[^1].advanceWidth.float32
proc getKerningAdjustment*(opentype: OpenType, left, right: Rune): float32 =
let pair = (left, right)
@ -1328,21 +1453,93 @@ proc parseOpenType*(buf: string): OpenType =
value += result.kerningPairs[key]
result.kerningPairs[key] = value
if "GPOS" in result.tableRecords:
result.gpos = parseGposTable(buf, result.tableRecords["GPOS"].offset.int)
# if "GPOS" in result.tableRecords:
# result.gpos = parseGposTable(buf, result.tableRecords["GPOS"].offset.int)
if result.gpos != nil and result.gpos.lookupList.pairPos != nil:
case result.gpos.lookupList.pairPos.coverage.coverageFormat:
of 1:
echo result.gpos.lookupList.pairPos.coverage.glyphCount
of 2:
echo result.gpos.lookupList.pairPos.coverage.rangeCount
else:
failUnsupported()
# if result.gpos != nil and result.gpos.lookupList.pairPos != nil:
# # case result.gpos.lookupList.pairPos.coverage.coverageFormat:
# # of 1:
# # echo "GLYPH COUNT:", result.gpos.lookupList.pairPos.coverage.glyphCount
# # of 2:
# # echo "RANGE COUNT:", result.gpos.lookupList.pairPos.coverage.rangeCount
# # else:
# # failUnsupported()
for pairSet in result.gpos.lookupList.pairPos.pairSets:
for pairValue in pairSet.pairValueRecords:
discard
# case result.gpos.lookupList.pairPos.posFormat:
# of 1:
# echo "posFormat 1 not implemented"
# of 2:
# proc classDefFormat1(classDef: ClassDef): Table[uint16, uint16] =
# for i in 0.uint16 ..< classDef.glyphCount:
# result[classDef.startGlyphID + i] = classDef.classValueArray[i]
# proc classDefFormat2(classDef: ClassDef): Table[uint16, uint16] =
# for record in classDef.classRangeRecords:
# if record.startGlyphID > record.endGlyphID:
# failUnsupported()
# for glyphId in record.startGlyphID .. record.endGlyphID:
# result[glyphId] = record.class
# var glyphIdToClass1: Table[uint16, uint16]
# case result.gpos.lookupList.pairPos.classDef1.classFormat:
# of 1:
# glyphIdToClass1 =
# classDefFormat1(result.gpos.lookupList.pairPos.classDef1)
# of 2:
# glyphIdToClass1 =
# classDefFormat2(result.gpos.lookupList.pairPos.classDef1)
# else:
# failUnsupported()
# var glyphIdToClass2: Table[uint16, uint16]
# case result.gpos.lookupList.pairPos.classDef2.classFormat:
# of 1:
# glyphIdToClass2 =
# classDefFormat1(result.gpos.lookupList.pairPos.classDef2)
# of 2:
# glyphIdToClass2 =
# classDefFormat2(result.gpos.lookupList.pairPos.classDef2)
# else:
# failUnsupported()
# var runeToClass1: Table[Rune, uint16]
# for glyphId, class in glyphIdToClass1:
# if glyphId in result.cmap.glyphIdToRune:
# let rune = result.cmap.glyphIdToRune[glyphId]
# runeToClass1[rune] = class
# var runeToClass2: Table[Rune, uint16]
# for glyphId, class in glyphIdToClass2:
# if glyphId in result.cmap.glyphIdToRune:
# let rune = result.cmap.glyphIdToRune[glyphId]
# runeToClass2[rune] = class
# var classPairs: Table[(uint16, uint16), Class2Record]
# for i, class1Record in result.gpos.lookupList.pairPos.class1Records:
# for j, class2Record in class1Record.class2Records:
# classPairs[(i.uint16, j.uint16)] = class2Record
# for left in result.cmap.runeToGlyphId.keys:
# for right in result.cmap.runeToGlyphId.keys:
# var leftClass, rightClass: uint16
# if left in runeToClass1:
# leftClass = runeToClass1[left]
# if right in runeToClass2:
# rightClass = runeToClass2[right]
# let pair = (leftClass, rightClass)
# if pair in classPairs:
# let classPair = classPairs[pair]
# if classPair.valueRecord1.xAdvance != 0:
# result.kerningPairs[(left, right)] =
# classPair.valueRecord1.xAdvance.float32
# else:
# failUnsupported()
# echo Rune(32) in result.cmap.runeToGlyphId
# echo getAdvance(result, Rune(32))
# echo result.head.unitsPerEm
# echo result.getGlyphId(Rune(32))
when defined(release):
{.pop.}

View file

@ -2,7 +2,7 @@ import pixie/common, pixie/paths, strutils, tables, unicode, vmath, xmlparser, x
type SvgFont* = ref object
unitsPerEm*, ascent*, descent*: float32
glyphAdvances: Table[Rune, float32]
advances: Table[Rune, float32]
glyphPaths: Table[Rune, Path]
kerningPairs: Table[(Rune, Rune), float32]
missingGlyphAdvance: float32
@ -14,9 +14,9 @@ proc getGlyphPath*(svgFont: SvgFont, rune: Rune): Path =
else:
svgFont.missingGlyphPath
proc getGlyphAdvance*(svgFont: SvgFont, rune: Rune): float32 =
if rune in svgFont.glyphAdvances:
svgFont.glyphAdvances[rune]
proc getAdvance*(svgFont: SvgFont, rune: Rune): float32 =
if rune in svgFont.advances:
svgFont.advances[rune]
else:
svgFont.missingGlyphAdvance
@ -74,7 +74,7 @@ proc parseSvgFont*(buf: string): SvgFont =
var advance = defaultAdvance
if node.attr("horiz-adv-x").len > 0:
advance = node.parseFloat("horiz-adv-x")
result.glyphAdvances[rune] = advance
result.advances[rune] = advance
result.glyphPaths[rune] = parsePath(node.attr("d"))
result.glyphPaths[rune].transform(scale(vec2(1, -1)))
else:

View file

@ -4,13 +4,16 @@ import pixie/fontformats/opentype, pixie/fontformats/svgfont, pixie/paths,
const AutoLineHeight* = -1.float32 ## Use default line height for the font size
type
Font* = ref object
Typeface = ref object
opentype: OpenType
svgFont: SvgFont
Font* = object
typeface*: Typeface
size*: float32 ## Font size in pixels.
lineHeight*: float32 ## The line height in pixels or AutoLineHeight for the font's default line height.
TypesetText* = ref object
Typesetting* = ref object
runes*: seq[Rune]
positions*: seq[Vec2]
@ -32,56 +35,59 @@ type
# tcSmallCaps
# tcSmallCapsForced
proc ascent(font: Font): float32 {.inline.} =
proc ascent(typeface: Typeface): float32 {.inline.} =
## The font ascender value in font units.
if font.opentype != nil:
font.opentype.hhea.ascender.float32
if typeface.opentype != nil:
typeface.opentype.hhea.ascender.float32
else:
font.svgFont.ascent
typeface.svgFont.ascent
proc descent(font: Font): float32 {.inline.} =
proc descent(typeface: Typeface): float32 {.inline.} =
## The font descender value in font units.
if font.opentype != nil:
font.opentype.hhea.descender.float32
if typeface.opentype != nil:
typeface.opentype.hhea.descender.float32
else:
font.svgFont.descent
typeface.svgFont.descent
proc lineGap(font: Font): float32 {.inline.} =
proc lineGap(typeface: Typeface): float32 {.inline.} =
## The font line gap value in font units.
if font.opentype != nil:
result = font.opentype.hhea.lineGap.float32
if typeface.opentype != nil:
result = typeface.opentype.hhea.lineGap.float32
proc getGlyphPath*(font: Font, rune: Rune): Path {.inline.} =
proc getGlyphPath*(typeface: Typeface, rune: Rune): Path {.inline.} =
## The glyph path for the rune.
if font.opentype != nil:
font.opentype.getGlyphPath(rune)
if typeface.opentype != nil:
typeface.opentype.getGlyphPath(rune)
else:
font.svgFont.getGlyphPath(rune)
typeface.svgFont.getGlyphPath(rune)
proc getGlyphAdvance(font: Font, rune: Rune): float32 {.inline.} =
proc getAdvance(typeface: Typeface, rune: Rune): float32 {.inline.} =
## The advance for the rune in pixels.
if font.opentype != nil:
font.opentype.getGlyphAdvance(rune)
if typeface.opentype != nil:
typeface.opentype.getAdvance(rune)
else:
font.svgFont.getGlyphAdvance(rune)
typeface.svgFont.getAdvance(rune)
proc getKerningAdjustment(font: Font, left, right: Rune): float32 {.inline.} =
proc getKerningAdjustment(
typeface: Typeface, left, right: Rune
): float32 {.inline.} =
## The kerning adjustment for the rune pair, in pixels.
if font.opentype != nil:
font.opentype.getKerningAdjustment(left, right)
if typeface.opentype != nil:
typeface.opentype.getKerningAdjustment(left, right)
else:
font.svgfont.getKerningAdjustment(left, right)
typeface.svgfont.getKerningAdjustment(left, right)
proc scale*(font: Font): float32 {.inline.} =
## The scale factor to transform font units into pixels.
if font.opentype != nil:
font.size / font.opentype.head.unitsPerEm.float32
if font.typeface.opentype != nil:
font.size / font.typeface.opentype.head.unitsPerEm.float32
else:
font.size / font.svgFont.unitsPerEm
font.size / font.typeface.svgFont.unitsPerEm
proc defaultLineHeight*(font: Font): float32 {.inline.} =
## The default line height in pixels for the current font size.
let fontUnits = (font.ascent + abs(font.descent) + font.lineGap)
let fontUnits =
font.typeface.ascent - font.typeface.descent + font.typeface.lineGap
round(fontUnits * font.scale)
proc convertTextCase(runes: var seq[Rune], textCase: TextCase) =
@ -107,12 +113,13 @@ proc typeset*(
bounds = vec2(0, 0),
hAlign = haLeft,
vAlign = vaTop,
textCase = tcNormal
): TypesetText =
result = TypesetText()
textCase = tcNormal,
wrap = true,
kerning = true
): Typesetting =
result = Typesetting()
result.runes = toRunes(text)
result.runes.convertTextCase(textCase)
result.positions.setLen(result.runes.len)
let lineHeight =
@ -121,22 +128,24 @@ proc typeset*(
else:
font.defaultLineHeight
proc glyphAdvance(runes: seq[Rune], font: Font, i: int): float32 {.inline.} =
if i + 1 < runes.len:
result += font.getKerningAdjustment(runes[i], runes[i + 1])
result += font.getGlyphAdvance(runes[i])
proc glyphAdvance(
font: Font, runes: seq[Rune], i: int, kerning: bool
): float32 {.inline.} =
if kerning and i + 1 < runes.len:
result += font.typeface.getKerningAdjustment(runes[i], runes[i + 1])
result += font.typeface.getAdvance(runes[i])
result *= font.scale
var
at: Vec2
prevCanWrap: int
at.y = round(font.ascent * font.scale)
at.y = round(font.typeface.ascent * font.scale)
at.y += (lineheight - font.defaultLineHeight) / 2
for i, rune in result.runes:
if rune.canWrap():
prevCanWrap = i
let advance = glyphAdvance(result.runes, font, i)
let advance = glyphAdvance(font, result.runes, i, kerning)
if rune != Rune(32) and bounds.x > 0 and at.x + advance > bounds.x:
# Wrap to new line
at.x = 0
@ -146,14 +155,40 @@ proc typeset*(
if prevCanWrap > 0 and prevCanWrap != i:
for j in prevCanWrap + 1 ..< i:
result.positions[j] = at
at.x += glyphAdvance(result.runes, font, j)
at.x += glyphAdvance(font, result.runes, j, kerning)
result.positions[i] = at
at.x += advance
iterator typesetPaths*(
font: Font,
text: string,
bounds = vec2(0, 0),
hAlign = haLeft,
vAlign = vaTop,
textCase = tcNormal,
wrap = true,
kerning = true
): Path =
let typesetText = font.typeset(
text,
bounds,
hAlign,
vAlign,
textCase,
wrap,
kerning
)
for i in 0 ..< typesetText.runes.len:
var path = font.typeface.getGlyphPath(typesetText.runes[i])
path.transform(
translate(typesetText.positions[i]) * scale(vec2(font.scale))
)
yield path
proc parseOtf*(buf: string): Font =
result = Font()
result.opentype = parseOpenType(buf)
result.typeface = Typeface()
result.typeface.opentype = parseOpenType(buf)
result.size = 12
result.lineHeight = AutoLineHeight
@ -161,7 +196,7 @@ proc parseTtf*(buf: string): Font =
parseOtf(buf)
proc parseSvgFont*(buf: string): Font =
result = Font()
result.svgFont = svgfont.parseSvgFont(buf)
result.typeface = Typeface()
result.typeface.svgFont = svgfont.parseSvgFont(buf)
result.size = 12
result.lineHeight = AutoLineHeight

View file

@ -2,7 +2,7 @@ import benchy, pixie
const text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis in quam in nulla bibendum luctus. Integer dui lectus, ultricies commodo enim quis, laoreet lacinia erat. Vivamus ultrices maximus risus, non aliquam quam sagittis quis. Ut nec diam vitae tortor interdum ullamcorper in aliquet velit. Ut sed lobortis mi. Nulla venenatis lectus varius justo lacinia, quis sollicitudin nunc ultrices. Donec a suscipit arcu, id egestas neque. Nullam commodo pharetra est. Nullam gravida nibh eget quam venenatis lacinia. Vestibulum et libero arcu. Sed dignissim enim eros. Nullam eleifend luctus erat sed luctus. Nunc tincidunt, mi nec tincidunt tristique, ex nulla lobortis sem, sit amet finibus purus justo non massa."
let font = readFont("tests/fonts/Roboto-Regular.ttf")
var font = readFont("tests/fonts/Roboto-Regular.ttf")
font.size = 16
timeIt "typeset":
@ -13,7 +13,7 @@ let
mask = newMask(500, 300)
timeIt "rasterize":
# image.fill(rgba(255, 255, 255, 255))
# image.fillText(font, text, rgba(0, 0, 0, 255), bounds = image.wh)
mask.fill(0)
mask.fillText(font, text, bounds = mask.wh)
image.fill(rgba(255, 255, 255, 255))
image.fillText(font, text, rgba(0, 0, 0, 255), bounds = image.wh)
# mask.fill(0)
# mask.fillText(font, text, bounds = mask.wh)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3 KiB

After

Width:  |  Height:  |  Size: 3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 711 B

After

Width:  |  Height:  |  Size: 709 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8 KiB

After

Width:  |  Height:  |  Size: 8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Some files were not shown because too many files have changed in this diff Show more