14d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann// Copyright 2016 PDFium Authors. All rights reserved.
24d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann// Use of this source code is governed by a BSD-style license that can be
34d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann// found in the LICENSE file.
44d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
54d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
64d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
74d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fpdfapi/render/cpdf_type3cache.h"
84d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
94d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include <map>
104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include <memory>
11d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#include <utility>
124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fpdfapi/font/cpdf_type3char.h"
144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fpdfapi/font/cpdf_type3font.h"
154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fpdfapi/render/cpdf_type3glyphs.h"
164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fxge/fx_dib.h"
174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fxge/fx_font.h"
18d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#include "third_party/base/ptr_util.h"
194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannnamespace {
214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstruct CPDF_UniqueKeyGen {
234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  void Generate(int count, ...);
24d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  char m_Key[128];
254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  int m_KeyLen;
264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann};
274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannvoid CPDF_UniqueKeyGen::Generate(int count, ...) {
294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  va_list argList;
304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  va_start(argList, count);
314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  for (int i = 0; i < count; i++) {
324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    int p = va_arg(argList, int);
334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    (reinterpret_cast<uint32_t*>(m_Key))[i] = p;
344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  va_end(argList);
364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  m_KeyLen = count * sizeof(uint32_t);
374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannbool IsScanLine1bpp(uint8_t* pBuf, int width) {
404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  int size = width / 8;
414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  for (int i = 0; i < size; i++) {
424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (pBuf[i])
434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      return true;
444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return (width % 8) && (pBuf[width / 8] & (0xff << (8 - width % 8)));
464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannbool IsScanLine8bpp(uint8_t* pBuf, int width) {
494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  for (int i = 0; i < width; i++) {
504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (pBuf[i] > 0x40)
514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      return true;
524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return false;
544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
56d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannint DetectFirstLastScan(const RetainPtr<CFX_DIBitmap>& pBitmap, bool bFirst) {
574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  int height = pBitmap->GetHeight();
584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  int pitch = pBitmap->GetPitch();
594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  int width = pBitmap->GetWidth();
604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  int bpp = pBitmap->GetBPP();
614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (bpp > 8)
624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    width *= bpp / 8;
634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  uint8_t* pBuf = pBitmap->GetBuffer();
644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  int line = bFirst ? 0 : height - 1;
654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  int line_step = bFirst ? 1 : -1;
664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  int line_end = bFirst ? height : -1;
674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  while (line != line_end) {
684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (bpp == 1) {
694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (IsScanLine1bpp(pBuf + line * pitch, width))
704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        return line;
714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    } else {
724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (IsScanLine8bpp(pBuf + line * pitch, width))
734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        return line;
744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    }
754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    line += line_step;
764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return -1;
784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}  // namespace
814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. MoltmannCPDF_Type3Cache::CPDF_Type3Cache(CPDF_Type3Font* pFont) : m_pFont(pFont) {}
834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
84d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. MoltmannCPDF_Type3Cache::~CPDF_Type3Cache() {}
854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. MoltmannCFX_GlyphBitmap* CPDF_Type3Cache::LoadGlyph(uint32_t charcode,
874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                            const CFX_Matrix* pMatrix,
88d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                            float retinaScaleX,
89d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                            float retinaScaleY) {
904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  CPDF_UniqueKeyGen keygen;
914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  keygen.Generate(
924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      4, FXSYS_round(pMatrix->a * 10000), FXSYS_round(pMatrix->b * 10000),
934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      FXSYS_round(pMatrix->c * 10000), FXSYS_round(pMatrix->d * 10000));
94d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  ByteString FaceGlyphsKey(keygen.m_Key, keygen.m_KeyLen);
954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  CPDF_Type3Glyphs* pSizeCache;
964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  auto it = m_SizeMap.find(FaceGlyphsKey);
974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (it == m_SizeMap.end()) {
98d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    auto pNew = pdfium::MakeUnique<CPDF_Type3Glyphs>();
99d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    pSizeCache = pNew.get();
100d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    m_SizeMap[FaceGlyphsKey] = std::move(pNew);
1014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  } else {
102d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    pSizeCache = it->second.get();
1034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
1044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  auto it2 = pSizeCache->m_GlyphMap.find(charcode);
1054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (it2 != pSizeCache->m_GlyphMap.end())
106d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    return it2->second.get();
1074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
108d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  std::unique_ptr<CFX_GlyphBitmap> pNewBitmap =
1094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      RenderGlyph(pSizeCache, charcode, pMatrix, retinaScaleX, retinaScaleY);
110d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  CFX_GlyphBitmap* pGlyphBitmap = pNewBitmap.get();
111d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  pSizeCache->m_GlyphMap[charcode] = std::move(pNewBitmap);
1124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return pGlyphBitmap;
1134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
1144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
115d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannstd::unique_ptr<CFX_GlyphBitmap> CPDF_Type3Cache::RenderGlyph(
116d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    CPDF_Type3Glyphs* pSize,
117d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    uint32_t charcode,
118d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    const CFX_Matrix* pMatrix,
119d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    float retinaScaleX,
120d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    float retinaScaleY) {
1214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  const CPDF_Type3Char* pChar = m_pFont->LoadChar(charcode);
122d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (!pChar || !pChar->GetBitmap())
1234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return nullptr;
1244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
12533357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  CFX_Matrix text_matrix(pMatrix->a, pMatrix->b, pMatrix->c, pMatrix->d, 0, 0);
126d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  CFX_Matrix image_matrix = pChar->matrix();
1274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  image_matrix.Concat(text_matrix);
12833357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann
129d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  RetainPtr<CFX_DIBitmap> pBitmap = pChar->GetBitmap();
130d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  RetainPtr<CFX_DIBitmap> pResBitmap;
1314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  int left = 0;
1324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  int top = 0;
133d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (fabs(image_matrix.b) < fabs(image_matrix.a) / 100 &&
134d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      fabs(image_matrix.c) < fabs(image_matrix.d) / 100) {
1354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    int top_line = DetectFirstLastScan(pBitmap, true);
1364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    int bottom_line = DetectFirstLastScan(pBitmap, false);
1374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (top_line == 0 && bottom_line == pBitmap->GetHeight() - 1) {
138d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      float top_y = image_matrix.d + image_matrix.f;
139d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      float bottom_y = image_matrix.f;
1404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      bool bFlipped = top_y > bottom_y;
1414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (bFlipped) {
142d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        float temp = top_y;
1434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        top_y = bottom_y;
1444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        bottom_y = temp;
1454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
1464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      pSize->AdjustBlue(top_y, bottom_y, top_line, bottom_line);
1474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      pResBitmap = pBitmap->StretchTo(
148d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann          static_cast<int>(FXSYS_round(image_matrix.a) * retinaScaleX),
149d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann          static_cast<int>(
150d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann              (bFlipped ? top_line - bottom_line : bottom_line - top_line) *
151d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann              retinaScaleY),
152d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann          0, nullptr);
1534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      top = top_line;
1544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (image_matrix.a < 0) {
1554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        image_matrix.Scale(retinaScaleX, retinaScaleY);
1564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        left = FXSYS_round(image_matrix.e + image_matrix.a);
1574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      } else {
1584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        left = FXSYS_round(image_matrix.e);
1594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
1604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    }
1614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
1624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (!pResBitmap) {
1634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    image_matrix.Scale(retinaScaleX, retinaScaleY);
164d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    pResBitmap = pBitmap->TransformTo(&image_matrix, &left, &top);
1654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
1664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (!pResBitmap)
1674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return nullptr;
1684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
169d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  auto pGlyph = pdfium::MakeUnique<CFX_GlyphBitmap>();
1704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  pGlyph->m_Left = left;
1714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  pGlyph->m_Top = -top;
172d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  pGlyph->m_pBitmap->TakeOver(std::move(pResBitmap));
1734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return pGlyph;
1744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
175