Пример #1
0
CFX_GlyphBitmap* CPDF_Type3Cache::LoadGlyph(FX_DWORD charcode,
                                            const CFX_AffineMatrix* pMatrix,
                                            FX_FLOAT retinaScaleX,
                                            FX_FLOAT retinaScaleY) {
  _CPDF_UniqueKeyGen keygen;
  keygen.Generate(
      4, FXSYS_round(pMatrix->a * 10000), FXSYS_round(pMatrix->b * 10000),
      FXSYS_round(pMatrix->c * 10000), FXSYS_round(pMatrix->d * 10000));
  CFX_ByteStringC FaceGlyphsKey(keygen.m_Key, keygen.m_KeyLen);
  CPDF_Type3Glyphs* pSizeCache;
  auto it = m_SizeMap.find(FaceGlyphsKey);
  if (it == m_SizeMap.end()) {
    pSizeCache = new CPDF_Type3Glyphs;
    m_SizeMap[FaceGlyphsKey] = pSizeCache;
  } else {
    pSizeCache = it->second;
  }
  CFX_GlyphBitmap* pGlyphBitmap;
  if (pSizeCache->m_GlyphMap.Lookup((void*)(uintptr_t)charcode,
                                    (void*&)pGlyphBitmap)) {
    return pGlyphBitmap;
  }
  pGlyphBitmap =
      RenderGlyph(pSizeCache, charcode, pMatrix, retinaScaleX, retinaScaleY);
  pSizeCache->m_GlyphMap.SetAt((void*)(uintptr_t)charcode, pGlyphBitmap);
  return pGlyphBitmap;
}
Пример #2
0
CFX_GlyphBitmap* CPDF_Type3Cache::RenderGlyph(CPDF_Type3Glyphs* pSize,
                                              FX_DWORD charcode,
                                              const CFX_AffineMatrix* pMatrix,
                                              FX_FLOAT retinaScaleX,
                                              FX_FLOAT retinaScaleY) {
  const CPDF_Type3Char* pChar = m_pFont->LoadChar(charcode);
  if (!pChar || !pChar->m_pBitmap)
    return nullptr;

  CFX_DIBitmap* pBitmap = pChar->m_pBitmap;
  CFX_AffineMatrix image_matrix, text_matrix;
  image_matrix = pChar->m_ImageMatrix;
  text_matrix.Set(pMatrix->a, pMatrix->b, pMatrix->c, pMatrix->d, 0, 0);
  image_matrix.Concat(text_matrix);
  CFX_DIBitmap* pResBitmap = NULL;
  int left, top;
  if (FXSYS_fabs(image_matrix.b) < FXSYS_fabs(image_matrix.a) / 100 &&
      FXSYS_fabs(image_matrix.c) < FXSYS_fabs(image_matrix.d) / 100) {
    int top_line, bottom_line;
    top_line = _DetectFirstLastScan(pBitmap, TRUE);
    bottom_line = _DetectFirstLastScan(pBitmap, FALSE);
    if (top_line == 0 && bottom_line == pBitmap->GetHeight() - 1) {
      FX_FLOAT top_y = image_matrix.d + image_matrix.f;
      FX_FLOAT bottom_y = image_matrix.f;
      FX_BOOL bFlipped = top_y > bottom_y;
      if (bFlipped) {
        FX_FLOAT temp = top_y;
        top_y = bottom_y;
        bottom_y = temp;
      }
      pSize->AdjustBlue(top_y, bottom_y, top_line, bottom_line);
      pResBitmap = pBitmap->StretchTo(
          (int)(FXSYS_round(image_matrix.a) * retinaScaleX),
          (int)((bFlipped ? top_line - bottom_line : bottom_line - top_line) *
                retinaScaleY));
      top = top_line;
      if (image_matrix.a < 0) {
        image_matrix.Scale(retinaScaleX, retinaScaleY);
        left = FXSYS_round(image_matrix.e + image_matrix.a);
      } else {
        left = FXSYS_round(image_matrix.e);
      }
    } else {
    }
  }
  if (pResBitmap == NULL) {
    image_matrix.Scale(retinaScaleX, retinaScaleY);
    pResBitmap = pBitmap->TransformTo(&image_matrix, left, top);
  }
  if (pResBitmap == NULL) {
    return NULL;
  }
  CFX_GlyphBitmap* pGlyph = new CFX_GlyphBitmap;
  pGlyph->m_Left = left;
  pGlyph->m_Top = -top;
  pGlyph->m_Bitmap.TakeOver(pResBitmap);
  delete pResBitmap;
  return pGlyph;
}
Пример #3
0
void CPDF_Type3Char::InitializeFromStreamData(bool bColored,
                                              const float* pData) {
  m_bColored = bColored;
  m_Width = FXSYS_round(TextUnitToGlyphUnit(pData[0]));
  m_BBox.left = FXSYS_round(TextUnitToGlyphUnit(pData[2]));
  m_BBox.bottom = FXSYS_round(TextUnitToGlyphUnit(pData[3]));
  m_BBox.right = FXSYS_round(TextUnitToGlyphUnit(pData[4]));
  m_BBox.top = FXSYS_round(TextUnitToGlyphUnit(pData[5]));
}
Пример #4
0
FX_BOOL FDE_ParseCSSColor(const FX_WCHAR* pszValue,
                          int32_t iValueLen,
                          FX_ARGB& dwColor) {
  FXSYS_assert(pszValue != NULL && iValueLen > 0);
  if (*pszValue == '#') {
    switch (iValueLen) {
      case 4: {
        uint8_t red = FX_Hex2Dec((uint8_t)pszValue[1], (uint8_t)pszValue[1]);
        uint8_t green = FX_Hex2Dec((uint8_t)pszValue[2], (uint8_t)pszValue[2]);
        uint8_t blue = FX_Hex2Dec((uint8_t)pszValue[3], (uint8_t)pszValue[3]);
        dwColor = ArgbEncode(255, red, green, blue);
      }
        return TRUE;
      case 7: {
        uint8_t red = FX_Hex2Dec((uint8_t)pszValue[1], (uint8_t)pszValue[2]);
        uint8_t green = FX_Hex2Dec((uint8_t)pszValue[3], (uint8_t)pszValue[4]);
        uint8_t blue = FX_Hex2Dec((uint8_t)pszValue[5], (uint8_t)pszValue[6]);
        dwColor = ArgbEncode(255, red, green, blue);
      }
        return TRUE;
    }
  } else if (iValueLen >= 10) {
    if (pszValue[iValueLen - 1] != ')' || FX_wcsnicmp(L"rgb(", pszValue, 4)) {
      return FALSE;
    }
    uint8_t rgb[3] = {0};
    FX_FLOAT fValue;
    FDE_CSSPRIMITIVETYPE eType;
    CFDE_CSSValueListParser list(pszValue + 4, iValueLen - 5, ',');
    for (int32_t i = 0; i < 3; ++i) {
      if (!list.NextValue(eType, pszValue, iValueLen)) {
        return FALSE;
      }
      if (eType != FDE_CSSPRIMITIVETYPE_Number) {
        return FALSE;
      }
      if (!FDE_ParseCSSNumber(pszValue, iValueLen, fValue, eType)) {
        return FALSE;
      }
      rgb[i] = eType == FDE_CSSPRIMITIVETYPE_Percent
                   ? FXSYS_round(fValue * 2.55f)
                   : FXSYS_round(fValue);
    }
    dwColor = ArgbEncode(255, rgb[0], rgb[1], rgb[2]);
    return TRUE;
  } else {
    FDE_LPCCSSCOLORTABLE pColor = FDE_GetCSSColorByName(pszValue, iValueLen);
    if (pColor != NULL) {
      dwColor = pColor->dwValue;
      return TRUE;
    }
  }
  return FALSE;
}
Пример #5
0
void CFX_Matrix::TransformRect(CFX_Rect& rect) const {
    FX_FLOAT left = (FX_FLOAT)rect.left;
    FX_FLOAT top = (FX_FLOAT)rect.bottom();
    FX_FLOAT right = (FX_FLOAT)rect.right();
    FX_FLOAT bottom = (FX_FLOAT)rect.top;
    TransformRect(left, right, top, bottom);
    rect.left = FXSYS_round(left);
    rect.top = FXSYS_round(bottom);
    rect.width = FXSYS_round(right - left);
    rect.height = FXSYS_round(top - bottom);
}
Пример #6
0
CPDF_Type3Char* CPDF_Type3Font::LoadChar(uint32_t charcode, int level) {
  if (level >= _FPDF_MAX_TYPE3_FORM_LEVEL_)
    return nullptr;

  auto it = m_CacheMap.find(charcode);
  if (it != m_CacheMap.end())
    return it->second;

  const FX_CHAR* name =
      GetAdobeCharName(m_BaseEncoding, m_pCharNames, charcode);
  if (!name)
    return nullptr;

  CPDF_Stream* pStream =
      ToStream(m_pCharProcs ? m_pCharProcs->GetDirectObjectBy(name) : nullptr);
  if (!pStream)
    return nullptr;

  std::unique_ptr<CPDF_Type3Char> pNewChar(new CPDF_Type3Char(new CPDF_Form(
      m_pDocument, m_pFontResources ? m_pFontResources : m_pPageResources,
      pStream, nullptr)));

  // This can trigger recursion into this method. The content of |m_CacheMap|
  // can change as a result. Thus after it returns, check the cache again for
  // a cache hit.
  pNewChar->m_pForm->ParseContent(nullptr, nullptr, pNewChar.get(), level + 1);
  it = m_CacheMap.find(charcode);
  if (it != m_CacheMap.end())
    return it->second;

  FX_FLOAT scale = m_FontMatrix.GetXUnit();
  pNewChar->m_Width = (int32_t)(pNewChar->m_Width * scale + 0.5f);
  FX_RECT& rcBBox = pNewChar->m_BBox;
  CFX_FloatRect char_rect(
      (FX_FLOAT)rcBBox.left / 1000.0f, (FX_FLOAT)rcBBox.bottom / 1000.0f,
      (FX_FLOAT)rcBBox.right / 1000.0f, (FX_FLOAT)rcBBox.top / 1000.0f);
  if (rcBBox.right <= rcBBox.left || rcBBox.bottom >= rcBBox.top)
    char_rect = pNewChar->m_pForm->CalcBoundingBox();

  char_rect.Transform(&m_FontMatrix);
  rcBBox.left = FXSYS_round(char_rect.left * 1000);
  rcBBox.right = FXSYS_round(char_rect.right * 1000);
  rcBBox.top = FXSYS_round(char_rect.top * 1000);
  rcBBox.bottom = FXSYS_round(char_rect.bottom * 1000);

  ASSERT(!pdfium::ContainsKey(m_CacheMap, charcode));
  CPDF_Type3Char* pCachedChar = pNewChar.release();
  m_CacheMap[charcode] = pCachedChar;
  if (pCachedChar->m_pForm->GetPageObjectList()->empty())
    pCachedChar->m_pForm.reset();
  return pCachedChar;
}
Пример #7
0
FX_DWORD CPDF_Bookmark::GetColorRef() const {
  if (!m_pDict) {
    return 0;
  }
  CPDF_Array* pColor = m_pDict->GetArray("C");
  if (!pColor) {
    return FXSYS_RGB(0, 0, 0);
  }
  int r = FXSYS_round(pColor->GetNumber(0) * 255);
  int g = FXSYS_round(pColor->GetNumber(1) * 255);
  int b = FXSYS_round(pColor->GetNumber(2) * 255);
  return FXSYS_RGB(r, g, b);
}
Пример #8
0
DLLEXPORT void STDCALL FPDF_PageToDevice(FPDF_PAGE page, int start_x, int start_y, int size_x, int size_y,
        int rotate, double page_x, double page_y, int* device_x, int* device_y)
{
    if (page == NULL || device_x == NULL || device_y == NULL) return;
    CPDF_Page* pPage = (CPDF_Page*)page;

    CPDF_Matrix page2device;
    pPage->GetDisplayMatrix(page2device, start_x, start_y, size_x, size_y, rotate);

    FX_FLOAT device_x_f, device_y_f;
    page2device.Transform(((FX_FLOAT)page_x), ((FX_FLOAT)page_y), device_x_f, device_y_f);

    *device_x = FXSYS_round(device_x_f);
    *device_y = FXSYS_round(device_y_f);
}
Пример #9
0
void CPDF_CalRGB::TranslateImageLine(uint8_t* pDestBuf, const uint8_t* pSrcBuf, int pixels, int image_width, int image_height, FX_BOOL bTransMask) const
{
    if (bTransMask) {
        FX_FLOAT Cal[3];
        FX_FLOAT R, G, B;
        for(int i = 0; i < pixels; i ++) {
            Cal[0] = ((FX_FLOAT)pSrcBuf[2]) / 255;
            Cal[1] = ((FX_FLOAT)pSrcBuf[1]) / 255;
            Cal[2] = ((FX_FLOAT)pSrcBuf[0]) / 255;
            GetRGB(Cal, R, G, B);
            pDestBuf[0] = FXSYS_round(B * 255);
            pDestBuf[1] = FXSYS_round(G * 255);
            pDestBuf[2] = FXSYS_round(R * 255);
            pSrcBuf += 3;
            pDestBuf += 3;
        }
    }
    ReverseRGB(pDestBuf, pSrcBuf, pixels);
}
Пример #10
0
CFX_DIBitmap* CPDF_RenderStatus::GetBackdrop(const CPDF_PageObject* pObj,
                                             const FX_RECT& rect,
                                             int& left,
                                             int& top,
                                             FX_BOOL bBackAlphaRequired) {
  FX_RECT bbox = rect;
  bbox.Intersect(m_pDevice->GetClipBox());
  left = bbox.left;
  top = bbox.top;
  CFX_Matrix deviceCTM = m_pDevice->GetCTM();
  FX_FLOAT scaleX = FXSYS_fabs(deviceCTM.a);
  FX_FLOAT scaleY = FXSYS_fabs(deviceCTM.d);
  int width = FXSYS_round(bbox.Width() * scaleX);
  int height = FXSYS_round(bbox.Height() * scaleY);
  std::unique_ptr<CFX_DIBitmap> pBackdrop(new CFX_DIBitmap);
  if (bBackAlphaRequired && !m_bDropObjects)
    pBackdrop->Create(width, height, FXDIB_Argb);
  else
    m_pDevice->CreateCompatibleBitmap(pBackdrop.get(), width, height);

  if (!pBackdrop->GetBuffer())
    return nullptr;

  FX_BOOL bNeedDraw;
  if (pBackdrop->HasAlpha())
    bNeedDraw = !(m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT);
  else
    bNeedDraw = !(m_pDevice->GetRenderCaps() & FXRC_GET_BITS);

  if (!bNeedDraw) {
    m_pDevice->GetDIBits(pBackdrop.get(), left, top);
    return pBackdrop.release();
  }

  CFX_Matrix FinalMatrix = m_DeviceMatrix;
  FinalMatrix.TranslateI(-left, -top);
  FinalMatrix.Scale(scaleX, scaleY);
  pBackdrop->Clear(pBackdrop->HasAlpha() ? 0 : 0xffffffff);
  CFX_FxgeDevice device;
  device.Attach(pBackdrop.get(), false, nullptr, false);
  m_pContext->Render(&device, pObj, &m_Options, &FinalMatrix);
  return pBackdrop.release();
}
Пример #11
0
CFX_GlyphBitmap* CPDF_Type3Cache::LoadGlyph(FX_DWORD charcode, const CFX_AffineMatrix* pMatrix, FX_FLOAT retinaScaleX, FX_FLOAT retinaScaleY)
{
    _CPDF_UniqueKeyGen keygen;
    keygen.Generate(4, FXSYS_round(pMatrix->a * 10000), FXSYS_round(pMatrix->b * 10000),
                    FXSYS_round(pMatrix->c * 10000), FXSYS_round(pMatrix->d * 10000));
    CFX_ByteStringC FaceGlyphsKey(keygen.m_Key, keygen.m_KeyLen);
    CPDF_Type3Glyphs* pSizeCache = NULL;
    if(!m_SizeMap.Lookup(FaceGlyphsKey, (void*&)pSizeCache)) {
        pSizeCache = FX_NEW CPDF_Type3Glyphs;
        m_SizeMap.SetAt(FaceGlyphsKey, pSizeCache);
    }
    CFX_GlyphBitmap* pGlyphBitmap;
    if(pSizeCache->m_GlyphMap.Lookup((FX_LPVOID)(FX_UINTPTR)charcode, (void*&)pGlyphBitmap)) {
        return pGlyphBitmap;
    }
    pGlyphBitmap = RenderGlyph(pSizeCache, charcode, pMatrix, retinaScaleX, retinaScaleY);
    pSizeCache->m_GlyphMap.SetAt((FX_LPVOID)(FX_UINTPTR)charcode, pGlyphBitmap);
    return pGlyphBitmap;
}
Пример #12
0
CFX_QuartzDeviceDriver::CFX_QuartzDeviceDriver(CGContextRef context, FX_INT32 deviceClass)
{
    m_saveCount = 0;
    _context		= context;
    _deviceClass	= deviceClass;
    CGContextRetain(_context);
    CGRect r = CGContextGetClipBoundingBox(context);
    _width	= FXSYS_round(r.size.width);
    _height	= FXSYS_round(r.size.height);
    _renderCaps = FXRC_SOFT_CLIP | FXRC_BLEND_MODE |
                  FXRC_ALPHA_PATH | FXRC_ALPHA_IMAGE |
                  FXRC_BIT_MASK | FXRC_ALPHA_MASK;
    if (_deviceClass != FXDC_DISPLAY) {
    } else {
        CGImageRef image = CGBitmapContextCreateImage(_context);
        if (image) {
            _renderCaps |= FXRC_GET_BITS;
            _width = CGImageGetWidth(image);
            _height = CGImageGetHeight(image);
            CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(image);
            if (kCGImageAlphaPremultipliedFirst == alphaInfo ||
                    kCGImageAlphaPremultipliedLast == alphaInfo ||
                    kCGImageAlphaOnly == alphaInfo) {
                _renderCaps |= FXRC_ALPHA_OUTPUT;
            }
        }
        CGImageRelease(image);
    }
    CGAffineTransform ctm = CGContextGetCTM(_context);
    CGContextSaveGState(_context);
    m_saveCount++;
    if (ctm.d >= 0) {
        CGFloat offset_x, offset_y;
        offset_x = ctm.tx;
        offset_y = ctm.ty;
        CGContextTranslateCTM(_context, -offset_x, -offset_y);
        CGContextConcatCTM(_context, CGAffineTransformMake(1, 0, 0, -1, offset_x, _height + offset_y));
    }
    _foxitDevice2User = CGAffineTransformIdentity;
    _user2FoxitDevice = CGAffineTransformInvert(_foxitDevice2User);
}
Пример #13
0
void CPDFXFA_Page::PageToDevice(int start_x,
                                int start_y,
                                int size_x,
                                int size_y,
                                int rotate,
                                double page_x,
                                double page_y,
                                int* device_x,
                                int* device_y) {
  if (!m_pPDFPage && !m_pXFAPageView)
    return;

  CFX_Matrix page2device;
  FX_FLOAT device_x_f, device_y_f;

  GetDisplayMatrix(page2device, start_x, start_y, size_x, size_y, rotate);

  page2device.Transform(((FX_FLOAT)page_x), ((FX_FLOAT)page_y), device_x_f,
                        device_y_f);

  *device_x = FXSYS_round(device_x_f);
  *device_y = FXSYS_round(device_y_f);
}
Пример #14
0
FX_BOOL CPDF_Type3Font::Load() {
  m_pFontResources = m_pFontDict->GetDictBy("Resources");
  CPDF_Array* pMatrix = m_pFontDict->GetArrayBy("FontMatrix");
  FX_FLOAT xscale = 1.0f, yscale = 1.0f;
  if (pMatrix) {
    m_FontMatrix = pMatrix->GetMatrix();
    xscale = m_FontMatrix.a;
    yscale = m_FontMatrix.d;
  }
  CPDF_Array* pBBox = m_pFontDict->GetArrayBy("FontBBox");
  if (pBBox) {
    m_FontBBox.left = (int32_t)(pBBox->GetNumberAt(0) * xscale * 1000);
    m_FontBBox.bottom = (int32_t)(pBBox->GetNumberAt(1) * yscale * 1000);
    m_FontBBox.right = (int32_t)(pBBox->GetNumberAt(2) * xscale * 1000);
    m_FontBBox.top = (int32_t)(pBBox->GetNumberAt(3) * yscale * 1000);
  }
  int StartChar = m_pFontDict->GetIntegerBy("FirstChar");
  CPDF_Array* pWidthArray = m_pFontDict->GetArrayBy("Widths");
  if (pWidthArray && (StartChar >= 0 && StartChar < 256)) {
    size_t count = pWidthArray->GetCount();
    if (count > 256)
      count = 256;
    if (StartChar + count > 256)
      count = 256 - StartChar;
    for (size_t i = 0; i < count; i++) {
      m_CharWidthL[StartChar + i] =
          FXSYS_round(pWidthArray->GetNumberAt(i) * xscale * 1000);
    }
  }
  m_pCharProcs = m_pFontDict->GetDictBy("CharProcs");
  CPDF_Object* pEncoding = m_pFontDict->GetDirectObjectBy("Encoding");
  if (pEncoding) {
    LoadPDFEncoding(pEncoding, m_BaseEncoding, m_pCharNames, FALSE, FALSE);
    if (m_pCharNames) {
      for (int i = 0; i < 256; i++) {
        m_Encoding.m_Unicodes[i] =
            PDF_UnicodeFromAdobeName(m_pCharNames[i].c_str());
        if (m_Encoding.m_Unicodes[i] == 0) {
          m_Encoding.m_Unicodes[i] = i;
        }
      }
    }
  }
  return TRUE;
}
Пример #15
0
static int _AdjustBlue(FX_FLOAT pos, int& count, int blues[]) {
  FX_FLOAT min_distance = 1000000.0f * 1.0f;
  int closest_pos = -1;
  for (int i = 0; i < count; i++) {
    FX_FLOAT distance = (FX_FLOAT)FXSYS_fabs(pos - (FX_FLOAT)blues[i]);
    if (distance < 1.0f * 80.0f / 100.0f && distance < min_distance) {
      min_distance = distance;
      closest_pos = i;
    }
  }
  if (closest_pos >= 0) {
    return blues[closest_pos];
  }
  int new_pos = FXSYS_round(pos);
  if (count == TYPE3_MAX_BLUES) {
    return new_pos;
  }
  blues[count++] = new_pos;
  return new_pos;
}
FX_BOOL CPDF_RenderStatus::ProcessInlines(CPDF_InlineImages* pInlines, const CFX_AffineMatrix* pObj2Device)
{
    int bitmap_alpha = 255;
    if (!pInlines->m_GeneralState.IsNull()) {
        bitmap_alpha = FXSYS_round(pInlines->m_GeneralState.GetObject()->m_FillAlpha * 255);
    }
    if (pInlines->m_pStream) {
        CPDF_DIBSource dibsrc;
        if (!dibsrc.Load(m_pContext->m_pDocument, pInlines->m_pStream, NULL, NULL, NULL, NULL)) {
            return TRUE;
        }
        pInlines->m_pBitmap = dibsrc.Clone();
        pInlines->m_pStream->Release();
        pInlines->m_pStream = NULL;
    }
    if (pInlines->m_pBitmap == NULL) {
        return TRUE;
    }
    FX_ARGB fill_argb = 0;
    if (pInlines->m_pBitmap->IsAlphaMask()) {
        fill_argb = GetFillArgb(pInlines);
    }
    int flags = 0;
    if (m_Options.m_Flags & RENDER_FORCE_DOWNSAMPLE) {
        flags |= RENDER_FORCE_DOWNSAMPLE;
    } else if (m_Options.m_Flags & RENDER_FORCE_HALFTONE) {
        flags = 0;
    }
    for (int i = 0; i < pInlines->m_Matrices.GetSize(); i ++) {
        CFX_AffineMatrix image_matrix = pInlines->m_Matrices.GetAt(i);
        image_matrix.Concat(*pObj2Device);
        CPDF_ImageRenderer renderer;
        if (renderer.Start(this, pInlines->m_pBitmap, fill_argb, bitmap_alpha, &image_matrix, flags, FALSE, m_curBlend)) {
            renderer.Continue(NULL);
        }
    }
    return TRUE;
}
Пример #17
0
CPDF_TransferFunc* CPDF_DocRenderData::GetTransferFunc(CPDF_Object* pObj) {
  if (!pObj)
    return nullptr;

  auto it = m_TransferFuncMap.find(pObj);
  if (it != m_TransferFuncMap.end()) {
    CPDF_CountedObject<CPDF_TransferFunc>* pTransferCounter = it->second;
    return pTransferCounter->AddRef();
  }

  std::unique_ptr<CPDF_Function> pFuncs[3];
  FX_BOOL bUniTransfer = TRUE;
  FX_BOOL bIdentity = TRUE;
  if (CPDF_Array* pArray = pObj->AsArray()) {
    bUniTransfer = FALSE;
    if (pArray->GetCount() < 3)
      return nullptr;

    for (uint32_t i = 0; i < 3; ++i) {
      pFuncs[2 - i] = CPDF_Function::Load(pArray->GetDirectObjectAt(i));
      if (!pFuncs[2 - i])
        return nullptr;
    }
  } else {
    pFuncs[0] = CPDF_Function::Load(pObj);
    if (!pFuncs[0])
      return nullptr;
  }
  CPDF_TransferFunc* pTransfer = new CPDF_TransferFunc(m_pPDFDoc);
  CPDF_CountedObject<CPDF_TransferFunc>* pTransferCounter =
      new CPDF_CountedObject<CPDF_TransferFunc>(pTransfer);
  m_TransferFuncMap[pObj] = pTransferCounter;
  static const int kMaxOutputs = 16;
  FX_FLOAT output[kMaxOutputs];
  FXSYS_memset(output, 0, sizeof(output));
  FX_FLOAT input;
  int noutput;
  for (int v = 0; v < 256; ++v) {
    input = (FX_FLOAT)v / 255.0f;
    if (bUniTransfer) {
      if (pFuncs[0] && pFuncs[0]->CountOutputs() <= kMaxOutputs)
        pFuncs[0]->Call(&input, 1, output, noutput);
      int o = FXSYS_round(output[0] * 255);
      if (o != v)
        bIdentity = FALSE;
      for (int i = 0; i < 3; ++i) {
        pTransfer->m_Samples[i * 256 + v] = o;
      }
    } else {
      for (int i = 0; i < 3; ++i) {
        if (pFuncs[i] && pFuncs[i]->CountOutputs() <= kMaxOutputs) {
          pFuncs[i]->Call(&input, 1, output, noutput);
          int o = FXSYS_round(output[0] * 255);
          if (o != v)
            bIdentity = FALSE;
          pTransfer->m_Samples[i * 256 + v] = o;
        } else {
          pTransfer->m_Samples[i * 256 + v] = v;
        }
      }
    }
  }

  pTransfer->m_bIdentity = bIdentity;
  return pTransferCounter->AddRef();
}
Пример #18
0
FX_BOOL CPDF_RenderStatus::ProcessType3Text(const CPDF_TextObject* textobj, const CFX_AffineMatrix* pObj2Device)
{
    CPDF_Type3Font* pType3Font = textobj->m_TextState.GetFont()->GetType3Font();
    for (int j = 0; j < m_Type3FontCache.GetSize(); j++)
        if ((CPDF_Type3Font*)m_Type3FontCache.GetAt(j) == pType3Font) {
            return TRUE;
        }
    CFX_Matrix dCTM = m_pDevice->GetCTM();
    FX_FLOAT sa = FXSYS_fabs(dCTM.a);
    FX_FLOAT sd = FXSYS_fabs(dCTM.d);
    CFX_AffineMatrix text_matrix;
    textobj->GetTextMatrix(&text_matrix);
    CFX_AffineMatrix char_matrix = pType3Font->GetFontMatrix();
    FX_FLOAT font_size = textobj->m_TextState.GetFontSize();
    char_matrix.Scale(font_size, font_size);
    FX_ARGB fill_argb = GetFillArgb(textobj, TRUE);
    int fill_alpha = FXARGB_A(fill_argb);
    int device_class = m_pDevice->GetDeviceClass();
    FXTEXT_GLYPHPOS* pGlyphAndPos = NULL;
    if (device_class == FXDC_DISPLAY) {
        pGlyphAndPos = FX_Alloc(FXTEXT_GLYPHPOS, textobj->m_nChars);
    } else if (fill_alpha < 255) {
        return FALSE;
    }
    CPDF_RefType3Cache refTypeCache(pType3Font);
    FX_DWORD *pChars = textobj->m_pCharCodes;
    if (textobj->m_nChars == 1) {
        pChars = (FX_DWORD*)(&textobj->m_pCharCodes);
    }
    for (int iChar = 0; iChar < textobj->m_nChars; iChar ++) {
        FX_DWORD charcode = pChars[iChar];
        if (charcode == (FX_DWORD) - 1) {
            continue;
        }
        CPDF_Type3Char* pType3Char = pType3Font->LoadChar(charcode);
        if (pType3Char == NULL) {
            continue;
        }
        CFX_AffineMatrix matrix = char_matrix;
        matrix.e += iChar ? textobj->m_pCharPos[iChar - 1] : 0;
        matrix.Concat(text_matrix);
        matrix.Concat(*pObj2Device);
        if (!pType3Char->LoadBitmap(m_pContext)) {
            if (pGlyphAndPos) {
                for (int i = 0; i < iChar; i ++) {
                    FXTEXT_GLYPHPOS& glyph = pGlyphAndPos[i];
                    if (glyph.m_pGlyph == NULL) {
                        continue;
                    }
                    m_pDevice->SetBitMask(&glyph.m_pGlyph->m_Bitmap,
                                          glyph.m_OriginX + glyph.m_pGlyph->m_Left,
                                          glyph.m_OriginY - glyph.m_pGlyph->m_Top, fill_argb);
                }
                FX_Free(pGlyphAndPos);
                pGlyphAndPos = NULL;
            }
            CPDF_GraphicStates* pStates = CloneObjStates(textobj, FALSE);
            CPDF_RenderOptions Options = m_Options;
            Options.m_Flags |= RENDER_FORCE_HALFTONE | RENDER_RECT_AA;
            Options.m_Flags &= ~RENDER_FORCE_DOWNSAMPLE;
            CPDF_Dictionary* pFormResource = NULL;
            if (pType3Char->m_pForm && pType3Char->m_pForm->m_pFormDict) {
                pFormResource = pType3Char->m_pForm->m_pFormDict->GetDict(FX_BSTRC("Resources"));
            }
            if (fill_alpha == 255) {
                CPDF_RenderStatus status;
                status.Initialize(m_Level + 1, m_pContext, m_pDevice, NULL, NULL, this, pStates, &Options,
                                  pType3Char->m_pForm->m_Transparency, m_bDropObjects, pFormResource, FALSE, pType3Char, fill_argb);
                status.m_Type3FontCache.Append(m_Type3FontCache);
                status.m_Type3FontCache.Add(pType3Font);
                m_pDevice->SaveState();
                status.RenderObjectList(pType3Char->m_pForm, &matrix);
                m_pDevice->RestoreState();
            } else {
                CFX_FloatRect rect_f = pType3Char->m_pForm->CalcBoundingBox();
                rect_f.Transform(&matrix);
                FX_RECT rect = rect_f.GetOutterRect();
                CFX_FxgeDevice bitmap_device;
                if (!bitmap_device.Create((int)(rect.Width() * sa), (int)(rect.Height() * sd), FXDIB_Argb)) {
                    return TRUE;
                }
                bitmap_device.GetBitmap()->Clear(0);
                CPDF_RenderStatus status;
                status.Initialize(m_Level + 1, m_pContext, &bitmap_device, NULL, NULL, this, pStates, &Options,
                                  pType3Char->m_pForm->m_Transparency, m_bDropObjects, pFormResource, FALSE, pType3Char, fill_argb);
                status.m_Type3FontCache.Append(m_Type3FontCache);
                status.m_Type3FontCache.Add(pType3Font);
                matrix.TranslateI(-rect.left, -rect.top);
                matrix.Scale(sa, sd);
                status.RenderObjectList(pType3Char->m_pForm, &matrix);
                m_pDevice->SetDIBits(bitmap_device.GetBitmap(), rect.left, rect.top);
            }
            delete pStates;
        } else if (pType3Char->m_pBitmap) {
            if (device_class == FXDC_DISPLAY) {
                CPDF_Type3Cache* pCache = GetCachedType3(pType3Font);
                refTypeCache.m_dwCount++;
                CFX_GlyphBitmap* pBitmap = pCache->LoadGlyph(charcode, &matrix, sa, sd);
                if (pBitmap == NULL) {
                    continue;
                }
                int origin_x = FXSYS_round(matrix.e);
                int origin_y = FXSYS_round(matrix.f);
                if (pGlyphAndPos) {
                    pGlyphAndPos[iChar].m_pGlyph = pBitmap;
                    pGlyphAndPos[iChar].m_OriginX = origin_x;
                    pGlyphAndPos[iChar].m_OriginY = origin_y;
                } else {
                    m_pDevice->SetBitMask(&pBitmap->m_Bitmap, origin_x + pBitmap->m_Left, origin_y - pBitmap->m_Top, fill_argb);
                }
            } else {
                CFX_AffineMatrix image_matrix = pType3Char->m_ImageMatrix;
                image_matrix.Concat(matrix);
                CPDF_ImageRenderer renderer;
                if (renderer.Start(this, pType3Char->m_pBitmap, fill_argb, 255, &image_matrix, 0, FALSE)) {
                    renderer.Continue(NULL);
                }
                if (!renderer.m_Result) {
                    return FALSE;
                }
            }
        }
    }
    if (pGlyphAndPos) {
        FX_RECT rect = FXGE_GetGlyphsBBox(pGlyphAndPos, textobj->m_nChars, 0, sa, sd);
        CFX_DIBitmap bitmap;
        if (!bitmap.Create((int)(rect.Width() * sa), (int)(rect.Height() * sd), FXDIB_8bppMask)) {
            FX_Free(pGlyphAndPos);
            return TRUE;
        }
        bitmap.Clear(0);
        for (int iChar = 0; iChar < textobj->m_nChars; iChar ++) {
            FXTEXT_GLYPHPOS& glyph = pGlyphAndPos[iChar];
            if (glyph.m_pGlyph == NULL) {
                continue;
            }
            bitmap.TransferBitmap((int)((glyph.m_OriginX + glyph.m_pGlyph->m_Left - rect.left) * sa),
                                  (int)((glyph.m_OriginY - glyph.m_pGlyph->m_Top - rect.top) * sd),
                                  glyph.m_pGlyph->m_Bitmap.GetWidth(), glyph.m_pGlyph->m_Bitmap.GetHeight(),
                                  &glyph.m_pGlyph->m_Bitmap, 0, 0);
        }
        m_pDevice->SetBitMask(&bitmap, rect.left, rect.top, fill_argb);
        FX_Free(pGlyphAndPos);
    }
    return TRUE;
}
Пример #19
0
FX_BOOL CPDF_PSEngine::DoOperator(PDF_PSOP op) {
  int i1, i2;
  FX_FLOAT d1, d2;
  switch (op) {
    case PSOP_ADD:
      d1 = Pop();
      d2 = Pop();
      Push(d1 + d2);
      break;
    case PSOP_SUB:
      d2 = Pop();
      d1 = Pop();
      Push(d1 - d2);
      break;
    case PSOP_MUL:
      d1 = Pop();
      d2 = Pop();
      Push(d1 * d2);
      break;
    case PSOP_DIV:
      d2 = Pop();
      d1 = Pop();
      Push(d1 / d2);
      break;
    case PSOP_IDIV:
      i2 = (int)Pop();
      i1 = (int)Pop();
      Push(i2 ? i1 / i2 : 0);
      break;
    case PSOP_MOD:
      i2 = (int)Pop();
      i1 = (int)Pop();
      Push(i2 ? i1 % i2 : 0);
      break;
    case PSOP_NEG:
      d1 = Pop();
      Push(-d1);
      break;
    case PSOP_ABS:
      d1 = Pop();
      Push((FX_FLOAT)FXSYS_fabs(d1));
      break;
    case PSOP_CEILING:
      d1 = Pop();
      Push((FX_FLOAT)FXSYS_ceil(d1));
      break;
    case PSOP_FLOOR:
      d1 = Pop();
      Push((FX_FLOAT)FXSYS_floor(d1));
      break;
    case PSOP_ROUND:
      d1 = Pop();
      Push(FXSYS_round(d1));
      break;
    case PSOP_TRUNCATE:
      i1 = (int)Pop();
      Push(i1);
      break;
    case PSOP_SQRT:
      d1 = Pop();
      Push((FX_FLOAT)FXSYS_sqrt(d1));
      break;
    case PSOP_SIN:
      d1 = Pop();
      Push((FX_FLOAT)FXSYS_sin(d1 * FX_PI / 180.0f));
      break;
    case PSOP_COS:
      d1 = Pop();
      Push((FX_FLOAT)FXSYS_cos(d1 * FX_PI / 180.0f));
      break;
    case PSOP_ATAN:
      d2 = Pop();
      d1 = Pop();
      d1 = (FX_FLOAT)(FXSYS_atan2(d1, d2) * 180.0 / FX_PI);
      if (d1 < 0) {
        d1 += 360;
      }
      Push(d1);
      break;
    case PSOP_EXP:
      d2 = Pop();
      d1 = Pop();
      Push((FX_FLOAT)FXSYS_pow(d1, d2));
      break;
    case PSOP_LN:
      d1 = Pop();
      Push((FX_FLOAT)FXSYS_log(d1));
      break;
    case PSOP_LOG:
      d1 = Pop();
      Push((FX_FLOAT)FXSYS_log10(d1));
      break;
    case PSOP_CVI:
      i1 = (int)Pop();
      Push(i1);
      break;
    case PSOP_CVR:
      break;
    case PSOP_EQ:
      d2 = Pop();
      d1 = Pop();
      Push((int)(d1 == d2));
      break;
    case PSOP_NE:
      d2 = Pop();
      d1 = Pop();
      Push((int)(d1 != d2));
      break;
    case PSOP_GT:
      d2 = Pop();
      d1 = Pop();
      Push((int)(d1 > d2));
      break;
    case PSOP_GE:
      d2 = Pop();
      d1 = Pop();
      Push((int)(d1 >= d2));
      break;
    case PSOP_LT:
      d2 = Pop();
      d1 = Pop();
      Push((int)(d1 < d2));
      break;
    case PSOP_LE:
      d2 = Pop();
      d1 = Pop();
      Push((int)(d1 <= d2));
      break;
    case PSOP_AND:
      i1 = (int)Pop();
      i2 = (int)Pop();
      Push(i1 & i2);
      break;
    case PSOP_OR:
      i1 = (int)Pop();
      i2 = (int)Pop();
      Push(i1 | i2);
      break;
    case PSOP_XOR:
      i1 = (int)Pop();
      i2 = (int)Pop();
      Push(i1 ^ i2);
      break;
    case PSOP_NOT:
      i1 = (int)Pop();
      Push((int)!i1);
      break;
    case PSOP_BITSHIFT: {
      int shift = (int)Pop();
      int i = (int)Pop();
      if (shift > 0) {
        Push(i << shift);
      } else {
        Push(i >> -shift);
      }
      break;
    }
    case PSOP_TRUE:
      Push(1);
      break;
    case PSOP_FALSE:
      Push(0);
      break;
    case PSOP_POP:
      Pop();
      break;
    case PSOP_EXCH:
      d2 = Pop();
      d1 = Pop();
      Push(d2);
      Push(d1);
      break;
    case PSOP_DUP:
      d1 = Pop();
      Push(d1);
      Push(d1);
      break;
    case PSOP_COPY: {
      int n = static_cast<int>(Pop());
      if (n < 0 || m_StackCount + n > PSENGINE_STACKSIZE ||
          n > static_cast<int>(m_StackCount))
        break;
      for (int i = 0; i < n; i++)
        m_Stack[m_StackCount + i] = m_Stack[m_StackCount + i - n];
      m_StackCount += n;
      break;
    }
    case PSOP_INDEX: {
      int n = static_cast<int>(Pop());
      if (n < 0 || n >= static_cast<int>(m_StackCount))
        break;
      Push(m_Stack[m_StackCount - n - 1]);
      break;
    }
    case PSOP_ROLL: {
      int j = static_cast<int>(Pop());
      int n = static_cast<int>(Pop());
      if (m_StackCount == 0)
        break;
      if (n < 0 || n > static_cast<int>(m_StackCount))
        break;
      if (j < 0) {
        for (int i = 0; i < -j; i++) {
          FX_FLOAT first = m_Stack[m_StackCount - n];
          for (int ii = 0; ii < n - 1; ii++)
            m_Stack[m_StackCount - n + ii] = m_Stack[m_StackCount - n + ii + 1];
          m_Stack[m_StackCount - 1] = first;
        }
      } else {
        for (int i = 0; i < j; i++) {
          FX_FLOAT last = m_Stack[m_StackCount - 1];
          int ii;
          for (ii = 0; ii < n - 1; ii++)
            m_Stack[m_StackCount - ii - 1] = m_Stack[m_StackCount - ii - 2];
          m_Stack[m_StackCount - ii - 1] = last;
        }
      }
      break;
    }
    default:
      break;
  }
  return TRUE;
}
Пример #20
0
void CFX_Matrix::TransformPoint(int32_t& x, int32_t& y) const {
    FX_FLOAT fx = a * x + c * y + e;
    FX_FLOAT fy = b * x + d * y + f;
    x = FXSYS_round(fx);
    y = FXSYS_round(fy);
}
Пример #21
0
FX_BOOL CPDF_RenderStatus::ProcessTransparency(
    const CPDF_PageObject* pPageObj,
    const CFX_AffineMatrix* pObj2Device) {
  const CPDF_GeneralStateData* pGeneralState = pPageObj->m_GeneralState;
  int blend_type =
      pGeneralState ? pGeneralState->m_BlendType : FXDIB_BLEND_NORMAL;
  if (blend_type == FXDIB_BLEND_UNSUPPORTED) {
    return TRUE;
  }
  CPDF_Dictionary* pSMaskDict =
      pGeneralState ? ToDictionary(pGeneralState->m_pSoftMask) : NULL;
  if (pSMaskDict) {
    if (pPageObj->m_Type == PDFPAGE_IMAGE &&
        ((CPDF_ImageObject*)pPageObj)
            ->m_pImage->GetDict()
            ->KeyExist(FX_BSTRC("SMask"))) {
      pSMaskDict = NULL;
    }
  }
  CPDF_Dictionary* pFormResource = NULL;
  FX_FLOAT group_alpha = 1.0f;
  int Transparency = m_Transparency;
  FX_BOOL bGroupTransparent = FALSE;
  if (pPageObj->m_Type == PDFPAGE_FORM) {
    CPDF_FormObject* pFormObj = (CPDF_FormObject*)pPageObj;
    const CPDF_GeneralStateData* pStateData =
        pFormObj->m_GeneralState.GetObject();
    if (pStateData) {
      group_alpha = pStateData->m_FillAlpha;
    }
    Transparency = pFormObj->m_pForm->m_Transparency;
    bGroupTransparent = !!(Transparency & PDFTRANS_ISOLATED);
    if (pFormObj->m_pForm->m_pFormDict) {
      pFormResource = pFormObj->m_pForm->m_pFormDict->GetDict("Resources");
    }
  }
  FX_BOOL bTextClip = FALSE;
  if (pPageObj->m_ClipPath.NotNull() && pPageObj->m_ClipPath.GetTextCount() &&
      m_pDevice->GetDeviceClass() == FXDC_DISPLAY &&
      !(m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_SOFT_CLIP)) {
    bTextClip = TRUE;
  }
  if ((m_Options.m_Flags & RENDER_OVERPRINT) &&
      pPageObj->m_Type == PDFPAGE_IMAGE && pGeneralState &&
      pGeneralState->m_FillOP && pGeneralState->m_StrokeOP) {
    CPDF_Document* pDocument = NULL;
    CPDF_Page* pPage = NULL;
    if (m_pContext->m_pPageCache) {
      pPage = m_pContext->m_pPageCache->GetPage();
      pDocument = pPage->m_pDocument;
    } else {
      pDocument = ((CPDF_ImageObject*)pPageObj)->m_pImage->GetDocument();
    }
    CPDF_Dictionary* pPageResources = pPage ? pPage->m_pPageResources : NULL;
    CPDF_Object* pCSObj = ((CPDF_ImageObject*)pPageObj)
                              ->m_pImage->GetStream()
                              ->GetDict()
                              ->GetElementValue(FX_BSTRC("ColorSpace"));
    CPDF_ColorSpace* pColorSpace =
        pDocument->LoadColorSpace(pCSObj, pPageResources);
    if (pColorSpace) {
      int format = pColorSpace->GetFamily();
      if (format == PDFCS_DEVICECMYK || format == PDFCS_SEPARATION ||
          format == PDFCS_DEVICEN) {
        blend_type = FXDIB_BLEND_DARKEN;
      }
      pDocument->GetPageData()->ReleaseColorSpace(pCSObj);
    }
  }
  if (pSMaskDict == NULL && group_alpha == 1.0f &&
      blend_type == FXDIB_BLEND_NORMAL && !bTextClip && !bGroupTransparent) {
    return FALSE;
  }
  FX_BOOL isolated = Transparency & PDFTRANS_ISOLATED;
  if (m_bPrint) {
    FX_BOOL bRet = FALSE;
    int rendCaps = m_pDevice->GetRenderCaps();
    if (!((Transparency & PDFTRANS_ISOLATED) || pSMaskDict || bTextClip) &&
        (rendCaps & FXRC_BLEND_MODE)) {
      int oldBlend = m_curBlend;
      m_curBlend = blend_type;
      bRet = DrawObjWithBlend(pPageObj, pObj2Device);
      m_curBlend = oldBlend;
    }
    if (!bRet) {
      DrawObjWithBackground(pPageObj, pObj2Device);
    }
    return TRUE;
  }
  FX_RECT rect = pPageObj->GetBBox(pObj2Device);
  rect.Intersect(m_pDevice->GetClipBox());
  if (rect.IsEmpty()) {
    return TRUE;
  }
  CFX_Matrix deviceCTM = m_pDevice->GetCTM();
  FX_FLOAT scaleX = FXSYS_fabs(deviceCTM.a);
  FX_FLOAT scaleY = FXSYS_fabs(deviceCTM.d);
  int width = FXSYS_round((FX_FLOAT)rect.Width() * scaleX);
  int height = FXSYS_round((FX_FLOAT)rect.Height() * scaleY);
  CFX_FxgeDevice bitmap_device;
  nonstd::unique_ptr<CFX_DIBitmap> oriDevice;
  if (!isolated && (m_pDevice->GetRenderCaps() & FXRC_GET_BITS)) {
    oriDevice.reset(new CFX_DIBitmap);
    if (!m_pDevice->CreateCompatibleBitmap(oriDevice.get(), width, height))
      return TRUE;

    m_pDevice->GetDIBits(oriDevice.get(), rect.left, rect.top);
  }
  if (!bitmap_device.Create(width, height, FXDIB_Argb, 0, oriDevice.get()))
    return TRUE;

  CFX_DIBitmap* bitmap = bitmap_device.GetBitmap();
  bitmap->Clear(0);
  CFX_AffineMatrix new_matrix = *pObj2Device;
  new_matrix.TranslateI(-rect.left, -rect.top);
  new_matrix.Scale(scaleX, scaleY);
  nonstd::unique_ptr<CFX_DIBitmap> pTextMask;
  if (bTextClip) {
    pTextMask.reset(new CFX_DIBitmap);
    if (!pTextMask->Create(width, height, FXDIB_8bppMask))
      return TRUE;

    pTextMask->Clear(0);
    CFX_FxgeDevice text_device;
    text_device.Attach(pTextMask.get());
    for (FX_DWORD i = 0; i < pPageObj->m_ClipPath.GetTextCount(); i++) {
      CPDF_TextObject* textobj = pPageObj->m_ClipPath.GetText(i);
      if (textobj == NULL) {
        break;
      }
      CFX_AffineMatrix text_matrix;
      textobj->GetTextMatrix(&text_matrix);
      CPDF_TextRenderer::DrawTextPath(
          &text_device, textobj->m_nChars, textobj->m_pCharCodes,
          textobj->m_pCharPos, textobj->m_TextState.GetFont(),
          textobj->m_TextState.GetFontSize(), &text_matrix, &new_matrix,
          textobj->m_GraphState, (FX_ARGB)-1, 0, NULL);
    }
  }
  CPDF_RenderStatus bitmap_render;
  bitmap_render.Initialize(m_pContext, &bitmap_device, NULL, m_pStopObj, NULL,
                           NULL, &m_Options, 0, m_bDropObjects, pFormResource,
                           TRUE);
  bitmap_render.ProcessObjectNoClip(pPageObj, &new_matrix);
  m_bStopped = bitmap_render.m_bStopped;
  if (pSMaskDict) {
    CFX_AffineMatrix smask_matrix;
    FXSYS_memcpy(&smask_matrix, pGeneralState->m_SMaskMatrix,
                 sizeof smask_matrix);
    smask_matrix.Concat(*pObj2Device);
    nonstd::unique_ptr<CFX_DIBSource> pSMaskSource(
        LoadSMask(pSMaskDict, &rect, &smask_matrix));
    if (pSMaskSource)
      bitmap->MultiplyAlpha(pSMaskSource.get());
  }
  if (pTextMask) {
    bitmap->MultiplyAlpha(pTextMask.get());
    pTextMask.reset();
  }
  if (Transparency & PDFTRANS_GROUP && group_alpha != 1.0f) {
    bitmap->MultiplyAlpha((int32_t)(group_alpha * 255));
  }
  Transparency = m_Transparency;
  if (pPageObj->m_Type == PDFPAGE_FORM) {
    Transparency |= PDFTRANS_GROUP;
  }
  CompositeDIBitmap(bitmap, rect.left, rect.top, 0, 255, blend_type,
                    Transparency);
  return TRUE;
}
Пример #22
0
int32_t CFX_Matrix::TransformDistance(int32_t dx, int32_t dy) const {
    FX_FLOAT fx = a * dx + c * dy, fy = b * dx + d * dy;
    return FXSYS_round(FXSYS_sqrt(fx * fx + fy * fy));
}
Пример #23
0
static void DrawAxialShading(CFX_DIBitmap* pBitmap,
                             CFX_Matrix* pObject2Bitmap,
                             CPDF_Dictionary* pDict,
                             CPDF_Function** pFuncs,
                             int nFuncs,
                             CPDF_ColorSpace* pCS,
                             int alpha) {
  ASSERT(pBitmap->GetFormat() == FXDIB_Argb);
  CPDF_Array* pCoords = pDict->GetArray("Coords");
  if (!pCoords) {
    return;
  }
  FX_FLOAT start_x = pCoords->GetNumber(0);
  FX_FLOAT start_y = pCoords->GetNumber(1);
  FX_FLOAT end_x = pCoords->GetNumber(2);
  FX_FLOAT end_y = pCoords->GetNumber(3);
  FX_FLOAT t_min = 0, t_max = 1.0f;
  CPDF_Array* pArray = pDict->GetArray("Domain");
  if (pArray) {
    t_min = pArray->GetNumber(0);
    t_max = pArray->GetNumber(1);
  }
  FX_BOOL bStartExtend = FALSE, bEndExtend = FALSE;
  pArray = pDict->GetArray("Extend");
  if (pArray) {
    bStartExtend = pArray->GetInteger(0);
    bEndExtend = pArray->GetInteger(1);
  }
  int width = pBitmap->GetWidth();
  int height = pBitmap->GetHeight();
  FX_FLOAT x_span = end_x - start_x;
  FX_FLOAT y_span = end_y - start_y;
  FX_FLOAT axis_len_square =
      FXSYS_Mul(x_span, x_span) + FXSYS_Mul(y_span, y_span);
  CFX_Matrix matrix;
  matrix.SetReverse(*pObject2Bitmap);
  int total_results = 0;
  for (int j = 0; j < nFuncs; j++) {
    if (pFuncs[j]) {
      total_results += pFuncs[j]->CountOutputs();
    }
  }
  if (pCS->CountComponents() > total_results) {
    total_results = pCS->CountComponents();
  }
  CFX_FixedBufGrow<FX_FLOAT, 16> result_array(total_results);
  FX_FLOAT* pResults = result_array;
  FXSYS_memset(pResults, 0, total_results * sizeof(FX_FLOAT));
  FX_DWORD rgb_array[SHADING_STEPS];
  for (int i = 0; i < SHADING_STEPS; i++) {
    FX_FLOAT input = (t_max - t_min) * i / SHADING_STEPS + t_min;
    int offset = 0;
    for (int j = 0; j < nFuncs; j++) {
      if (pFuncs[j]) {
        int nresults = 0;
        if (pFuncs[j]->Call(&input, 1, pResults + offset, nresults)) {
          offset += nresults;
        }
      }
    }
    FX_FLOAT R = 0.0f, G = 0.0f, B = 0.0f;
    pCS->GetRGB(pResults, R, G, B);
    rgb_array[i] =
        FXARGB_TODIB(FXARGB_MAKE(alpha, FXSYS_round(R * 255),
                                 FXSYS_round(G * 255), FXSYS_round(B * 255)));
  }
  int pitch = pBitmap->GetPitch();
  for (int row = 0; row < height; row++) {
    FX_DWORD* dib_buf = (FX_DWORD*)(pBitmap->GetBuffer() + row * pitch);
    for (int column = 0; column < width; column++) {
      FX_FLOAT x = (FX_FLOAT)column, y = (FX_FLOAT)row;
      matrix.Transform(x, y);
      FX_FLOAT scale = FXSYS_Div(
          FXSYS_Mul(x - start_x, x_span) + FXSYS_Mul(y - start_y, y_span),
          axis_len_square);
      int index = (int32_t)(scale * (SHADING_STEPS - 1));
      if (index < 0) {
        if (!bStartExtend) {
          continue;
        }
        index = 0;
      } else if (index >= SHADING_STEPS) {
        if (!bEndExtend) {
          continue;
        }
        index = SHADING_STEPS - 1;
      }
      dib_buf[column] = rgb_array[index];
    }
  }
}
Пример #24
0
bool CPDF_ImageRenderer::StartRenderDIBSource() {
  if (!m_Loader.m_pBitmap)
    return false;

  m_BitmapAlpha =
      FXSYS_round(255 * m_pImageObject->m_GeneralState.GetFillAlpha());
  m_pDIBSource = m_Loader.m_pBitmap;
  if (m_pRenderStatus->m_Options.m_ColorMode == RENDER_COLOR_ALPHA &&
      !m_Loader.m_pMask) {
    return StartBitmapAlpha();
  }
  if (m_pImageObject->m_GeneralState.GetTR()) {
    if (!m_pImageObject->m_GeneralState.GetTransferFunc()) {
      m_pImageObject->m_GeneralState.SetTransferFunc(
          m_pRenderStatus->GetTransferFunc(
              m_pImageObject->m_GeneralState.GetTR()));
    }
    if (m_pImageObject->m_GeneralState.GetTransferFunc() &&
        !m_pImageObject->m_GeneralState.GetTransferFunc()->m_bIdentity) {
      m_pDIBSource = m_Loader.m_pBitmap =
          m_pImageObject->m_GeneralState.GetTransferFunc()->TranslateImage(
              m_Loader.m_pBitmap, !m_Loader.m_bCached);
      if (m_Loader.m_bCached && m_Loader.m_pMask)
        m_Loader.m_pMask = m_Loader.m_pMask->Clone().release();
      m_Loader.m_bCached = false;
    }
  }
  m_FillArgb = 0;
  m_bPatternColor = false;
  m_pPattern = nullptr;
  if (m_pDIBSource->IsAlphaMask()) {
    const CPDF_Color* pColor = m_pImageObject->m_ColorState.GetFillColor();
    if (pColor && pColor->IsPattern()) {
      m_pPattern = pColor->GetPattern();
      if (m_pPattern)
        m_bPatternColor = true;
    }
    m_FillArgb = m_pRenderStatus->GetFillArgb(m_pImageObject);
  } else if (m_pRenderStatus->m_Options.m_ColorMode == RENDER_COLOR_GRAY) {
    m_pClone = m_pDIBSource->Clone();
    m_pClone->ConvertColorScale(m_pRenderStatus->m_Options.m_BackColor,
                                m_pRenderStatus->m_Options.m_ForeColor);
    m_pDIBSource = m_pClone.get();
  }
  m_Flags = 0;
  if (m_pRenderStatus->m_Options.m_Flags & RENDER_FORCE_DOWNSAMPLE)
    m_Flags |= RENDER_FORCE_DOWNSAMPLE;
  else if (m_pRenderStatus->m_Options.m_Flags & RENDER_FORCE_HALFTONE)
    m_Flags |= RENDER_FORCE_HALFTONE;
  if (m_pRenderStatus->m_pDevice->GetDeviceClass() != FXDC_DISPLAY) {
    CPDF_Object* pFilters =
        m_pImageObject->GetImage()->GetStream()->GetDict()->GetDirectObjectFor(
            "Filter");
    if (pFilters) {
      if (pFilters->IsName()) {
        CFX_ByteString bsDecodeType = pFilters->GetString();
        if (bsDecodeType == "DCTDecode" || bsDecodeType == "JPXDecode")
          m_Flags |= FXRENDER_IMAGE_LOSSY;
      } else if (CPDF_Array* pArray = pFilters->AsArray()) {
        for (size_t i = 0; i < pArray->GetCount(); i++) {
          CFX_ByteString bsDecodeType = pArray->GetStringAt(i);
          if (bsDecodeType == "DCTDecode" || bsDecodeType == "JPXDecode") {
            m_Flags |= FXRENDER_IMAGE_LOSSY;
            break;
          }
        }
      }
    }
  }
  if (m_pRenderStatus->m_Options.m_Flags & RENDER_NOIMAGESMOOTH)
    m_Flags |= FXDIB_NOSMOOTH;
  else if (m_pImageObject->GetImage()->IsInterpol())
    m_Flags |= FXDIB_INTERPOL;
  if (m_Loader.m_pMask)
    return DrawMaskedImage();

  if (m_bPatternColor)
    return DrawPatternImage(m_pObj2Device);

  if (m_BitmapAlpha != 255 || !m_pImageObject->m_GeneralState ||
      !m_pImageObject->m_GeneralState.GetFillOP() ||
      m_pImageObject->m_GeneralState.GetOPMode() != 0 ||
      m_pImageObject->m_GeneralState.GetBlendType() != FXDIB_BLEND_NORMAL ||
      m_pImageObject->m_GeneralState.GetStrokeAlpha() != 1.0f ||
      m_pImageObject->m_GeneralState.GetFillAlpha() != 1.0f) {
    return StartDIBSource();
  }
  CPDF_Document* pDocument = nullptr;
  CPDF_Page* pPage = nullptr;
  if (m_pRenderStatus->m_pContext->GetPageCache()) {
    pPage = m_pRenderStatus->m_pContext->GetPageCache()->GetPage();
    pDocument = pPage->m_pDocument;
  } else {
    pDocument = m_pImageObject->GetImage()->GetDocument();
  }
  CPDF_Dictionary* pPageResources = pPage ? pPage->m_pPageResources : nullptr;
  CPDF_Object* pCSObj =
      m_pImageObject->GetImage()->GetStream()->GetDict()->GetDirectObjectFor(
          "ColorSpace");
  CPDF_ColorSpace* pColorSpace =
      pDocument->LoadColorSpace(pCSObj, pPageResources);
  if (!pColorSpace)
    return StartDIBSource();
  int format = pColorSpace->GetFamily();
  if (format == PDFCS_DEVICECMYK || format == PDFCS_SEPARATION ||
      format == PDFCS_DEVICEN) {
    m_BlendType = FXDIB_BLEND_DARKEN;
  }
  pDocument->GetPageData()->ReleaseColorSpace(pCSObj);
  return StartDIBSource();
}
Пример #25
0
FX_BOOL CPDF_RenderStatus::ProcessTransparency(CPDF_PageObject* pPageObj,
                                               const CFX_Matrix* pObj2Device) {
#if defined _SKIA_SUPPORT_
  DebugVerifyDeviceIsPreMultiplied();
#endif
  int blend_type = pPageObj->m_GeneralState.GetBlendType();
  if (blend_type == FXDIB_BLEND_UNSUPPORTED)
    return TRUE;

  CPDF_Dictionary* pSMaskDict =
      ToDictionary(pPageObj->m_GeneralState.GetSoftMask());
  if (pSMaskDict) {
    if (pPageObj->IsImage() &&
        pPageObj->AsImage()->GetImage()->GetDict()->KeyExist("SMask")) {
      pSMaskDict = nullptr;
    }
  }
  CPDF_Dictionary* pFormResource = nullptr;
  FX_FLOAT group_alpha = 1.0f;
  int Transparency = m_Transparency;
  FX_BOOL bGroupTransparent = FALSE;
  if (pPageObj->IsForm()) {
    const CPDF_FormObject* pFormObj = pPageObj->AsForm();
    group_alpha = pFormObj->m_GeneralState.GetFillAlpha();
    Transparency = pFormObj->m_pForm->m_Transparency;
    bGroupTransparent = !!(Transparency & PDFTRANS_ISOLATED);
    if (pFormObj->m_pForm->m_pFormDict) {
      pFormResource = pFormObj->m_pForm->m_pFormDict->GetDictBy("Resources");
    }
  }
  bool bTextClip =
      (pPageObj->m_ClipPath && pPageObj->m_ClipPath.GetTextCount() &&
       m_pDevice->GetDeviceClass() == FXDC_DISPLAY &&
       !(m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_SOFT_CLIP));
  if ((m_Options.m_Flags & RENDER_OVERPRINT) && pPageObj->IsImage() &&
      pPageObj->m_GeneralState.GetFillOP() &&
      pPageObj->m_GeneralState.GetStrokeOP()) {
    CPDF_Document* pDocument = nullptr;
    CPDF_Page* pPage = nullptr;
    if (m_pContext->GetPageCache()) {
      pPage = m_pContext->GetPageCache()->GetPage();
      pDocument = pPage->m_pDocument;
    } else {
      pDocument = pPageObj->AsImage()->GetImage()->GetDocument();
    }
    CPDF_Dictionary* pPageResources = pPage ? pPage->m_pPageResources : nullptr;
    CPDF_Object* pCSObj = pPageObj->AsImage()
                              ->GetImage()
                              ->GetStream()
                              ->GetDict()
                              ->GetDirectObjectBy("ColorSpace");
    CPDF_ColorSpace* pColorSpace =
        pDocument->LoadColorSpace(pCSObj, pPageResources);
    if (pColorSpace) {
      int format = pColorSpace->GetFamily();
      if (format == PDFCS_DEVICECMYK || format == PDFCS_SEPARATION ||
          format == PDFCS_DEVICEN) {
        blend_type = FXDIB_BLEND_DARKEN;
      }
      pDocument->GetPageData()->ReleaseColorSpace(pCSObj);
    }
  }
  if (!pSMaskDict && group_alpha == 1.0f && blend_type == FXDIB_BLEND_NORMAL &&
      !bTextClip && !bGroupTransparent) {
    return FALSE;
  }
  bool isolated = !!(Transparency & PDFTRANS_ISOLATED);
  if (m_bPrint) {
    FX_BOOL bRet = FALSE;
    int rendCaps = m_pDevice->GetRenderCaps();
    if (!((Transparency & PDFTRANS_ISOLATED) || pSMaskDict || bTextClip) &&
        (rendCaps & FXRC_BLEND_MODE)) {
      int oldBlend = m_curBlend;
      m_curBlend = blend_type;
      bRet = DrawObjWithBlend(pPageObj, pObj2Device);
      m_curBlend = oldBlend;
    }
    if (!bRet) {
      DrawObjWithBackground(pPageObj, pObj2Device);
    }
    return TRUE;
  }
  FX_RECT rect = pPageObj->GetBBox(pObj2Device);
  rect.Intersect(m_pDevice->GetClipBox());
  if (rect.IsEmpty()) {
    return TRUE;
  }
  CFX_Matrix deviceCTM = m_pDevice->GetCTM();
  FX_FLOAT scaleX = FXSYS_fabs(deviceCTM.a);
  FX_FLOAT scaleY = FXSYS_fabs(deviceCTM.d);
  int width = FXSYS_round((FX_FLOAT)rect.Width() * scaleX);
  int height = FXSYS_round((FX_FLOAT)rect.Height() * scaleY);
  CFX_FxgeDevice bitmap_device;
  std::unique_ptr<CFX_DIBitmap> oriDevice;
  if (!isolated && (m_pDevice->GetRenderCaps() & FXRC_GET_BITS)) {
    oriDevice.reset(new CFX_DIBitmap);
    if (!m_pDevice->CreateCompatibleBitmap(oriDevice.get(), width, height))
      return TRUE;
    m_pDevice->GetDIBits(oriDevice.get(), rect.left, rect.top);
  }
  if (!bitmap_device.Create(width, height, FXDIB_Argb, oriDevice.get()))
    return TRUE;
  CFX_DIBitmap* bitmap = bitmap_device.GetBitmap();
  bitmap->Clear(0);
  CFX_Matrix new_matrix = *pObj2Device;
  new_matrix.TranslateI(-rect.left, -rect.top);
  new_matrix.Scale(scaleX, scaleY);
  std::unique_ptr<CFX_DIBitmap> pTextMask;
  if (bTextClip) {
    pTextMask.reset(new CFX_DIBitmap);
    if (!pTextMask->Create(width, height, FXDIB_8bppMask))
      return TRUE;

    pTextMask->Clear(0);
    CFX_FxgeDevice text_device;
    text_device.Attach(pTextMask.get(), false, nullptr, false);
    for (uint32_t i = 0; i < pPageObj->m_ClipPath.GetTextCount(); i++) {
      CPDF_TextObject* textobj = pPageObj->m_ClipPath.GetText(i);
      if (!textobj) {
        break;
      }
      CFX_Matrix text_matrix;
      textobj->GetTextMatrix(&text_matrix);
      CPDF_TextRenderer::DrawTextPath(
          &text_device, textobj->m_nChars, textobj->m_pCharCodes,
          textobj->m_pCharPos, textobj->m_TextState.GetFont(),
          textobj->m_TextState.GetFontSize(), &text_matrix, &new_matrix,
          textobj->m_GraphState.GetObject(), (FX_ARGB)-1, 0, nullptr, 0);
    }
  }
  CPDF_RenderStatus bitmap_render;
  bitmap_render.Initialize(m_pContext, &bitmap_device, nullptr, m_pStopObj,
                           nullptr, nullptr, &m_Options, 0, m_bDropObjects,
                           pFormResource, TRUE);
  bitmap_render.ProcessObjectNoClip(pPageObj, &new_matrix);
  m_bStopped = bitmap_render.m_bStopped;
  if (pSMaskDict) {
    CFX_Matrix smask_matrix = *pPageObj->m_GeneralState.GetSMaskMatrix();
    smask_matrix.Concat(*pObj2Device);
    std::unique_ptr<CFX_DIBSource> pSMaskSource(
        LoadSMask(pSMaskDict, &rect, &smask_matrix));
    if (pSMaskSource)
      bitmap->MultiplyAlpha(pSMaskSource.get());
  }
  if (pTextMask) {
    bitmap->MultiplyAlpha(pTextMask.get());
    pTextMask.reset();
  }
  int32_t blitAlpha = 255;
  if (Transparency & PDFTRANS_GROUP && group_alpha != 1.0f) {
    blitAlpha = (int32_t)(group_alpha * 255);
#ifndef _SKIA_SUPPORT_
    bitmap->MultiplyAlpha(blitAlpha);
    blitAlpha = 255;
#endif
  }
  Transparency = m_Transparency;
  if (pPageObj->IsForm()) {
    Transparency |= PDFTRANS_GROUP;
  }
  CompositeDIBitmap(bitmap, rect.left, rect.top, 0, blitAlpha, blend_type,
                    Transparency);
#if defined _SKIA_SUPPORT_
  DebugVerifyDeviceIsPreMultiplied();
#endif
  return TRUE;
}
Пример #26
0
void CFX_Matrix::TransformVector(CFX_Vector& v) const {
    FX_FLOAT fx = a * v.x + c * v.y;
    FX_FLOAT fy = b * v.x + d * v.y;
    v.x = FXSYS_round(fx);
    v.y = FXSYS_round(fy);
}
void CScript_LayoutPseudoModel::HWXY(CFXJSE_Arguments* pArguments,
                                     XFA_LAYOUTMODEL_HWXY layoutModel) {
  int32_t iLength = pArguments->GetLength();
  if (iLength < 1 || iLength > 3) {
    const FX_WCHAR* methodName = nullptr;
    switch (layoutModel) {
      case XFA_LAYOUTMODEL_H:
        methodName = L"h";
        break;
      case XFA_LAYOUTMODEL_W:
        methodName = L"w";
        break;
      case XFA_LAYOUTMODEL_X:
        methodName = L"x";
        break;
      case XFA_LAYOUTMODEL_Y:
        methodName = L"y";
        break;
    }
    ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, methodName);
    return;
  }
  CXFA_Node* pNode = nullptr;
  CFX_WideString wsUnit(L"pt");
  int32_t iIndex = 0;
  if (iLength >= 1) {
    pNode = static_cast<CXFA_Node*>(pArguments->GetObject(0));
  }
  if (iLength >= 2) {
    CFX_ByteString bsUnit = pArguments->GetUTF8String(1);
    if (!bsUnit.IsEmpty()) {
      wsUnit = CFX_WideString::FromUTF8(bsUnit.AsStringC());
    }
  }
  if (iLength >= 3) {
    iIndex = pArguments->GetInt32(2);
  }
  if (!pNode) {
    return;
  }
  CXFA_LayoutProcessor* pDocLayout = m_pDocument->GetDocLayout();
  if (!pDocLayout) {
    return;
  }
  CFX_RectF rtRect;
  CXFA_Measurement measure;
  CXFA_LayoutItem* pLayoutItem = pDocLayout->GetLayoutItem(pNode);
  if (!pLayoutItem) {
    return;
  }
  while (iIndex > 0 && pLayoutItem) {
    pLayoutItem = pLayoutItem->GetNext();
    iIndex--;
  }
  CFXJSE_Value* pValue = pArguments->GetReturnValue();
  if (!pLayoutItem) {
    pValue->SetFloat(0);
    return;
  }
  pLayoutItem->GetRect(rtRect, TRUE);
  switch (layoutModel) {
    case XFA_LAYOUTMODEL_H:
      measure.Set(rtRect.height, XFA_UNIT_Pt);
      break;
    case XFA_LAYOUTMODEL_W:
      measure.Set(rtRect.width, XFA_UNIT_Pt);
      break;
    case XFA_LAYOUTMODEL_X:
      measure.Set(rtRect.left, XFA_UNIT_Pt);
      break;
    case XFA_LAYOUTMODEL_Y:
      measure.Set(rtRect.top, XFA_UNIT_Pt);
      break;
  }
  XFA_UNIT unit = measure.GetUnit(wsUnit.AsStringC());
  FX_FLOAT fValue = measure.ToUnit(unit);
  fValue = FXSYS_round(fValue * 1000) / 1000.0f;
  if (pValue)
    pValue->SetFloat(fValue);
}
Пример #28
0
void CPDF_RenderStatus::DrawTilingPattern(CPDF_TilingPattern* pPattern,
                                          CPDF_PageObject* pPageObj,
                                          const CFX_Matrix* pObj2Device,
                                          FX_BOOL bStroke) {
  if (!pPattern->Load()) {
    return;
  }
  m_pDevice->SaveState();
  if (pPageObj->m_Type == PDFPAGE_PATH) {
    if (!SelectClipPath((CPDF_PathObject*)pPageObj, pObj2Device, bStroke)) {
      m_pDevice->RestoreState();
      return;
    }
  } else if (pPageObj->m_Type == PDFPAGE_IMAGE) {
    FX_RECT rect = pPageObj->GetBBox(pObj2Device);
    m_pDevice->SetClip_Rect(&rect);
  } else {
    return;
  }
  FX_RECT clip_box = m_pDevice->GetClipBox();
  if (clip_box.IsEmpty()) {
    m_pDevice->RestoreState();
    return;
  }
  CFX_Matrix dCTM = m_pDevice->GetCTM();
  FX_FLOAT sa = FXSYS_fabs(dCTM.a);
  FX_FLOAT sd = FXSYS_fabs(dCTM.d);
  clip_box.right = clip_box.left + (int32_t)FXSYS_ceil(clip_box.Width() * sa);
  clip_box.bottom = clip_box.top + (int32_t)FXSYS_ceil(clip_box.Height() * sd);
  CFX_Matrix mtPattern2Device = pPattern->m_Pattern2Form;
  mtPattern2Device.Concat(*pObj2Device);
  GetScaledMatrix(mtPattern2Device);
  FX_BOOL bAligned = FALSE;
  if (pPattern->m_BBox.left == 0 && pPattern->m_BBox.bottom == 0 &&
      pPattern->m_BBox.right == pPattern->m_XStep &&
      pPattern->m_BBox.top == pPattern->m_YStep &&
      (mtPattern2Device.IsScaled() || mtPattern2Device.Is90Rotated())) {
    bAligned = TRUE;
  }
  CFX_FloatRect cell_bbox = pPattern->m_BBox;
  mtPattern2Device.TransformRect(cell_bbox);
  int width = (int)FXSYS_ceil(cell_bbox.Width());
  int height = (int)FXSYS_ceil(cell_bbox.Height());
  if (width == 0) {
    width = 1;
  }
  if (height == 0) {
    height = 1;
  }
  int min_col, max_col, min_row, max_row;
  CFX_Matrix mtDevice2Pattern;
  mtDevice2Pattern.SetReverse(mtPattern2Device);
  CFX_FloatRect clip_box_p(clip_box);
  clip_box_p.Transform(&mtDevice2Pattern);
  min_col = (int)FXSYS_ceil(
      FXSYS_Div(clip_box_p.left - pPattern->m_BBox.right, pPattern->m_XStep));
  max_col = (int)FXSYS_floor(
      FXSYS_Div(clip_box_p.right - pPattern->m_BBox.left, pPattern->m_XStep));
  min_row = (int)FXSYS_ceil(
      FXSYS_Div(clip_box_p.bottom - pPattern->m_BBox.top, pPattern->m_YStep));
  max_row = (int)FXSYS_floor(
      FXSYS_Div(clip_box_p.top - pPattern->m_BBox.bottom, pPattern->m_YStep));
  if (width > clip_box.Width() || height > clip_box.Height() ||
      width * height > clip_box.Width() * clip_box.Height()) {
    CPDF_GraphicStates* pStates = NULL;
    if (!pPattern->m_bColored) {
      pStates = CloneObjStates(pPageObj, bStroke);
    }
    CPDF_Dictionary* pFormResource = NULL;
    if (pPattern->m_pForm->m_pFormDict) {
      pFormResource = pPattern->m_pForm->m_pFormDict->GetDict("Resources");
    }
    for (int col = min_col; col <= max_col; col++)
      for (int row = min_row; row <= max_row; row++) {
        FX_FLOAT orig_x, orig_y;
        orig_x = col * pPattern->m_XStep;
        orig_y = row * pPattern->m_YStep;
        mtPattern2Device.Transform(orig_x, orig_y);
        CFX_Matrix matrix = *pObj2Device;
        matrix.Translate(orig_x - mtPattern2Device.e,
                         orig_y - mtPattern2Device.f);
        m_pDevice->SaveState();
        CPDF_RenderStatus status;
        status.Initialize(m_pContext, m_pDevice, NULL, NULL, this, pStates,
                          &m_Options, pPattern->m_pForm->m_Transparency,
                          m_bDropObjects, pFormResource);
        status.RenderObjectList(pPattern->m_pForm, &matrix);
        m_pDevice->RestoreState();
      }
    m_pDevice->RestoreState();
    delete pStates;
    return;
  }
  if (bAligned) {
    int orig_x = FXSYS_round(mtPattern2Device.e);
    int orig_y = FXSYS_round(mtPattern2Device.f);
    min_col = (clip_box.left - orig_x) / width;
    if (clip_box.left < orig_x) {
      min_col--;
    }
    max_col = (clip_box.right - orig_x) / width;
    if (clip_box.right <= orig_x) {
      max_col--;
    }
    min_row = (clip_box.top - orig_y) / height;
    if (clip_box.top < orig_y) {
      min_row--;
    }
    max_row = (clip_box.bottom - orig_y) / height;
    if (clip_box.bottom <= orig_y) {
      max_row--;
    }
  }
  FX_FLOAT left_offset = cell_bbox.left - mtPattern2Device.e;
  FX_FLOAT top_offset = cell_bbox.bottom - mtPattern2Device.f;
  CFX_DIBitmap* pPatternBitmap = NULL;
  if (width * height < 16) {
    CFX_DIBitmap* pEnlargedBitmap =
        DrawPatternBitmap(m_pContext->m_pDocument, m_pContext->m_pPageCache,
                          pPattern, pObj2Device, 8, 8, m_Options.m_Flags);
    pPatternBitmap = pEnlargedBitmap->StretchTo(width, height);
    delete pEnlargedBitmap;
  } else {
    pPatternBitmap = DrawPatternBitmap(
        m_pContext->m_pDocument, m_pContext->m_pPageCache, pPattern,
        pObj2Device, width, height, m_Options.m_Flags);
  }
  if (!pPatternBitmap) {
    m_pDevice->RestoreState();
    return;
  }
  if (m_Options.m_ColorMode == RENDER_COLOR_GRAY) {
    pPatternBitmap->ConvertColorScale(m_Options.m_ForeColor,
                                      m_Options.m_BackColor);
  }
  FX_ARGB fill_argb = GetFillArgb(pPageObj);
  int clip_width = clip_box.right - clip_box.left;
  int clip_height = clip_box.bottom - clip_box.top;
  CFX_DIBitmap screen;
  if (!screen.Create(clip_width, clip_height, FXDIB_Argb)) {
    return;
  }
  screen.Clear(0);
  FX_DWORD* src_buf = (FX_DWORD*)pPatternBitmap->GetBuffer();
  for (int col = min_col; col <= max_col; col++) {
    for (int row = min_row; row <= max_row; row++) {
      int start_x, start_y;
      if (bAligned) {
        start_x = FXSYS_round(mtPattern2Device.e) + col * width - clip_box.left;
        start_y = FXSYS_round(mtPattern2Device.f) + row * height - clip_box.top;
      } else {
        FX_FLOAT orig_x = col * pPattern->m_XStep;
        FX_FLOAT orig_y = row * pPattern->m_YStep;
        mtPattern2Device.Transform(orig_x, orig_y);
        start_x = FXSYS_round(orig_x + left_offset) - clip_box.left;
        start_y = FXSYS_round(orig_y + top_offset) - clip_box.top;
      }
      if (width == 1 && height == 1) {
        if (start_x < 0 || start_x >= clip_box.Width() || start_y < 0 ||
            start_y >= clip_box.Height()) {
          continue;
        }
        FX_DWORD* dest_buf =
            (FX_DWORD*)(screen.GetBuffer() + screen.GetPitch() * start_y +
                        start_x * 4);
        if (pPattern->m_bColored) {
          *dest_buf = *src_buf;
        } else {
          *dest_buf = (*(uint8_t*)src_buf << 24) | (fill_argb & 0xffffff);
        }
      } else {
        if (pPattern->m_bColored) {
          screen.CompositeBitmap(start_x, start_y, width, height,
                                 pPatternBitmap, 0, 0);
        } else {
          screen.CompositeMask(start_x, start_y, width, height, pPatternBitmap,
                               fill_argb, 0, 0);
        }
      }
    }
  }
  CompositeDIBitmap(&screen, clip_box.left, clip_box.top, 0, 255,
                    FXDIB_BLEND_NORMAL, FALSE);
  m_pDevice->RestoreState();
  delete pPatternBitmap;
}
Пример #29
0
void CPDF_ContentParser::Continue(IFX_Pause* pPause)
{
    while (m_Status == ToBeContinued) {
        if (m_InternalStage == PAGEPARSE_STAGE_PARSE) {
            if (m_pStreamFilter == NULL) {
                if (m_CurrentOffset == m_nStreams) {
                    m_InternalStage = PAGEPARSE_STAGE_CHECKCLIP;
                    if (m_pType3Char) {
                        m_pType3Char->m_bColored = m_pParser->m_bColored;
                        m_pType3Char->m_Width = FXSYS_round(m_pParser->m_Type3Data[0] * 1000);
                        m_pType3Char->m_BBox.left = FXSYS_round(m_pParser->m_Type3Data[2] * 1000);
                        m_pType3Char->m_BBox.bottom = FXSYS_round(m_pParser->m_Type3Data[3] * 1000);
                        m_pType3Char->m_BBox.right = FXSYS_round(m_pParser->m_Type3Data[4] * 1000);
                        m_pType3Char->m_BBox.top = FXSYS_round(m_pParser->m_Type3Data[5] * 1000);
                        m_pType3Char->m_bPageRequired = m_pParser->m_bResourceMissing;
                    }
                    delete m_pParser;
                    m_pParser = NULL;
                    continue;
                }
                CPDF_Object* pContent = m_pObjects->m_pFormDict->GetElementValue(FX_BSTRC("Contents"));
                if (pContent->GetType() == PDFOBJ_STREAM) {
                    m_pStreamFilter = ((CPDF_Stream*)pContent)->GetStreamFilter();
                } else {
                    CPDF_Stream* pStream = ((CPDF_Array*)pContent)->GetStream(m_CurrentOffset);
                    if (pStream == NULL) {
                        m_CurrentOffset ++;
                        continue;
                    }
                    m_pStreamFilter = pStream->GetStreamFilter();
                }
            }
            FX_DWORD len = m_pStreamFilter->ReadBlock(m_pParser->m_pStreamBuf, STREAM_PARSE_BUFSIZE);
            m_pParser->InputData(m_pParser->m_pStreamBuf, len);
            if (m_pParser->m_bAbort) {
                delete m_pStreamFilter;
                m_pStreamFilter = NULL;
                m_Status = Done;
                delete m_pParser;
                m_pParser = NULL;
                return;
            }
            if (len < STREAM_PARSE_BUFSIZE) {
                m_pParser->Finish();
                m_CurrentOffset ++;
                delete m_pStreamFilter;
                m_pStreamFilter = NULL;
            }
            if (pPause && pPause->NeedToPauseNow()) {
                return;
            }
        }
        if (m_InternalStage == PAGEPARSE_STAGE_CHECKCLIP) {
            FX_POSITION pos = m_pObjects->m_ObjectList.GetHeadPosition();
            while (pos) {
                CPDF_PageObject* pObj = (CPDF_PageObject*)m_pObjects->m_ObjectList.GetNext(pos);
                if (pObj == NULL) {
                    continue;
                }
                if (pObj->m_ClipPath.IsNull()) {
                    continue;
                }
                if (pObj->m_ClipPath.GetPathCount() != 1) {
                    continue;
                }
                if (pObj->m_ClipPath.GetTextCount()) {
                    continue;
                }
                CPDF_Path ClipPath = pObj->m_ClipPath.GetPath(0);
                if (!ClipPath.IsRect() || pObj->m_Type == PDFPAGE_SHADING) {
                    continue;
                }
                CFX_FloatRect old_rect(ClipPath.GetPointX(0), ClipPath.GetPointY(0),
                                       ClipPath.GetPointX(2), ClipPath.GetPointY(2));
                CFX_FloatRect obj_rect(pObj->m_Left, pObj->m_Bottom, pObj->m_Right, pObj->m_Top);
                if (old_rect.Contains(obj_rect)) {
                    pObj->m_ClipPath.SetNull();
                }
            }
            if (m_pObjects->m_ObjectList.GetCount() == 1) {
                CPDF_PageObject* pObj = (CPDF_PageObject*)m_pObjects->m_ObjectList.GetAt(m_pObjects->m_ObjectList.GetHeadPosition());
                if (pObj && pObj->m_Type == PDFPAGE_TEXT) {
                    CPDF_TextObject* pText = (CPDF_TextObject*)pObj;
                }
            }
            m_Status = Done;
            return;
        }
    }
}
Пример #30
0
int32_t CFX_Matrix::TransformXDistance(int32_t dx) const {
    FX_FLOAT fx = a * dx, fy = b * dx;
    return FXSYS_round(FXSYS_sqrt(fx * fx + fy * fy));
}