Ejemplo n.º 1
0
bool CFX_RenderDevice::DrawPathWithBlend(const CFX_PathData* pPathData,
                                         const CFX_Matrix* pObject2Device,
                                         const CFX_GraphStateData* pGraphState,
                                         uint32_t fill_color,
                                         uint32_t stroke_color,
                                         int fill_mode,
                                         BlendMode blend_type) {
  uint8_t stroke_alpha = pGraphState ? FXARGB_A(stroke_color) : 0;
  uint8_t fill_alpha = (fill_mode & 3) ? FXARGB_A(fill_color) : 0;
  const std::vector<FX_PATHPOINT>& pPoints = pPathData->GetPoints();
  if (stroke_alpha == 0 && pPoints.size() == 2) {
    CFX_PointF pos1 = pPoints[0].m_Point;
    CFX_PointF pos2 = pPoints[1].m_Point;
    if (pObject2Device) {
      pos1 = pObject2Device->Transform(pos1);
      pos2 = pObject2Device->Transform(pos2);
    }
    DrawCosmeticLine(pos1, pos2, fill_color, fill_mode, blend_type);
    return true;
  }

  if ((pPoints.size() == 5 || pPoints.size() == 4) && stroke_alpha == 0) {
    CFX_FloatRect rect_f;
    if (!(fill_mode & FXFILL_RECT_AA) &&
        pPathData->IsRect(pObject2Device, &rect_f)) {
      FX_RECT rect_i = rect_f.GetOuterRect();

      // Depending on the top/bottom, left/right values of the rect it's
      // possible to overflow the Width() and Height() calculations. Check that
      // the rect will have valid dimension before continuing.
      if (!rect_i.Valid())
        return false;

      int width = static_cast<int>(ceil(rect_f.right - rect_f.left));
      if (width < 1) {
        width = 1;
        if (rect_i.left == rect_i.right)
          ++rect_i.right;
      }
      int height = static_cast<int>(ceil(rect_f.top - rect_f.bottom));
      if (height < 1) {
        height = 1;
        if (rect_i.bottom == rect_i.top)
          ++rect_i.bottom;
      }
      if (rect_i.Width() >= width + 1) {
        if (rect_f.left - static_cast<float>(rect_i.left) >
            static_cast<float>(rect_i.right) - rect_f.right) {
          ++rect_i.left;
        } else {
          --rect_i.right;
        }
      }
      if (rect_i.Height() >= height + 1) {
        if (rect_f.top - static_cast<float>(rect_i.top) >
            static_cast<float>(rect_i.bottom) - rect_f.bottom) {
          ++rect_i.top;
        } else {
          --rect_i.bottom;
        }
      }
      if (FillRectWithBlend(rect_i, fill_color, blend_type))
        return true;
    }
  }
  if ((fill_mode & 3) && stroke_alpha == 0 && !(fill_mode & FX_FILL_STROKE) &&
      !(fill_mode & FX_FILL_TEXT_MODE)) {
    CFX_PathData newPath;
    bool bThin = false;
    bool setIdentity = false;
    if (pPathData->GetZeroAreaPath(pObject2Device,
                                   !!m_pDeviceDriver->GetDriverType(), &newPath,
                                   &bThin, &setIdentity)) {
      CFX_GraphStateData graphState;
      graphState.m_LineWidth = 0.0f;

      uint32_t strokecolor = fill_color;
      if (bThin)
        strokecolor = (((fill_alpha >> 2) << 24) | (strokecolor & 0x00ffffff));

      const CFX_Matrix* pMatrix = nullptr;
      if (pObject2Device && !pObject2Device->IsIdentity() && !setIdentity)
        pMatrix = pObject2Device;

      int smooth_path = FX_ZEROAREA_FILL;
      if (fill_mode & FXFILL_NOPATHSMOOTH)
        smooth_path |= FXFILL_NOPATHSMOOTH;

      m_pDeviceDriver->DrawPath(&newPath, pMatrix, &graphState, 0, strokecolor,
                                smooth_path, blend_type);
    }
Ejemplo n.º 2
0
bool CFX_RenderDevice::DrawPathWithBlend(const CFX_PathData* pPathData,
                                         const CFX_Matrix* pObject2Device,
                                         const CFX_GraphStateData* pGraphState,
                                         uint32_t fill_color,
                                         uint32_t stroke_color,
                                         int fill_mode,
                                         int blend_type) {
  uint8_t stroke_alpha = pGraphState ? FXARGB_A(stroke_color) : 0;
  uint8_t fill_alpha = (fill_mode & 3) ? FXARGB_A(fill_color) : 0;
  if (stroke_alpha == 0 && pPathData->GetPointCount() == 2) {
    FX_PATHPOINT* pPoints = pPathData->GetPoints();
    FX_FLOAT x1, x2, y1, y2;
    if (pObject2Device) {
      pObject2Device->Transform(pPoints[0].m_PointX, pPoints[0].m_PointY, x1,
                                y1);
      pObject2Device->Transform(pPoints[1].m_PointX, pPoints[1].m_PointY, x2,
                                y2);
    } else {
      x1 = pPoints[0].m_PointX;
      y1 = pPoints[0].m_PointY;
      x2 = pPoints[1].m_PointX;
      y2 = pPoints[1].m_PointY;
    }
    DrawCosmeticLine(x1, y1, x2, y2, fill_color, fill_mode, blend_type);
    return true;
  }
  if ((pPathData->GetPointCount() == 5 || pPathData->GetPointCount() == 4) &&
      stroke_alpha == 0) {
    CFX_FloatRect rect_f;
    if (!(fill_mode & FXFILL_RECT_AA) &&
        pPathData->IsRect(pObject2Device, &rect_f)) {
      FX_RECT rect_i = rect_f.GetOuterRect();

      // Depending on the top/bottom, left/right values of the rect it's
      // possible to overflow the Width() and Height() calculations. Check that
      // the rect will have valid dimension before continuing.
      if (!rect_i.Valid())
        return false;

      int width = (int)FXSYS_ceil(rect_f.right - rect_f.left);
      if (width < 1) {
        width = 1;
        if (rect_i.left == rect_i.right)
          rect_i.right++;
      }
      int height = (int)FXSYS_ceil(rect_f.top - rect_f.bottom);
      if (height < 1) {
        height = 1;
        if (rect_i.bottom == rect_i.top)
          rect_i.bottom++;
      }
      if (rect_i.Width() >= width + 1) {
        if (rect_f.left - (FX_FLOAT)(rect_i.left) >
            (FX_FLOAT)(rect_i.right) - rect_f.right) {
          rect_i.left++;
        } else {
          rect_i.right--;
        }
      }
      if (rect_i.Height() >= height + 1) {
        if (rect_f.top - (FX_FLOAT)(rect_i.top) >
            (FX_FLOAT)(rect_i.bottom) - rect_f.bottom) {
          rect_i.top++;
        } else {
          rect_i.bottom--;
        }
      }
      if (FillRectWithBlend(&rect_i, fill_color, blend_type))
        return true;
    }
  }
  if ((fill_mode & 3) && stroke_alpha == 0 && !(fill_mode & FX_FILL_STROKE) &&
      !(fill_mode & FX_FILL_TEXT_MODE)) {
    CFX_PathData newPath;
    bool bThin = false;
    if (pPathData->GetZeroAreaPath(newPath, (CFX_Matrix*)pObject2Device, bThin,
                                   !!m_pDeviceDriver->GetDriverType())) {
      CFX_GraphStateData graphState;
      graphState.m_LineWidth = 0.0f;
      uint32_t strokecolor = fill_color;
      if (bThin)
        strokecolor = (((fill_alpha >> 2) << 24) | (strokecolor & 0x00ffffff));
      CFX_Matrix* pMatrix = nullptr;
      if (pObject2Device && !pObject2Device->IsIdentity())
        pMatrix = (CFX_Matrix*)pObject2Device;
      int smooth_path = FX_ZEROAREA_FILL;
      if (fill_mode & FXFILL_NOPATHSMOOTH)
        smooth_path |= FXFILL_NOPATHSMOOTH;
      m_pDeviceDriver->DrawPath(&newPath, pMatrix, &graphState, 0, strokecolor,
                                smooth_path, blend_type);
    }