Esempio n. 1
0
CPDF_Font* CPDF_Document::AddFont(CFX_Font* pFont, int charset, FX_BOOL bVert) {
  if (!pFont) {
    return NULL;
  }
  FX_BOOL bCJK = charset == FXFONT_CHINESEBIG5_CHARSET ||
                 charset == FXFONT_GB2312_CHARSET ||
                 charset == FXFONT_HANGEUL_CHARSET ||
                 charset == FXFONT_SHIFTJIS_CHARSET;
  CFX_ByteString basefont = pFont->GetFamilyName();
  basefont.Replace(" ", "");
  int flags = 0;
  if (pFont->IsBold()) {
    flags |= PDFFONT_FORCEBOLD;
  }
  if (pFont->IsItalic()) {
    flags |= PDFFONT_ITALIC;
  }
  if (pFont->IsFixedWidth()) {
    flags |= PDFFONT_FIXEDPITCH;
  }
  CPDF_Dictionary* pBaseDict = new CPDF_Dictionary;
  pBaseDict->SetAtName("Type", "Font");
  std::unique_ptr<CFX_UnicodeEncoding> pEncoding(
      new CFX_UnicodeEncoding(pFont));
  CPDF_Dictionary* pFontDict = pBaseDict;
  if (!bCJK) {
    CPDF_Array* pWidths = new CPDF_Array;
    int charcode;
    for (charcode = 32; charcode < 128; charcode++) {
      int glyph_index = pEncoding->GlyphFromCharCode(charcode);
      int char_width = pFont->GetGlyphWidth(glyph_index);
      pWidths->AddInteger(char_width);
    }
    if (charset == FXFONT_ANSI_CHARSET || charset == FXFONT_DEFAULT_CHARSET ||
        charset == FXFONT_SYMBOL_CHARSET) {
      if (charset == FXFONT_SYMBOL_CHARSET) {
        flags |= PDFFONT_SYMBOLIC;
      } else {
        flags |= PDFFONT_NONSYMBOLIC;
      }
      pBaseDict->SetAtName("Encoding", "WinAnsiEncoding");
      for (charcode = 128; charcode <= 255; charcode++) {
        int glyph_index = pEncoding->GlyphFromCharCode(charcode);
        int char_width = pFont->GetGlyphWidth(glyph_index);
        pWidths->AddInteger(char_width);
      }
    } else {
      flags |= PDFFONT_NONSYMBOLIC;
      size_t i;
      for (i = 0; i < sizeof g_FX_CharsetUnicodes / sizeof(FX_CharsetUnicodes);
           i++)
        if (g_FX_CharsetUnicodes[i].m_Charset == charset) {
          break;
        }
      if (i < sizeof g_FX_CharsetUnicodes / sizeof(FX_CharsetUnicodes)) {
        CPDF_Dictionary* pEncodingDict = new CPDF_Dictionary;
        pEncodingDict->SetAtName("BaseEncoding", "WinAnsiEncoding");
        CPDF_Array* pArray = new CPDF_Array;
        pArray->AddInteger(128);
        const FX_WCHAR* pUnicodes = g_FX_CharsetUnicodes[i].m_pUnicodes;
        for (int j = 0; j < 128; j++) {
          CFX_ByteString name = PDF_AdobeNameFromUnicode(pUnicodes[j]);
          if (name.IsEmpty()) {
            pArray->AddName(".notdef");
          } else {
            pArray->AddName(name);
          }
          int glyph_index = pEncoding->GlyphFromCharCode(pUnicodes[j]);
          int char_width = pFont->GetGlyphWidth(glyph_index);
          pWidths->AddInteger(char_width);
        }
        pEncodingDict->SetAt("Differences", pArray);
        AddIndirectObject(pEncodingDict);
        pBaseDict->SetAtReference("Encoding", this, pEncodingDict);
      }
    }
    if (pFont->IsBold() && pFont->IsItalic()) {
      basefont += ",BoldItalic";
    } else if (pFont->IsBold()) {
      basefont += ",Bold";
    } else if (pFont->IsItalic()) {
      basefont += ",Italic";
    }
    pBaseDict->SetAtName("Subtype", "TrueType");
    pBaseDict->SetAtName("BaseFont", basefont);
    pBaseDict->SetAtNumber("FirstChar", 32);
    pBaseDict->SetAtNumber("LastChar", 255);
    pBaseDict->SetAt("Widths", pWidths);
  } else {
    flags |= PDFFONT_NONSYMBOLIC;
    pFontDict = new CPDF_Dictionary;
    CFX_ByteString cmap;
    CFX_ByteString ordering;
    int supplement;
    CPDF_Array* pWidthArray = new CPDF_Array;
    switch (charset) {
      case FXFONT_CHINESEBIG5_CHARSET:
        cmap = bVert ? "ETenms-B5-V" : "ETenms-B5-H";
        ordering = "CNS1";
        supplement = 4;
        pWidthArray->AddInteger(1);
        _InsertWidthArray1(pFont, pEncoding.get(), 0x20, 0x7e, pWidthArray);
        break;
      case FXFONT_GB2312_CHARSET:
        cmap = bVert ? "GBK-EUC-V" : "GBK-EUC-H";
        ordering = "GB1", supplement = 2;
        pWidthArray->AddInteger(7716);
        _InsertWidthArray1(pFont, pEncoding.get(), 0x20, 0x20, pWidthArray);
        pWidthArray->AddInteger(814);
        _InsertWidthArray1(pFont, pEncoding.get(), 0x21, 0x7e, pWidthArray);
        break;
      case FXFONT_HANGEUL_CHARSET:
        cmap = bVert ? "KSCms-UHC-V" : "KSCms-UHC-H";
        ordering = "Korea1";
        supplement = 2;
        pWidthArray->AddInteger(1);
        _InsertWidthArray1(pFont, pEncoding.get(), 0x20, 0x7e, pWidthArray);
        break;
      case FXFONT_SHIFTJIS_CHARSET:
        cmap = bVert ? "90ms-RKSJ-V" : "90ms-RKSJ-H";
        ordering = "Japan1";
        supplement = 5;
        pWidthArray->AddInteger(231);
        _InsertWidthArray1(pFont, pEncoding.get(), 0x20, 0x7d, pWidthArray);
        pWidthArray->AddInteger(326);
        _InsertWidthArray1(pFont, pEncoding.get(), 0xa0, 0xa0, pWidthArray);
        pWidthArray->AddInteger(327);
        _InsertWidthArray1(pFont, pEncoding.get(), 0xa1, 0xdf, pWidthArray);
        pWidthArray->AddInteger(631);
        _InsertWidthArray1(pFont, pEncoding.get(), 0x7e, 0x7e, pWidthArray);
        break;
    }
    pBaseDict->SetAtName("Subtype", "Type0");
    pBaseDict->SetAtName("BaseFont", basefont);
    pBaseDict->SetAtName("Encoding", cmap);
    pFontDict->SetAt("W", pWidthArray);
    pFontDict->SetAtName("Type", "Font");
    pFontDict->SetAtName("Subtype", "CIDFontType2");
    pFontDict->SetAtName("BaseFont", basefont);
    CPDF_Dictionary* pCIDSysInfo = new CPDF_Dictionary;
    pCIDSysInfo->SetAtString("Registry", "Adobe");
    pCIDSysInfo->SetAtString("Ordering", ordering);
    pCIDSysInfo->SetAtInteger("Supplement", supplement);
    pFontDict->SetAt("CIDSystemInfo", pCIDSysInfo);
    CPDF_Array* pArray = new CPDF_Array;
    pBaseDict->SetAt("DescendantFonts", pArray);
    AddIndirectObject(pFontDict);
    pArray->AddReference(this, pFontDict);
  }
  AddIndirectObject(pBaseDict);
  CPDF_Dictionary* pFontDesc = new CPDF_Dictionary;
  pFontDesc->SetAtName("Type", "FontDescriptor");
  pFontDesc->SetAtName("FontName", basefont);
  pFontDesc->SetAtInteger("Flags", flags);
  pFontDesc->SetAtInteger(
      "ItalicAngle",
      pFont->GetSubstFont() ? pFont->GetSubstFont()->m_ItalicAngle : 0);
  pFontDesc->SetAtInteger("Ascent", pFont->GetAscent());
  pFontDesc->SetAtInteger("Descent", pFont->GetDescent());
  FX_RECT bbox;
  pFont->GetBBox(bbox);
  CPDF_Array* pBBox = new CPDF_Array;
  pBBox->AddInteger(bbox.left);
  pBBox->AddInteger(bbox.bottom);
  pBBox->AddInteger(bbox.right);
  pBBox->AddInteger(bbox.top);
  pFontDesc->SetAt("FontBBox", pBBox);
  int32_t nStemV = 0;
  if (pFont->GetSubstFont()) {
    nStemV = pFont->GetSubstFont()->m_Weight / 5;
  } else {
    static const FX_CHAR stem_chars[] = {'i', 'I', '!', '1'};
    const size_t count = sizeof(stem_chars) / sizeof(stem_chars[0]);
    FX_DWORD glyph = pEncoding->GlyphFromCharCode(stem_chars[0]);
    nStemV = pFont->GetGlyphWidth(glyph);
    for (size_t i = 1; i < count; i++) {
      glyph = pEncoding->GlyphFromCharCode(stem_chars[i]);
      int width = pFont->GetGlyphWidth(glyph);
      if (width > 0 && width < nStemV) {
        nStemV = width;
      }
    }
  }
  pFontDesc->SetAtInteger("StemV", nStemV);
  AddIndirectObject(pFontDesc);
  pFontDict->SetAtReference("FontDescriptor", this, pFontDesc);
  return LoadFont(pBaseDict);
}
Esempio n. 2
0
CPDF_Font* CPDF_Document::AddFont(CFX_Font* pFont, int charset, FX_BOOL bVert) {
  if (!pFont)
    return nullptr;

  bool bCJK = charset == FXFONT_CHINESEBIG5_CHARSET ||
              charset == FXFONT_GB2312_CHARSET ||
              charset == FXFONT_HANGUL_CHARSET ||
              charset == FXFONT_SHIFTJIS_CHARSET;
  CFX_ByteString basefont = pFont->GetFamilyName();
  basefont.Replace(" ", "");
  int flags =
      CalculateFlags(pFont->IsBold(), pFont->IsItalic(), pFont->IsFixedWidth(),
                     false, false, charset == FXFONT_SYMBOL_CHARSET);

  CPDF_Dictionary* pBaseDict = new CPDF_Dictionary(m_pByteStringPool);
  pBaseDict->SetNameFor("Type", "Font");
  std::unique_ptr<CFX_UnicodeEncoding> pEncoding(
      new CFX_UnicodeEncoding(pFont));
  CPDF_Dictionary* pFontDict = pBaseDict;
  if (!bCJK) {
    CPDF_Array* pWidths = new CPDF_Array;
    for (int charcode = 32; charcode < 128; charcode++) {
      int glyph_index = pEncoding->GlyphFromCharCode(charcode);
      int char_width = pFont->GetGlyphWidth(glyph_index);
      pWidths->AddInteger(char_width);
    }
    if (charset == FXFONT_ANSI_CHARSET || charset == FXFONT_DEFAULT_CHARSET ||
        charset == FXFONT_SYMBOL_CHARSET) {
      pBaseDict->SetNameFor("Encoding", "WinAnsiEncoding");
      for (int charcode = 128; charcode <= 255; charcode++) {
        int glyph_index = pEncoding->GlyphFromCharCode(charcode);
        int char_width = pFont->GetGlyphWidth(glyph_index);
        pWidths->AddInteger(char_width);
      }
    } else {
      size_t i = CalculateEncodingDict(charset, pBaseDict);
      if (i < FX_ArraySize(g_FX_CharsetUnicodes)) {
        const uint16_t* pUnicodes = g_FX_CharsetUnicodes[i].m_pUnicodes;
        for (int j = 0; j < 128; j++) {
          int glyph_index = pEncoding->GlyphFromCharCode(pUnicodes[j]);
          int char_width = pFont->GetGlyphWidth(glyph_index);
          pWidths->AddInteger(char_width);
        }
      }
    }
    ProcessNonbCJK(pBaseDict, pFont->IsBold(), pFont->IsItalic(), basefont,
                   pWidths);
  } else {
    pFontDict = ProcessbCJK(pBaseDict, charset, bVert, basefont,
                            [pFont, &pEncoding](FX_WCHAR start, FX_WCHAR end,
                                                CPDF_Array* widthArr) {
                              InsertWidthArray1(pFont, pEncoding.get(), start,
                                                end, widthArr);
                            });
  }
  AddIndirectObject(pBaseDict);
  int italicangle =
      pFont->GetSubstFont() ? pFont->GetSubstFont()->m_ItalicAngle : 0;
  FX_RECT bbox;
  pFont->GetBBox(bbox);
  CPDF_Array* pBBox = new CPDF_Array;
  pBBox->AddInteger(bbox.left);
  pBBox->AddInteger(bbox.bottom);
  pBBox->AddInteger(bbox.right);
  pBBox->AddInteger(bbox.top);
  int32_t nStemV = 0;
  if (pFont->GetSubstFont()) {
    nStemV = pFont->GetSubstFont()->m_Weight / 5;
  } else {
    static const FX_CHAR stem_chars[] = {'i', 'I', '!', '1'};
    const size_t count = FX_ArraySize(stem_chars);
    uint32_t glyph = pEncoding->GlyphFromCharCode(stem_chars[0]);
    nStemV = pFont->GetGlyphWidth(glyph);
    for (size_t i = 1; i < count; i++) {
      glyph = pEncoding->GlyphFromCharCode(stem_chars[i]);
      int width = pFont->GetGlyphWidth(glyph);
      if (width > 0 && width < nStemV)
        nStemV = width;
    }
  }
  CPDF_Dictionary* pFontDesc =
      CalculateFontDesc(this, basefont, flags, italicangle, pFont->GetAscent(),
                        pFont->GetDescent(), pBBox, nStemV);
  pFontDict->SetReferenceFor("FontDescriptor", this,
                             AddIndirectObject(pFontDesc));
  return LoadFont(pBaseDict);
}