src/Pure/Admin/build_fonts.scala
changeset 75393 87ebf5a50283
parent 74433 ec1774613824
child 75394 42267c650205
equal deleted inserted replaced
75388:b3ca4a6ed74b 75393:87ebf5a50283
     5 */
     5 */
     6 
     6 
     7 package isabelle
     7 package isabelle
     8 
     8 
     9 
     9 
    10 object Build_Fonts
    10 object Build_Fonts {
    11 {
       
    12   /* relevant codepoint ranges */
    11   /* relevant codepoint ranges */
    13 
    12 
    14   object Range
    13   object Range {
    15   {
       
    16     def base_font: Seq[Int] =
    14     def base_font: Seq[Int] =
    17       (0x0020 to 0x007e) ++  // ASCII
    15       (0x0020 to 0x007e) ++  // ASCII
    18       (0x00a0 to 0x024f) ++  // Latin Extended-A/B
    16       (0x00a0 to 0x024f) ++  // Latin Extended-A/B
    19       (0x0400 to 0x04ff) ++  // Cyrillic
    17       (0x0400 to 0x04ff) ++  // Cyrillic
    20       (0x0600 to 0x06ff) ++  // Arabic
    18       (0x0600 to 0x06ff) ++  // Arabic
   135 
   133 
   136   sealed case class Family(
   134   sealed case class Family(
   137     plain: String = "",
   135     plain: String = "",
   138     bold: String = "",
   136     bold: String = "",
   139     italic: String = "",
   137     italic: String = "",
   140     bold_italic: String = "")
   138     bold_italic: String = ""
   141   {
   139   ) {
   142     val fonts: List[String] =
   140     val fonts: List[String] =
   143       proper_string(plain).toList :::
   141       proper_string(plain).toList :::
   144       proper_string(bold).toList :::
   142       proper_string(bold).toList :::
   145       proper_string(italic).toList :::
   143       proper_string(italic).toList :::
   146       proper_string(bold_italic).toList
   144       proper_string(bold_italic).toList
   147 
   145 
   148     def get(index: Int): String = fonts(index % fonts.length)
   146     def get(index: Int): String = fonts(index % fonts.length)
   149   }
   147   }
   150 
   148 
   151   object Family
   149   object Family {
   152   {
       
   153     def isabelle_symbols: Family =
   150     def isabelle_symbols: Family =
   154       Family(
   151       Family(
   155         plain = "IsabelleSymbols.sfd",
   152         plain = "IsabelleSymbols.sfd",
   156         bold = "IsabelleSymbolsBold.sfd")
   153         bold = "IsabelleSymbolsBold.sfd")
   157 
   154 
   181 
   178 
   182 
   179 
   183   /* hinting */
   180   /* hinting */
   184 
   181 
   185   // see https://www.freetype.org/ttfautohint/doc/ttfautohint.html
   182   // see https://www.freetype.org/ttfautohint/doc/ttfautohint.html
   186   private def auto_hint(source: Path, target: Path): Unit =
   183   private def auto_hint(source: Path, target: Path): Unit = {
   187   {
       
   188     Isabelle_System.bash("ttfautohint -i " +
   184     Isabelle_System.bash("ttfautohint -i " +
   189       File.bash_path(source) + " " + File.bash_path(target)).check
   185       File.bash_path(source) + " " + File.bash_path(target)).check
   190   }
   186   }
   191 
   187 
   192   private def hinted_path(hinted: Boolean): Path =
   188   private def hinted_path(hinted: Boolean): Path =
   195   private val hinting = List(false, true)
   191   private val hinting = List(false, true)
   196 
   192 
   197 
   193 
   198   /* build fonts */
   194   /* build fonts */
   199 
   195 
   200   private def find_file(dirs: List[Path], name: String): Path =
   196   private def find_file(dirs: List[Path], name: String): Path = {
   201   {
       
   202     val path = Path.explode(name)
   197     val path = Path.explode(name)
   203     dirs.collectFirst({ case dir if (dir + path).is_file => dir + path }) match {
   198     dirs.collectFirst({ case dir if (dir + path).is_file => dir + path }) match {
   204       case Some(file) => file
   199       case Some(file) => file
   205       case None =>
   200       case None =>
   206         error(cat_lines(
   201         error(cat_lines(
   218     sources: List[Family] = default_sources,
   213     sources: List[Family] = default_sources,
   219     source_dirs: List[Path] = Nil,
   214     source_dirs: List[Path] = Nil,
   220     target_prefix: String = "Isabelle",
   215     target_prefix: String = "Isabelle",
   221     target_version: String = "",
   216     target_version: String = "",
   222     target_dir: Path = default_target_dir,
   217     target_dir: Path = default_target_dir,
   223     progress: Progress = new Progress): Unit =
   218     progress: Progress = new Progress
   224   {
   219   ): Unit = {
   225     Isabelle_System.require_command("ttfautohint")
   220     Isabelle_System.require_command("ttfautohint")
   226 
   221 
   227     progress.echo("Directory " + target_dir)
   222     progress.echo("Directory " + target_dir)
   228     hinting.foreach(hinted => Isabelle_System.make_directory(target_dir + hinted_path(hinted)))
   223     hinting.foreach(hinted => Isabelle_System.make_directory(target_dir + hinted_path(hinted)))
   229 
   224 
   241         val source_file = find_file(font_dirs, source_font)
   236         val source_file = find_file(font_dirs, source_font)
   242         val source_names = Fontforge.font_names(source_file)
   237         val source_names = Fontforge.font_names(source_file)
   243 
   238 
   244         val target_names = source_names.update(prefix = target_prefix, version = target_version)
   239         val target_names = source_names.update(prefix = target_prefix, version = target_version)
   245 
   240 
   246         Isabelle_System.with_tmp_file("font", "ttf")(tmp_file =>
   241         Isabelle_System.with_tmp_file("font", "ttf")(tmp_file => {
   247         {
       
   248           for (hinted <- hinting) {
   242           for (hinted <- hinting) {
   249             val target_file = target_dir + hinted_path(hinted) + target_names.ttf
   243             val target_file = target_dir + hinted_path(hinted) + target_names.ttf
   250             progress.echo("Font " + target_file.toString + " ...")
   244             progress.echo("Font " + target_file.toString + " ...")
   251 
   245 
   252             if (hinted) auto_hint(source_file, tmp_file)
   246             if (hinted) auto_hint(source_file, tmp_file)
   340 
   334 
   341 
   335 
   342   /* Isabelle tool wrapper */
   336   /* Isabelle tool wrapper */
   343 
   337 
   344   val isabelle_tool =
   338   val isabelle_tool =
   345     Isabelle_Tool("build_fonts", "construct Isabelle fonts", Scala_Project.here, args =>
   339     Isabelle_Tool("build_fonts", "construct Isabelle fonts", Scala_Project.here, args => {
   346     {
       
   347       var source_dirs: List[Path] = Nil
   340       var source_dirs: List[Path] = Nil
   348 
   341 
   349       val getopts = Getopts("""
   342       val getopts = Getopts("""
   350 Usage: isabelle build_fonts [OPTIONS]
   343 Usage: isabelle build_fonts [OPTIONS]
   351 
   344