のねのBlog

パソコンの問題や、ソフトウェアの開発で起きた問題など書いていきます。よろしくお願いします^^。

skia cmapその1

skia cmapその1

    486 SkAdvancedTypefaceMetrics* SkTypeface_FreeType::onGetAdvancedTypefaceMetrics(
    487         SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo,
    488         const uint32_t* glyphIDs,
    489         uint32_t glyphIDsCount) const {
    490 #if defined(SK_BUILD_FOR_MAC)
    491     return NULL;
    492 #else
    493     AutoFTAccess fta(this);
    494     FT_Face face = fta.face();
    495     if (!face) {
    496         return NULL;
    497     }
    498 
    499     SkAdvancedTypefaceMetrics* info = new SkAdvancedTypefaceMetrics;
    500     info->fFontName.set(FT_Get_Postscript_Name(face));
    501     info->fMultiMaster = FT_HAS_MULTIPLE_MASTERS(face);
    502     info->fLastGlyphID = face->num_glyphs - 1;
    503     info->fEmSize = 1000;
    504 
    505     bool cid = false;
    506     const char* fontType = FT_Get_X11_Font_Format(face);
    507     if (strcmp(fontType, "Type 1") == 0) {
    508         info->fType = SkAdvancedTypefaceMetrics::kType1_Font;

    509     } else if (strcmp(fontType, "CID Type 1") == 0) {
    510         info->fType = SkAdvancedTypefaceMetrics::kType1CID_Font;
    511         cid = true;

    512     } else if (strcmp(fontType, "CFF") == 0) {
    513         info->fType = SkAdvancedTypefaceMetrics::kCFF_Font;

    514     } else if (strcmp(fontType, "TrueType") == 0) {
    515         info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;
    516         cid = true;
    517         TT_Header* ttHeader;
    518         if ((ttHeader = (TT_Header*)FT_Get_Sfnt_Table(face,
    519                                                       ft_sfnt_head)) != NULL) {
    520             info->fEmSize = ttHeader->Units_Per_EM;
    521         }
    522     }
    523 
    524     info->fStyle = 0;
    525     if (FT_IS_FIXED_WIDTH(face))
    526         info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
    527     if (face->style_flags & FT_STYLE_FLAG_ITALIC)
    528         info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
    529 
    530     PS_FontInfoRec ps_info;
    531     TT_Postscript* tt_info;
    532     if (FT_Get_PS_Font_Info(face, &ps_info) == 0) {
    533         info->fItalicAngle = ps_info.italic_angle;
    534     } else if ((tt_info =
    535                 (TT_Postscript*)FT_Get_Sfnt_Table(face,
    536                                                   ft_sfnt_post)) != NULL) {
    537         info->fItalicAngle = SkFixedToScalar(tt_info->italicAngle);
    538     } else {
    539         info->fItalicAngle = 0;
    540     }
    541 
    542     info->fAscent = face->ascender;
    543     info->fDescent = face->descender;
    544 
    545     // Figure out a good guess for StemV - Min width of i, I, !, 1.
    546     // This probably isn't very good with an italic font.
    547     int16_t min_width = SHRT_MAX;
    548     info->fStemV = 0;
    549     char stem_chars[] = {'i', 'I', '!', '1'};
    550     for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) {
    551         FT_BBox bbox;
    552         if (GetLetterCBox(face, stem_chars[i], &bbox)) {
    553             int16_t width = bbox.xMax - bbox.xMin;
    554             if (width > 0 && width < min_width) {
    555                 min_width = width;
    556                 info->fStemV = min_width;
    557             }
    558         }
    559     }
    560 
    561     TT_PCLT* pclt_info;
    562     TT_OS2* os2_table;
    563     if ((pclt_info = (TT_PCLT*)FT_Get_Sfnt_Table(face, ft_sfnt_pclt)) != NULL) {
    564         info->fCapHeight = pclt_info->CapHeight;
    565         uint8_t serif_style = pclt_info->SerifStyle & 0x3F;
    566         if (serif_style >= 2 && serif_style <= 6)
    567             info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
    568         else if (serif_style >= 9 && serif_style <= 12)
    569             info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
    570     } else if ((os2_table =
    571                 (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2)) != NULL) {
    572         info->fCapHeight = os2_table->sCapHeight;
    573     } else {
    574         // Figure out a good guess for CapHeight: average the height of M and X.
    575         FT_BBox m_bbox, x_bbox;
    576         bool got_m, got_x;
    577         got_m = GetLetterCBox(face, 'M', &m_bbox);
    578         got_x = GetLetterCBox(face, 'X', &x_bbox);
    579         if (got_m && got_x) {
    580             info->fCapHeight = (m_bbox.yMax - m_bbox.yMin + x_bbox.yMax -
    581                     x_bbox.yMin) / 2;
    582         } else if (got_m && !got_x) {
    583             info->fCapHeight = m_bbox.yMax - m_bbox.yMin;
    584         } else if (!got_m && got_x) {
    585             info->fCapHeight = x_bbox.yMax - x_bbox.yMin;
    586         }
    587     }
    588 
    589     info->fBBox = SkIRect::MakeLTRB(face->bbox.xMin, face->bbox.yMax,
    590                                     face->bbox.xMax, face->bbox.yMin);
    591 
    592     if (!canEmbed(face) || !FT_IS_SCALABLE(face) ||
    593             info->fType == SkAdvancedTypefaceMetrics::kOther_Font) {
    594         perGlyphInfo = SkAdvancedTypefaceMetrics::kNo_PerGlyphInfo;
    595     }
    596 
    597     if (perGlyphInfo & SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) {
    598         if (FT_IS_FIXED_WIDTH(face)) {
    599             appendRange(&info->fGlyphWidths, 0);
    600             int16_t advance = face->max_advance_width;
    601             info->fGlyphWidths->fAdvance.append(1, &advance);
    602             finishRange(info->fGlyphWidths.get(), 0,
    603                         SkAdvancedTypefaceMetrics::WidthRange::kDefault);
    604         } else if (!cid) {
    605             appendRange(&info->fGlyphWidths, 0);
    606             // So as to not blow out the stack, get advances in batches.
    607             for (int gID = 0; gID < face->num_glyphs; gID += 128) {
    608                 FT_Fixed advances[128];
    609                 int advanceCount = 128;
    610                 if (gID + advanceCount > face->num_glyphs)
    611                     advanceCount = face->num_glyphs - gID + 1;
    612                 getAdvances(face, gID, advanceCount, FT_LOAD_NO_SCALE,
    613                             advances);
    614                 for (int i = 0; i < advanceCount; i++) {
    615                     int16_t advance = advances[i];
    616                     info->fGlyphWidths->fAdvance.append(1, &advance);
    617                 }
    618             }
    619             finishRange(info->fGlyphWidths.get(), face->num_glyphs - 1,
    620                         SkAdvancedTypefaceMetrics::WidthRange::kRange);
    621         } else {
    622             info->fGlyphWidths.reset(
    623                 getAdvanceData(face,
    624                                face->num_glyphs,
    625                                glyphIDs,
    626                                glyphIDsCount,
    627                                &getWidthAdvance));
    628         }
    629     }
    630 
    631     if (perGlyphInfo & SkAdvancedTypefaceMetrics::kVAdvance_PerGlyphInfo &&
    632             FT_HAS_VERTICAL(face)) {
    633         SkASSERT(false);  // Not implemented yet.
    634     }
    635 
    636     if (perGlyphInfo & SkAdvancedTypefaceMetrics::kGlyphNames_PerGlyphInfo &&
    637             info->fType == SkAdvancedTypefaceMetrics::kType1_Font) {
    638         // Postscript fonts may contain more than 255 glyphs, so we end up
    639         // using multiple font descriptions with a glyph ordering.  Record
    640         // the name of each glyph.
    641         info->fGlyphNames.reset(
    642                 new SkAutoTArray<SkString>(face->num_glyphs));
    643         for (int gID = 0; gID < face->num_glyphs; gID++) {
    644             char glyphName[128];  // PS limit for names is 127 bytes.
    645             FT_Get_Glyph_Name(face, gID, glyphName, 128);
    646             info->fGlyphNames->get()[gID].set(glyphName);
    647         }
    648     }
    649 
    650     if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo &&
    651            info->fType != SkAdvancedTypefaceMetrics::kType1_Font &&
    652            face->num_charmaps) {
    653         populate_glyph_to_unicode(face, &(info->fGlyphToUnicode)); <=====
    654     }
    655 
    656     if (!canEmbed(face))
    657         info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font;
    658 
    659     return info;
    660 #endif
    661 }
    436 static void populate_glyph_to_unicode(FT_Face& face,
    437                                       SkTDArray<SkUnichar>* glyphToUnicode) {
    438     // Check and see if we have Unicode cmaps.
    439     for (int i = 0; i < face->num_charmaps; ++i) {
    440         // CMaps known to support Unicode:
    441         // Platform ID   Encoding ID   Name
    442         // -----------   -----------   -----------------------------------
    443         // 0             0,1           Apple Unicode
    444         // 0             3             Apple Unicode 2.0 (preferred)
    445         // 3             1             Microsoft Unicode UCS-2
    446         // 3             10            Microsoft Unicode UCS-4 (preferred)
    447         //
    448         // See Apple TrueType Reference Manual
    449         // http://developer.apple.com/fonts/TTRefMan/RM06/Chap6cmap.html
    450         // http://developer.apple.com/fonts/TTRefMan/RM06/Chap6name.html#ID
    451         // Microsoft OpenType Specification
    452         // http://www.microsoft.com/typography/otspec/cmap.htm
    453 
    454         FT_UShort platformId = face->charmaps[i]->platform_id;
    455         FT_UShort encodingId = face->charmaps[i]->encoding_id;
    456 
    457         if (platformId != 0 && platformId != 3) {
    458             continue;
    459         }
    460         if (platformId == 3 && encodingId != 1 && encodingId != 10) {
    461             continue;
    462         }
    463         bool preferredMap = ((platformId == 3 && encodingId == 10) ||
    464                              (platformId == 0 && encodingId == 3));
    465 
    466         FT_Set_Charmap(face, face->charmaps[i]);
    467         if (glyphToUnicode->isEmpty()) {
    468             glyphToUnicode->setCount(face->num_glyphs);
    469             memset(glyphToUnicode->begin(), 0,
    470                    sizeof(SkUnichar) * face->num_glyphs);
    471         }
    472 
    473         // Iterate through each cmap entry.
    474         FT_UInt glyphIndex;
    475         for (SkUnichar charCode = FT_Get_First_Char(face, &glyphIndex);
    476              glyphIndex != 0;
    477              charCode = FT_Get_Next_Char(face, charCode, &glyphIndex)) {
    478             if (charCode &&
    479                     ((*glyphToUnicode)[glyphIndex] == 0 || preferredMap)) {
    480                 (*glyphToUnicode)[glyphIndex] = charCode;
    481             }
    482         }
    483     }
    484 }
     27 class SkAdvancedTypefaceMetrics : public SkRefCnt {
     28 public:
     29     SK_DECLARE_INST_COUNT(SkAdvancedTypefaceMetrics)
     30 
     31     SkString fFontName;
     32 
     33     enum FontType {
     34         kType1_Font,
     35         kType1CID_Font,
     36         kCFF_Font,
     37         kTrueType_Font,
     38         kOther_Font,
     39         kNotEmbeddable_Font
     40     };

     41     // The type of the underlying font program.  This field determines which
     42     // of the following fields are valid.  If it is kOther_Font or
     43     // kNotEmbeddable_Font, the per glyph information will never be populated.
     44     FontType fType;
     45 
     46     // fMultiMaster may be true for Type1_Font or CFF_Font.
     47     bool fMultiMaster;
     48     uint16_t fLastGlyphID; // The last valid glyph ID in the font.
     49     uint16_t fEmSize;  // The size of the em box (defines font units).
     50 
     51     // These enum values match the values used in the PDF file format.
     52     enum StyleFlags {
     53         kFixedPitch_Style  = 0x00001,
     54         kSerif_Style       = 0x00002,
     55         kScript_Style      = 0x00008,
     56         kItalic_Style      = 0x00040,
     57         kAllCaps_Style     = 0x10000,
     58         kSmallCaps_Style   = 0x20000,
     59         kForceBold_Style   = 0x40000
     60     };

     61     uint16_t fStyle;        // Font style characteristics.
     62     int16_t fItalicAngle;   // Counterclockwise degrees from vertical of the
     63                             // dominant vertical stroke for an Italic face.
     64     // The following fields are all in font units.
     65     int16_t fAscent;       // Max height above baseline, not including accents.
     66     int16_t fDescent;      // Max depth below baseline (negative).
     67     int16_t fStemV;        // Thickness of dominant vertical stem.
     68     int16_t fCapHeight;    // Height (from baseline) of top of flat capitals.
     69 
     70     SkIRect fBBox;  // The bounding box of all glyphs (in font units).
     71 
     72     // The type of advance data wanted.
     73     enum PerGlyphInfo {
     74       kNo_PerGlyphInfo         = 0x0, // Don't populate any per glyph info.
     75       kHAdvance_PerGlyphInfo   = 0x1, // Populate horizontal advance data.
     76       kVAdvance_PerGlyphInfo   = 0x2, // Populate vertical advance data.
     77       kGlyphNames_PerGlyphInfo = 0x4, // Populate glyph names (Type 1 only).
     78       kToUnicode_PerGlyphInfo  = 0x8  // Populate ToUnicode table, ignored
     79                                       // for Type 1 fonts
     80     };


     81 
     82     template <typename Data>
     83     struct AdvanceMetric {
     84         enum MetricType {
     85             kDefault,  // Default advance: fAdvance.count = 1
     86             kRange,    // Advances for a range: fAdvance.count = fEndID-fStartID
     87             kRun       // fStartID-fEndID have same advance: fAdvance.count = 1
     88         };
     89         MetricType fType;
     90         uint16_t fStartId;
     91         uint16_t fEndId;
     92         SkTDArray<Data> fAdvance;
     93         SkTScopedPtr<AdvanceMetric<Data> > fNext;
     94     };
     95 
     96     struct VerticalMetric {
     97         int16_t fVerticalAdvance;
     98         int16_t fOriginXDisp;  // Horiz. displacement of the secondary origin.
     99         int16_t fOriginYDisp;  // Vert. displacement of the secondary origin.
    100     };
    101     typedef AdvanceMetric<int16_t> WidthRange;
    102     typedef AdvanceMetric<VerticalMetric> VerticalAdvanceRange;
    103 
    104     // This is indexed by glyph id.
    105     SkTScopedPtr<WidthRange> fGlyphWidths;
    106     // Only used for Vertical CID fonts.
    107     SkTScopedPtr<VerticalAdvanceRange> fVerticalMetrics;
    108 
    109     // The names of each glyph, only populated for postscript fonts.
    110     SkTScopedPtr<SkAutoTArray<SkString> > fGlyphNames;
    111 
    112     // The mapping from glyph to Unicode, only populated if
    113     // kToUnicode_PerGlyphInfo is passed to GetAdvancedTypefaceMetrics.
    114     SkTDArray<SkUnichar> fGlyphToUnicode;
    115 
    116 private:
    117     typedef SkRefCnt INHERITED;
    118 };