Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 74c3669c authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add font_fallback.xml generator script" into main

parents 424ef796 7e706b03
Loading
Loading
Loading
Loading
+36 −0
Original line number Diff line number Diff line
// Copyright (C) 2024 The Android Open Source Project
//
// 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.

python_library_host {
    name: "generate_fonts_xml_lib",
    srcs: [
        "alias_builder.py",
        "commandline.py",
        "custom_json.py",
        "fallback_builder.py",
        "family_builder.py",
        "font_builder.py",
        "validators.py",
        "xml_builder.py",
    ],
}

python_binary_host {
    name: "generate_fonts_xml",
    main: "generate_fonts_xml_main.py",
    srcs: ["generate_fonts_xml_main.py"],
    libs: [
        "generate_fonts_xml_lib",
    ],
}
+64 −0
Original line number Diff line number Diff line
#!/usr/bin/env python

#
# Copyright (C) 2024 The Android Open Source Project
#
# 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.
#

"""Build Alias instance with validating JSON contents."""

import dataclasses

from custom_json import _load_json_with_comment
from validators import check_str
from validators import check_weight_or_none


@dataclasses.dataclass
class Alias:
  name: str
  to: str
  weight: int | None


_ALIAS_KEYS = set(["name", "to", "weight"])


def parse_alias(obj) -> Alias:
  """Convert given dict object to Alias instance."""
  unknown_keys = obj.keys() - _ALIAS_KEYS
  assert not unknown_keys, "Unknown keys found: %s" % unknown_keys
  alias = Alias(
      name=check_str(obj, "name"),
      to=check_str(obj, "to"),
      weight=check_weight_or_none(obj, "weight"),
  )

  assert alias.name != alias.to, "name and to must not be equal"

  return alias


def parse_alias_from_json(json_str) -> Alias:
  """For testing purposes."""
  return parse_alias(_load_json_with_comment(json_str))


def parse_aliases(objs) -> [Alias]:
  assert isinstance(objs, list), "aliases must be list"
  return [parse_alias(obj) for obj in objs]


def parse_aliases_from_json(json_str) -> [Alias]:
  return parse_aliases(_load_json_with_comment(json_str))
+71 −0
Original line number Diff line number Diff line
#!/usr/bin/env python

#
# Copyright (C) 2024 The Android Open Source Project
#
# 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.
#

"""Build commandline arguments."""

import argparse
import dataclasses
from typing import Callable

from alias_builder import Alias
from alias_builder import parse_aliases_from_json
from fallback_builder import FallbackEntry
from fallback_builder import parse_fallback_from_json
from family_builder import Family
from family_builder import parse_families_from_json


@dataclasses.dataclass
class CommandlineArgs:
  outfile: str
  fallback: [FallbackEntry]
  aliases: [Alias]
  families: [Family]


def _create_argument_parser() -> argparse.ArgumentParser:
  """Create argument parser."""
  parser = argparse.ArgumentParser()
  parser.add_argument('-o', '--output')
  parser.add_argument('--alias')
  parser.add_argument('--fallback')
  return parser


def _fileread(path: str) -> str:
  with open(path, 'r') as f:
    return f.read()


def parse_commandline(
    args: [str], fileread: Callable[str, str] = _fileread
) -> CommandlineArgs:
  """Parses command line arguments and returns CommandlineArg."""
  parser = _create_argument_parser()
  args, inputs = parser.parse_known_args(args)

  families = []
  for i in inputs:
    families = families + parse_families_from_json(fileread(i))

  return CommandlineArgs(
      outfile=args.output,
      fallback=parse_fallback_from_json(fileread(args.fallback)),
      aliases=parse_aliases_from_json(fileread(args.alias)),
      families=families,
  )
+31 −0
Original line number Diff line number Diff line
#!/usr/bin/env python

#
# Copyright (C) 2024 The Android Open Source Project
#
# 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.
#

"""A custom json parser that additionally supports line comments."""

import json
import re

# RegEx of removing line comment line in JSON.
_LINE_COMMENT_RE = re.compile(r'\/\/[^\n\r]*[\n\r]')


def _load_json_with_comment(json_str: str):
  """Parse JSON string with accepting line comment."""
  raw_text = re.sub(_LINE_COMMENT_RE, '', json_str)
  return json.loads(raw_text)
+61 −0
Original line number Diff line number Diff line
#!/usr/bin/env python

#
# Copyright (C) 2024 The Android Open Source Project
#
# 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.
#

"""Build Fallback instance with validating JSON contents."""

import dataclasses

from custom_json import _load_json_with_comment
from validators import check_str_or_none


@dataclasses.dataclass
class FallbackEntry:
  lang: str | None
  id: str | None


_FALLBACK_KEYS = set(["lang", "id"])


def _parse_entry(obj) -> FallbackEntry:
  """Convert given dict object to FallbackEntry instance."""
  unknown_keys = obj.keys() - _FALLBACK_KEYS
  assert not unknown_keys, "Unknown keys found: %s" % unknown_keys
  entry = FallbackEntry(
      lang=check_str_or_none(obj, "lang"),
      id=check_str_or_none(obj, "id"),
  )

  assert entry.lang or entry.id, "lang or id must be specified."
  assert (
      not entry.lang or not entry.id
  ), "lang and id must not be specified at the same time"

  return entry


def parse_fallback(objs) -> [FallbackEntry]:
  assert isinstance(objs, list), "fallback must be list"
  assert objs, "at least one etnry must be specified"
  return [_parse_entry(obj) for obj in objs]


def parse_fallback_from_json(json_str) -> [FallbackEntry]:
  """For testing purposes."""
  return parse_fallback(_load_json_with_comment(json_str))
Loading