LCOV - code coverage report
Current view: top level - gfx/ots/src - os2.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 193 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 6 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2009 The Chromium Authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include <string>
       6             : 
       7             : #include "os2.h"
       8             : #include "head.h"
       9             : 
      10             : // OS/2 - OS/2 and Windows Metrics
      11             : // http://www.microsoft.com/typography/otspec/os2.htm
      12             : 
      13             : #define TABLE_NAME "OS/2"
      14             : 
      15             : namespace ots {
      16             : 
      17           0 : bool ots_os2_parse(Font *font, const uint8_t *data, size_t length) {
      18           0 :   Buffer table(data, length);
      19             : 
      20           0 :   OpenTypeOS2 *os2 = new OpenTypeOS2;
      21           0 :   font->os2 = os2;
      22             : 
      23           0 :   if (!table.ReadU16(&os2->version) ||
      24           0 :       !table.ReadS16(&os2->avg_char_width) ||
      25           0 :       !table.ReadU16(&os2->weight_class) ||
      26           0 :       !table.ReadU16(&os2->width_class) ||
      27           0 :       !table.ReadU16(&os2->type) ||
      28           0 :       !table.ReadS16(&os2->subscript_x_size) ||
      29           0 :       !table.ReadS16(&os2->subscript_y_size) ||
      30           0 :       !table.ReadS16(&os2->subscript_x_offset) ||
      31           0 :       !table.ReadS16(&os2->subscript_y_offset) ||
      32           0 :       !table.ReadS16(&os2->superscript_x_size) ||
      33           0 :       !table.ReadS16(&os2->superscript_y_size) ||
      34           0 :       !table.ReadS16(&os2->superscript_x_offset) ||
      35           0 :       !table.ReadS16(&os2->superscript_y_offset) ||
      36           0 :       !table.ReadS16(&os2->strikeout_size) ||
      37           0 :       !table.ReadS16(&os2->strikeout_position) ||
      38           0 :       !table.ReadS16(&os2->family_class)) {
      39           0 :     return OTS_FAILURE_MSG("Error reading basic table elements");
      40             :   }
      41             : 
      42           0 :   if (os2->version > 5) {
      43           0 :     return OTS_FAILURE_MSG("Unsupported table version: %u", os2->version);
      44             :   }
      45             : 
      46             :   // Follow WPF Font Selection Model's advice.
      47           0 :   if (1 <= os2->weight_class && os2->weight_class <= 9) {
      48           0 :     OTS_WARNING("Bad usWeightClass: %u, changing it to: %u", os2->weight_class, os2->weight_class * 100);
      49           0 :     os2->weight_class *= 100;
      50             :   }
      51             :   // Ditto.
      52           0 :   if (os2->weight_class > 999) {
      53           0 :     OTS_WARNING("Bad usWeightClass: %u, changing it to: %d", os2->weight_class, 999);
      54           0 :     os2->weight_class = 999;
      55             :   }
      56             : 
      57           0 :   if (os2->width_class < 1) {
      58           0 :     OTS_WARNING("Bad usWidthClass: %u, changing it to: %d", os2->width_class, 1);
      59           0 :     os2->width_class = 1;
      60           0 :   } else if (os2->width_class > 9) {
      61           0 :     OTS_WARNING("Bad usWidthClass: %u, changing it to: %d", os2->width_class, 9);
      62           0 :     os2->width_class = 9;
      63             :   }
      64             : 
      65             :   // lowest 3 bits of fsType are exclusive.
      66           0 :   if (os2->type & 0x2) {
      67             :     // mask bits 2 & 3.
      68           0 :     os2->type &= 0xfff3u;
      69           0 :   } else if (os2->type & 0x4) {
      70             :     // mask bits 1 & 3.
      71           0 :     os2->type &= 0xfff4u;
      72           0 :   } else if (os2->type & 0x8) {
      73             :     // mask bits 1 & 2.
      74           0 :     os2->type &= 0xfff9u;
      75             :   }
      76             : 
      77             :   // mask reserved bits. use only 0..3, 8, 9 bits.
      78           0 :   os2->type &= 0x30f;
      79             : 
      80             : #define SET_TO_ZERO(a, b)                                     \
      81             :   if (os2->b < 0) {                                           \
      82             :     OTS_WARNING("Bad " a ": %d, setting it to zero", os2->b); \
      83             :     os2->b = 0;                                               \
      84             :   }
      85             : 
      86           0 :   SET_TO_ZERO("ySubscriptXSize", subscript_x_size);
      87           0 :   SET_TO_ZERO("ySubscriptYSize", subscript_y_size);
      88           0 :   SET_TO_ZERO("ySuperscriptXSize", superscript_x_size);
      89           0 :   SET_TO_ZERO("ySuperscriptYSize", superscript_y_size);
      90           0 :   SET_TO_ZERO("yStrikeoutSize", strikeout_size);
      91             : #undef SET_TO_ZERO
      92             : 
      93             :   static std::string panose_strings[10] = {
      94             :     "bFamilyType",
      95             :     "bSerifStyle",
      96             :     "bWeight",
      97             :     "bProportion",
      98             :     "bContrast",
      99             :     "bStrokeVariation",
     100             :     "bArmStyle",
     101             :     "bLetterform",
     102             :     "bMidline",
     103             :     "bXHeight",
     104           0 :   };
     105           0 :   for (unsigned i = 0; i < 10; ++i) {
     106           0 :     if (!table.ReadU8(&os2->panose[i])) {
     107           0 :       return OTS_FAILURE_MSG("Error reading PANOSE %s", panose_strings[i].c_str());
     108             :     }
     109             :   }
     110             : 
     111           0 :   if (!table.ReadU32(&os2->unicode_range_1) ||
     112           0 :       !table.ReadU32(&os2->unicode_range_2) ||
     113           0 :       !table.ReadU32(&os2->unicode_range_3) ||
     114           0 :       !table.ReadU32(&os2->unicode_range_4) ||
     115           0 :       !table.ReadU32(&os2->vendor_id) ||
     116           0 :       !table.ReadU16(&os2->selection) ||
     117           0 :       !table.ReadU16(&os2->first_char_index) ||
     118           0 :       !table.ReadU16(&os2->last_char_index) ||
     119           0 :       !table.ReadS16(&os2->typo_ascender) ||
     120           0 :       !table.ReadS16(&os2->typo_descender) ||
     121           0 :       !table.ReadS16(&os2->typo_linegap) ||
     122           0 :       !table.ReadU16(&os2->win_ascent) ||
     123           0 :       !table.ReadU16(&os2->win_descent)) {
     124           0 :     return OTS_FAILURE_MSG("Error reading more basic table fields");
     125             :   }
     126             : 
     127             :   // If bit 6 is set, then bits 0 and 5 must be clear.
     128           0 :   if (os2->selection & 0x40) {
     129           0 :     os2->selection &= 0xffdeu;
     130             :   }
     131             : 
     132             :   // the settings of bits 0 and 1 must be reflected in the macStyle bits
     133             :   // in the 'head' table.
     134           0 :   if (!font->head) {
     135           0 :     return OTS_FAILURE_MSG("Needed head table is missing from the font");
     136             :   }
     137           0 :   if ((os2->selection & 0x1) &&
     138           0 :       !(font->head->mac_style & 0x2)) {
     139           0 :     OTS_WARNING("adjusting Mac style (italic)");
     140           0 :     font->head->mac_style |= 0x2;
     141             :   }
     142           0 :   if ((os2->selection & 0x2) &&
     143           0 :       !(font->head->mac_style & 0x4)) {
     144           0 :     OTS_WARNING("adjusting Mac style (underscore)");
     145           0 :     font->head->mac_style |= 0x4;
     146             :   }
     147             : 
     148             :   // While bit 6 on implies that bits 0 and 1 of macStyle are clear,
     149             :   // the reverse is not true.
     150           0 :   if ((os2->selection & 0x40) &&
     151           0 :       (font->head->mac_style & 0x3)) {
     152           0 :     OTS_WARNING("adjusting Mac style (regular)");
     153           0 :     font->head->mac_style &= 0xfffcu;
     154             :   }
     155             : 
     156           0 :   if ((os2->version < 4) &&
     157           0 :       (os2->selection & 0x300)) {
     158             :     // bit 8 and 9 must be unset in OS/2 table versions less than 4.
     159           0 :     return OTS_FAILURE_MSG("Version %d incompatible with selection %d", os2->version, os2->selection);
     160             :   }
     161             : 
     162             :   // mask reserved bits. use only 0..9 bits.
     163           0 :   os2->selection &= 0x3ff;
     164             : 
     165           0 :   if (os2->first_char_index > os2->last_char_index) {
     166           0 :     return OTS_FAILURE_MSG("first char index %d > last char index %d in os2", os2->first_char_index, os2->last_char_index);
     167             :   }
     168           0 :   if (os2->typo_linegap < 0) {
     169           0 :     OTS_WARNING("bad linegap: %d", os2->typo_linegap);
     170           0 :     os2->typo_linegap = 0;
     171             :   }
     172             : 
     173           0 :   if (os2->version < 1) {
     174             :     // http://www.microsoft.com/typography/otspec/os2ver0.htm
     175           0 :     return true;
     176             :   }
     177             : 
     178           0 :   if (length < offsetof(OpenTypeOS2, code_page_range_2)) {
     179           0 :     OTS_WARNING("bad version number: %u", os2->version);
     180             :     // Some fonts (e.g., kredit1.ttf and quinquef.ttf) have weird version
     181             :     // numbers. Fix them.
     182           0 :     os2->version = 0;
     183           0 :     return true;
     184             :   }
     185             : 
     186           0 :   if (!table.ReadU32(&os2->code_page_range_1) ||
     187           0 :       !table.ReadU32(&os2->code_page_range_2)) {
     188           0 :     return OTS_FAILURE_MSG("Failed to read codepage ranges");
     189             :   }
     190             : 
     191           0 :   if (os2->version < 2) {
     192             :     // http://www.microsoft.com/typography/otspec/os2ver1.htm
     193           0 :     return true;
     194             :   }
     195             : 
     196           0 :   if (length < offsetof(OpenTypeOS2, max_context)) {
     197           0 :     OTS_WARNING("bad version number: %u", os2->version);
     198             :     // some Japanese fonts (e.g., mona.ttf) have weird version number.
     199             :     // fix them.
     200           0 :     os2->version = 1;
     201           0 :     return true;
     202             :   }
     203             : 
     204           0 :   if (!table.ReadS16(&os2->x_height) ||
     205           0 :       !table.ReadS16(&os2->cap_height) ||
     206           0 :       !table.ReadU16(&os2->default_char) ||
     207           0 :       !table.ReadU16(&os2->break_char) ||
     208           0 :       !table.ReadU16(&os2->max_context)) {
     209           0 :     return OTS_FAILURE_MSG("Failed to read version 2-specific fields");
     210             :   }
     211             : 
     212           0 :   if (os2->x_height < 0) {
     213           0 :     OTS_WARNING("bad x_height: %d", os2->x_height);
     214           0 :     os2->x_height = 0;
     215             :   }
     216           0 :   if (os2->cap_height < 0) {
     217           0 :     OTS_WARNING("bad cap_height: %d", os2->cap_height);
     218           0 :     os2->cap_height = 0;
     219             :   }
     220             : 
     221           0 :   if (os2->version < 5) {
     222             :     // http://www.microsoft.com/typography/otspec/os2ver4.htm
     223           0 :     return true;
     224             :   }
     225             : 
     226           0 :   if (!table.ReadU16(&os2->lower_optical_pointsize) ||
     227           0 :       !table.ReadU16(&os2->upper_optical_pointsize)) {
     228           0 :     return OTS_FAILURE_MSG("Failed to read version 5-specific fields");
     229             :   }
     230             : 
     231           0 :   if (os2->lower_optical_pointsize > 0xFFFE) {
     232           0 :     OTS_WARNING("'usLowerOpticalPointSize' is bigger than 0xFFFE: %d", os2->lower_optical_pointsize);
     233           0 :     os2->lower_optical_pointsize = 0xFFFE;
     234             :   }
     235             : 
     236           0 :   if (os2->upper_optical_pointsize < 2) {
     237           0 :     OTS_WARNING("'usUpperOpticalPointSize' is lower than 2: %d", os2->upper_optical_pointsize);
     238           0 :     os2->upper_optical_pointsize = 2;
     239             :   }
     240             : 
     241           0 :   return true;
     242             : }
     243             : 
     244           0 : bool ots_os2_should_serialise(Font *font) {
     245           0 :   return font->os2 != NULL;
     246             : }
     247             : 
     248           0 : bool ots_os2_serialise(OTSStream *out, Font *font) {
     249           0 :   const OpenTypeOS2 *os2 = font->os2;
     250             : 
     251           0 :   if (!out->WriteU16(os2->version) ||
     252           0 :       !out->WriteS16(os2->avg_char_width) ||
     253           0 :       !out->WriteU16(os2->weight_class) ||
     254           0 :       !out->WriteU16(os2->width_class) ||
     255           0 :       !out->WriteU16(os2->type) ||
     256           0 :       !out->WriteS16(os2->subscript_x_size) ||
     257           0 :       !out->WriteS16(os2->subscript_y_size) ||
     258           0 :       !out->WriteS16(os2->subscript_x_offset) ||
     259           0 :       !out->WriteS16(os2->subscript_y_offset) ||
     260           0 :       !out->WriteS16(os2->superscript_x_size) ||
     261           0 :       !out->WriteS16(os2->superscript_y_size) ||
     262           0 :       !out->WriteS16(os2->superscript_x_offset) ||
     263           0 :       !out->WriteS16(os2->superscript_y_offset) ||
     264           0 :       !out->WriteS16(os2->strikeout_size) ||
     265           0 :       !out->WriteS16(os2->strikeout_position) ||
     266           0 :       !out->WriteS16(os2->family_class)) {
     267           0 :     return OTS_FAILURE_MSG("Failed to write basic OS2 information");
     268             :   }
     269             : 
     270           0 :   for (unsigned i = 0; i < 10; ++i) {
     271           0 :     if (!out->Write(&os2->panose[i], 1)) {
     272           0 :       return OTS_FAILURE_MSG("Failed to write os2 panose information");
     273             :     }
     274             :   }
     275             : 
     276           0 :   if (!out->WriteU32(os2->unicode_range_1) ||
     277           0 :       !out->WriteU32(os2->unicode_range_2) ||
     278           0 :       !out->WriteU32(os2->unicode_range_3) ||
     279           0 :       !out->WriteU32(os2->unicode_range_4) ||
     280           0 :       !out->WriteU32(os2->vendor_id) ||
     281           0 :       !out->WriteU16(os2->selection) ||
     282           0 :       !out->WriteU16(os2->first_char_index) ||
     283           0 :       !out->WriteU16(os2->last_char_index) ||
     284           0 :       !out->WriteS16(os2->typo_ascender) ||
     285           0 :       !out->WriteS16(os2->typo_descender) ||
     286           0 :       !out->WriteS16(os2->typo_linegap) ||
     287           0 :       !out->WriteU16(os2->win_ascent) ||
     288           0 :       !out->WriteU16(os2->win_descent)) {
     289           0 :     return OTS_FAILURE_MSG("Failed to write version 1-specific fields");
     290             :   }
     291             : 
     292           0 :   if (os2->version < 1) {
     293           0 :     return true;
     294             :   }
     295             : 
     296           0 :   if (!out->WriteU32(os2->code_page_range_1) ||
     297           0 :       !out->WriteU32(os2->code_page_range_2)) {
     298           0 :     return OTS_FAILURE_MSG("Failed to write codepage ranges");
     299             :   }
     300             : 
     301           0 :   if (os2->version < 2) {
     302           0 :     return true;
     303             :   }
     304             : 
     305           0 :   if (!out->WriteS16(os2->x_height) ||
     306           0 :       !out->WriteS16(os2->cap_height) ||
     307           0 :       !out->WriteU16(os2->default_char) ||
     308           0 :       !out->WriteU16(os2->break_char) ||
     309           0 :       !out->WriteU16(os2->max_context)) {
     310           0 :     return OTS_FAILURE_MSG("Failed to write version 2-specific fields");
     311             :   }
     312             : 
     313           0 :   if (os2->version < 5) {
     314           0 :     return true;
     315             :   }
     316             : 
     317           0 :   if (!out->WriteU16(os2->lower_optical_pointsize) ||
     318           0 :       !out->WriteU16(os2->upper_optical_pointsize)) {
     319           0 :     return OTS_FAILURE_MSG("Failed to write version 5-specific fields");
     320             :   }
     321             : 
     322           0 :   return true;
     323             : }
     324             : 
     325           0 : void ots_os2_reuse(Font *font, Font *other) {
     326           0 :   font->os2 = other->os2;
     327           0 :   font->os2_reused = true;
     328           0 : }
     329             : 
     330           0 : void ots_os2_free(Font *font) {
     331           0 :   delete font->os2;
     332           0 : }
     333             : 
     334             : }  // namespace ots
     335             : 
     336             : #undef TABLE_NAME

Generated by: LCOV version 1.13