Skip to content

Commit

Permalink
check that bitmap is actually a PNG file
Browse files Browse the repository at this point in the history
  • Loading branch information
anthrotype committed Feb 17, 2022
1 parent 065d482 commit 6943142
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 5 deletions.
5 changes: 3 additions & 2 deletions src/nanoemoji/color_glyph.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
PaintRadialGradient,
PaintSolid,
)
from nanoemoji.png import PNG
from picosvg.geometric_types import Point, Rect
from picosvg.svg_meta import number_or_percentage
from picosvg.svg_reuse import normalize, affine_between
Expand Down Expand Up @@ -402,7 +403,7 @@ class ColorGlyph(NamedTuple):
painted_layers: Optional[Tuple[Paint, ...]] # None for untouched and bitmap formats
svg: Optional[SVG] # None for bitmap formats
user_transform: Affine2D
bitmap: Optional[bytes] # None for vector formats
bitmap: Optional[PNG] # None for vector formats

@staticmethod
def create(
Expand All @@ -413,7 +414,7 @@ def create(
ufo_glyph_name: str,
codepoints: Tuple[int, ...],
svg: Optional[SVG],
bitmap: Optional[bytes] = None,
bitmap: Optional[PNG] = None,
) -> "ColorGlyph":
logging.debug(" ColorGlyph for %s (%s)", ", ".join(filenames), codepoints)
base_glyph = ufo.newGlyph(ufo_glyph_name)
Expand Down
28 changes: 28 additions & 0 deletions src/nanoemoji/png.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


class PNG(bytes):

# The first eight bytes of a PNG file always contain the following (decimal) values:
# 137 80 78 71 13 10 26 10
# https://www.w3.org/TR/PNG-Structure.html
SIGNATURE = b"\x89PNG\r\n\x1a\n"

def __new__(cls, *args, **kwargs):
self = super().__new__(cls, *args, **kwargs)
header = self[:8]
if header != cls.SIGNATURE:
raise ValueError("Invalid PNG file: bad signature {header!r}")
return self
5 changes: 3 additions & 2 deletions src/nanoemoji/write_font.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
PaintGlyph,
PaintSolid,
)
from nanoemoji.png import PNG
from nanoemoji.svg import make_svg_table
from nanoemoji.svg_path import draw_svg_path
from nanoemoji import util
Expand Down Expand Up @@ -92,7 +93,7 @@ class InputGlyph(NamedTuple):
codepoints: Tuple[int, ...]
glyph_name: str
svg: Optional[SVG] # None for bitmap formats
bitmap: Optional[bytes] # None for vector formats
bitmap: Optional[PNG] # None for vector formats


# A color font generator.
Expand Down Expand Up @@ -784,7 +785,7 @@ def _inputs(
if font_config.has_bitmaps:
if png_file is None:
raise ValueError(f"No {file_stem}.png among inputs")
bitmap = png_file.read_bytes()
bitmap = PNG(png_file.read_bytes())

filenames = []
if svg_file is not None:
Expand Down
22 changes: 22 additions & 0 deletions tests/png_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from nanoemoji.png import PNG
import pytest


def test_good_png_signature():
# example from https://en.wikipedia.org/wiki/Portable_Network_Graphics
data = bytes(
int(b, 16)
for b in (
"89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52 "
"00 00 00 01 00 00 00 01 08 02 00 00 00 90 77 53 "
"DE 00 00 00 0C 49 44 41 54 08 D7 63 F8 CF C0 00 "
"00 03 01 01 00 18 DD 8D B0 00 00 00 00 49 45 4E "
"44 AE 42 60 82"
).split()
)
assert PNG(data) == data


def test_bad_png_signature():
with pytest.raises(ValueError, match="bad signature"):
PNG(b"<?xml")
3 changes: 2 additions & 1 deletion tests/test_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from nanoemoji import features
from nanoemoji.glyph import glyph_name
from nanoemoji import write_font
from nanoemoji.png import PNG
from pathlib import Path
from picosvg.svg import SVG
import pytest
Expand Down Expand Up @@ -64,7 +65,7 @@ def rasterize_svg(filename, bitmap_resolution):
output_file,
]
)
return output_file.read_bytes()
return PNG(output_file.read_bytes())


def color_font_config(config_overrides, svgs, tmp_dir=None):
Expand Down

0 comments on commit 6943142

Please sign in to comment.