Home | History | Annotate | Download | only in ge
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "core/include/fxge/fx_ge.h"
      8 
      9 CFX_RenderDevice::CFX_RenderDevice() {
     10   m_pDeviceDriver = NULL;
     11   m_pBitmap = NULL;
     12 }
     13 CFX_RenderDevice::~CFX_RenderDevice() {
     14   delete m_pDeviceDriver;
     15 }
     16 void CFX_RenderDevice::SetDeviceDriver(IFX_RenderDeviceDriver* pDriver) {
     17   delete m_pDeviceDriver;
     18   m_pDeviceDriver = pDriver;
     19   InitDeviceInfo();
     20 }
     21 void CFX_RenderDevice::InitDeviceInfo() {
     22   m_Width = m_pDeviceDriver->GetDeviceCaps(FXDC_PIXEL_WIDTH);
     23   m_Height = m_pDeviceDriver->GetDeviceCaps(FXDC_PIXEL_HEIGHT);
     24   m_bpp = m_pDeviceDriver->GetDeviceCaps(FXDC_BITS_PIXEL);
     25   m_RenderCaps = m_pDeviceDriver->GetDeviceCaps(FXDC_RENDER_CAPS);
     26   m_DeviceClass = m_pDeviceDriver->GetDeviceCaps(FXDC_DEVICE_CLASS);
     27   if (!m_pDeviceDriver->GetClipBox(&m_ClipBox)) {
     28     m_ClipBox.left = 0;
     29     m_ClipBox.top = 0;
     30     m_ClipBox.right = m_Width;
     31     m_ClipBox.bottom = m_Height;
     32   }
     33 }
     34 FX_BOOL CFX_RenderDevice::StartRendering() {
     35   return m_pDeviceDriver->StartRendering();
     36 }
     37 void CFX_RenderDevice::EndRendering() {
     38   m_pDeviceDriver->EndRendering();
     39 }
     40 void CFX_RenderDevice::SaveState() {
     41   m_pDeviceDriver->SaveState();
     42 }
     43 void CFX_RenderDevice::RestoreState(FX_BOOL bKeepSaved) {
     44   m_pDeviceDriver->RestoreState(bKeepSaved);
     45   UpdateClipBox();
     46 }
     47 int CFX_RenderDevice::GetDeviceCaps(int caps_id) const {
     48   return m_pDeviceDriver->GetDeviceCaps(caps_id);
     49 }
     50 CFX_Matrix CFX_RenderDevice::GetCTM() const {
     51   return m_pDeviceDriver->GetCTM();
     52 }
     53 FX_BOOL CFX_RenderDevice::CreateCompatibleBitmap(CFX_DIBitmap* pDIB,
     54                                                  int width,
     55                                                  int height) const {
     56   if (m_RenderCaps & FXRC_CMYK_OUTPUT) {
     57     return pDIB->Create(width, height, m_RenderCaps & FXRC_ALPHA_OUTPUT
     58                                            ? FXDIB_Cmyka
     59                                            : FXDIB_Cmyk);
     60   }
     61   if (m_RenderCaps & FXRC_BYTEMASK_OUTPUT) {
     62     return pDIB->Create(width, height, FXDIB_8bppMask);
     63   }
     64 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
     65   return pDIB->Create(width, height, m_RenderCaps & FXRC_ALPHA_OUTPUT
     66                                          ? FXDIB_Argb
     67                                          : FXDIB_Rgb32);
     68 #else
     69   return pDIB->Create(
     70       width, height, m_RenderCaps & FXRC_ALPHA_OUTPUT ? FXDIB_Argb : FXDIB_Rgb);
     71 #endif
     72 }
     73 FX_BOOL CFX_RenderDevice::SetClip_PathFill(const CFX_PathData* pPathData,
     74                                            const CFX_Matrix* pObject2Device,
     75                                            int fill_mode) {
     76   if (!m_pDeviceDriver->SetClip_PathFill(pPathData, pObject2Device,
     77                                          fill_mode)) {
     78     return FALSE;
     79   }
     80   UpdateClipBox();
     81   return TRUE;
     82 }
     83 FX_BOOL CFX_RenderDevice::SetClip_PathStroke(
     84     const CFX_PathData* pPathData,
     85     const CFX_Matrix* pObject2Device,
     86     const CFX_GraphStateData* pGraphState) {
     87   if (!m_pDeviceDriver->SetClip_PathStroke(pPathData, pObject2Device,
     88                                            pGraphState)) {
     89     return FALSE;
     90   }
     91   UpdateClipBox();
     92   return TRUE;
     93 }
     94 FX_BOOL CFX_RenderDevice::SetClip_Rect(const FX_RECT* pRect) {
     95   CFX_PathData path;
     96   path.AppendRect((FX_FLOAT)(pRect->left), (FX_FLOAT)(pRect->bottom),
     97                   (FX_FLOAT)(pRect->right), (FX_FLOAT)(pRect->top));
     98   if (!SetClip_PathFill(&path, NULL, FXFILL_WINDING)) {
     99     return FALSE;
    100   }
    101   UpdateClipBox();
    102   return TRUE;
    103 }
    104 void CFX_RenderDevice::UpdateClipBox() {
    105   if (m_pDeviceDriver->GetClipBox(&m_ClipBox)) {
    106     return;
    107   }
    108   m_ClipBox.left = 0;
    109   m_ClipBox.top = 0;
    110   m_ClipBox.right = m_Width;
    111   m_ClipBox.bottom = m_Height;
    112 }
    113 FX_BOOL CFX_RenderDevice::DrawPath(const CFX_PathData* pPathData,
    114                                    const CFX_Matrix* pObject2Device,
    115                                    const CFX_GraphStateData* pGraphState,
    116                                    FX_DWORD fill_color,
    117                                    FX_DWORD stroke_color,
    118                                    int fill_mode,
    119                                    int alpha_flag,
    120                                    void* pIccTransform,
    121                                    int blend_type) {
    122   uint8_t fill_alpha, stroke_alpha;
    123   if (FXGETFLAG_COLORTYPE(alpha_flag)) {
    124     fill_alpha = FXGETFLAG_ALPHA_FILL(alpha_flag);
    125     stroke_alpha = FXGETFLAG_ALPHA_STROKE(alpha_flag);
    126   } else {
    127     fill_alpha = FXARGB_A(fill_color);
    128     stroke_alpha = FXARGB_A(stroke_color);
    129   }
    130   if ((fill_mode & 3) == 0) {
    131     fill_alpha = 0;
    132   }
    133   if (!pGraphState) {
    134     stroke_alpha = 0;
    135   }
    136   if (stroke_alpha == 0 && pPathData->GetPointCount() == 2) {
    137     FX_PATHPOINT* pPoints = pPathData->GetPoints();
    138     FX_FLOAT x1, x2, y1, y2;
    139     if (pObject2Device) {
    140       pObject2Device->Transform(pPoints[0].m_PointX, pPoints[0].m_PointY, x1,
    141                                 y1);
    142       pObject2Device->Transform(pPoints[1].m_PointX, pPoints[1].m_PointY, x2,
    143                                 y2);
    144     } else {
    145       x1 = pPoints[0].m_PointX;
    146       y1 = pPoints[0].m_PointY;
    147       x2 = pPoints[1].m_PointX;
    148       y2 = pPoints[1].m_PointY;
    149     }
    150     DrawCosmeticLine(x1, y1, x2, y2, fill_color, fill_mode, alpha_flag,
    151                      pIccTransform, blend_type);
    152     return TRUE;
    153   }
    154   if ((pPathData->GetPointCount() == 5 || pPathData->GetPointCount() == 4) &&
    155       stroke_alpha == 0) {
    156     CFX_FloatRect rect_f;
    157     if (!(fill_mode & FXFILL_RECT_AA) &&
    158         pPathData->IsRect(pObject2Device, &rect_f)) {
    159       FX_RECT rect_i = rect_f.GetOutterRect();
    160       int width = (int)FXSYS_ceil(rect_f.right - rect_f.left);
    161       if (width < 1) {
    162         width = 1;
    163         if (rect_i.left == rect_i.right) {
    164           rect_i.right++;
    165         }
    166       }
    167       int height = (int)FXSYS_ceil(rect_f.top - rect_f.bottom);
    168       if (height < 1) {
    169         height = 1;
    170         if (rect_i.bottom == rect_i.top) {
    171           rect_i.bottom++;
    172         }
    173       }
    174       if (rect_i.Width() >= width + 1) {
    175         if (rect_f.left - (FX_FLOAT)(rect_i.left) >
    176             (FX_FLOAT)(rect_i.right) - rect_f.right) {
    177           rect_i.left++;
    178         } else {
    179           rect_i.right--;
    180         }
    181       }
    182       if (rect_i.Height() >= height + 1) {
    183         if (rect_f.top - (FX_FLOAT)(rect_i.top) >
    184             (FX_FLOAT)(rect_i.bottom) - rect_f.bottom) {
    185           rect_i.top++;
    186         } else {
    187           rect_i.bottom--;
    188         }
    189       }
    190       if (FillRect(&rect_i, fill_color, alpha_flag, pIccTransform,
    191                    blend_type)) {
    192         return TRUE;
    193       }
    194     }
    195   }
    196   if ((fill_mode & 3) && stroke_alpha == 0 && !(fill_mode & FX_FILL_STROKE) &&
    197       !(fill_mode & FX_FILL_TEXT_MODE)) {
    198     CFX_PathData newPath;
    199     FX_BOOL bThin = FALSE;
    200     if (pPathData->GetZeroAreaPath(newPath, (CFX_Matrix*)pObject2Device, bThin,
    201                                    m_pDeviceDriver->GetDriverType())) {
    202       CFX_GraphStateData graphState;
    203       graphState.m_LineWidth = 0.0f;
    204       FX_DWORD strokecolor = fill_color;
    205       if (bThin) {
    206         if (FXGETFLAG_COLORTYPE(alpha_flag)) {
    207           FXSETFLAG_ALPHA_STROKE(alpha_flag, fill_alpha >> 2);
    208         } else {
    209           strokecolor =
    210               (((fill_alpha >> 2) << 24) | (strokecolor & 0x00ffffff));
    211         }
    212       }
    213       CFX_Matrix* pMatrix = NULL;
    214       if (pObject2Device && !pObject2Device->IsIdentity()) {
    215         pMatrix = (CFX_Matrix*)pObject2Device;
    216       }
    217       int smooth_path = FX_ZEROAREA_FILL;
    218       if (fill_mode & FXFILL_NOPATHSMOOTH) {
    219         smooth_path |= FXFILL_NOPATHSMOOTH;
    220       }
    221       m_pDeviceDriver->DrawPath(&newPath, pMatrix, &graphState, 0, strokecolor,
    222                                 smooth_path, alpha_flag, pIccTransform,
    223                                 blend_type);
    224     }
    225   }
    226   if ((fill_mode & 3) && fill_alpha && stroke_alpha < 0xff &&
    227       (fill_mode & FX_FILL_STROKE)) {
    228     if (!(m_RenderCaps & FXRC_GET_BITS)) {
    229       return FALSE;
    230     }
    231     CFX_FloatRect bbox;
    232     if (pGraphState) {
    233       bbox = pPathData->GetBoundingBox(pGraphState->m_LineWidth,
    234                                        pGraphState->m_MiterLimit);
    235     } else {
    236       bbox = pPathData->GetBoundingBox();
    237     }
    238     if (pObject2Device) {
    239       bbox.Transform(pObject2Device);
    240     }
    241     CFX_Matrix ctm = GetCTM();
    242     FX_FLOAT fScaleX = FXSYS_fabs(ctm.a);
    243     FX_FLOAT fScaleY = FXSYS_fabs(ctm.d);
    244     FX_RECT rect = bbox.GetOutterRect();
    245     CFX_DIBitmap bitmap, Backdrop;
    246     if (!CreateCompatibleBitmap(&bitmap, FXSYS_round(rect.Width() * fScaleX),
    247                                 FXSYS_round(rect.Height() * fScaleY))) {
    248       return FALSE;
    249     }
    250     if (bitmap.HasAlpha()) {
    251       bitmap.Clear(0);
    252       Backdrop.Copy(&bitmap);
    253     } else {
    254       if (!m_pDeviceDriver->GetDIBits(&bitmap, rect.left, rect.top, NULL)) {
    255         return FALSE;
    256       }
    257       Backdrop.Copy(&bitmap);
    258     }
    259     CFX_FxgeDevice bitmap_device;
    260     bitmap_device.Attach(&bitmap, 0, FALSE, &Backdrop, TRUE);
    261     CFX_Matrix matrix;
    262     if (pObject2Device) {
    263       matrix = *pObject2Device;
    264     }
    265     matrix.TranslateI(-rect.left, -rect.top);
    266     matrix.Concat(fScaleX, 0, 0, fScaleY, 0, 0);
    267     if (!bitmap_device.GetDeviceDriver()->DrawPath(
    268             pPathData, &matrix, pGraphState, fill_color, stroke_color,
    269             fill_mode, alpha_flag, pIccTransform, blend_type)) {
    270       return FALSE;
    271     }
    272     FX_RECT src_rect(0, 0, FXSYS_round(rect.Width() * fScaleX),
    273                      FXSYS_round(rect.Height() * fScaleY));
    274     return m_pDeviceDriver->SetDIBits(&bitmap, 0, &src_rect, rect.left,
    275                                       rect.top, FXDIB_BLEND_NORMAL);
    276   }
    277   return m_pDeviceDriver->DrawPath(pPathData, pObject2Device, pGraphState,
    278                                    fill_color, stroke_color, fill_mode,
    279                                    alpha_flag, pIccTransform, blend_type);
    280 }
    281 FX_BOOL CFX_RenderDevice::SetPixel(int x,
    282                                    int y,
    283                                    FX_DWORD color,
    284                                    int alpha_flag,
    285                                    void* pIccTransform) {
    286   if (m_pDeviceDriver->SetPixel(x, y, color, alpha_flag, pIccTransform)) {
    287     return TRUE;
    288   }
    289   FX_RECT rect(x, y, x + 1, y + 1);
    290   return FillRect(&rect, color, alpha_flag, pIccTransform);
    291 }
    292 FX_BOOL CFX_RenderDevice::FillRect(const FX_RECT* pRect,
    293                                    FX_DWORD fill_color,
    294                                    int alpha_flag,
    295                                    void* pIccTransform,
    296                                    int blend_type) {
    297   if (m_pDeviceDriver->FillRect(pRect, fill_color, alpha_flag, pIccTransform,
    298                                 blend_type)) {
    299     return TRUE;
    300   }
    301   if (!(m_RenderCaps & FXRC_GET_BITS)) {
    302     return FALSE;
    303   }
    304   CFX_DIBitmap bitmap;
    305   if (!CreateCompatibleBitmap(&bitmap, pRect->Width(), pRect->Height())) {
    306     return FALSE;
    307   }
    308   if (!m_pDeviceDriver->GetDIBits(&bitmap, pRect->left, pRect->top)) {
    309     return FALSE;
    310   }
    311   if (!bitmap.CompositeRect(0, 0, pRect->Width(), pRect->Height(), fill_color,
    312                             alpha_flag, pIccTransform)) {
    313     return FALSE;
    314   }
    315   FX_RECT src_rect(0, 0, pRect->Width(), pRect->Height());
    316   m_pDeviceDriver->SetDIBits(&bitmap, 0, &src_rect, pRect->left, pRect->top,
    317                              FXDIB_BLEND_NORMAL);
    318   return TRUE;
    319 }
    320 FX_BOOL CFX_RenderDevice::DrawCosmeticLine(FX_FLOAT x1,
    321                                            FX_FLOAT y1,
    322                                            FX_FLOAT x2,
    323                                            FX_FLOAT y2,
    324                                            FX_DWORD color,
    325                                            int fill_mode,
    326                                            int alpha_flag,
    327                                            void* pIccTransform,
    328                                            int blend_type) {
    329   if (((m_RenderCaps & FXRC_ALPHA_PATH) &&
    330        (FXGETFLAG_COLORTYPE(alpha_flag) &&
    331         FXGETFLAG_ALPHA_FILL(alpha_flag) == 0xff)) ||
    332       color >= 0xff000000)
    333     if (m_pDeviceDriver->DrawCosmeticLine(x1, y1, x2, y2, color, alpha_flag,
    334                                           pIccTransform, blend_type)) {
    335       return TRUE;
    336     }
    337   CFX_GraphStateData graph_state;
    338   CFX_PathData path;
    339   path.SetPointCount(2);
    340   path.SetPoint(0, x1, y1, FXPT_MOVETO);
    341   path.SetPoint(1, x2, y2, FXPT_LINETO);
    342   return m_pDeviceDriver->DrawPath(&path, NULL, &graph_state, 0, color,
    343                                    fill_mode, alpha_flag, pIccTransform,
    344                                    blend_type);
    345 }
    346 FX_BOOL CFX_RenderDevice::GetDIBits(CFX_DIBitmap* pBitmap,
    347                                     int left,
    348                                     int top,
    349                                     void* pIccTransform) {
    350   if (!(m_RenderCaps & FXRC_GET_BITS)) {
    351     return FALSE;
    352   }
    353   return m_pDeviceDriver->GetDIBits(pBitmap, left, top, pIccTransform);
    354 }
    355 CFX_DIBitmap* CFX_RenderDevice::GetBackDrop() {
    356   return m_pDeviceDriver->GetBackDrop();
    357 }
    358 FX_BOOL CFX_RenderDevice::SetDIBits(const CFX_DIBSource* pBitmap,
    359                                     int left,
    360                                     int top,
    361                                     int blend_mode,
    362                                     void* pIccTransform) {
    363   ASSERT(!pBitmap->IsAlphaMask());
    364   CFX_Matrix ctm = GetCTM();
    365   FX_FLOAT fScaleX = FXSYS_fabs(ctm.a);
    366   FX_FLOAT fScaleY = FXSYS_fabs(ctm.d);
    367   FX_RECT dest_rect(left, top,
    368                     FXSYS_round(left + pBitmap->GetWidth() / fScaleX),
    369                     FXSYS_round(top + pBitmap->GetHeight() / fScaleY));
    370   dest_rect.Intersect(m_ClipBox);
    371   if (dest_rect.IsEmpty()) {
    372     return TRUE;
    373   }
    374   FX_RECT src_rect(dest_rect.left - left, dest_rect.top - top,
    375                    dest_rect.left - left + dest_rect.Width(),
    376                    dest_rect.top - top + dest_rect.Height());
    377   src_rect.left = FXSYS_round(src_rect.left * fScaleX);
    378   src_rect.top = FXSYS_round(src_rect.top * fScaleY);
    379   src_rect.right = FXSYS_round(src_rect.right * fScaleX);
    380   src_rect.bottom = FXSYS_round(src_rect.bottom * fScaleY);
    381   if ((blend_mode != FXDIB_BLEND_NORMAL && !(m_RenderCaps & FXRC_BLEND_MODE)) ||
    382       (pBitmap->HasAlpha() && !(m_RenderCaps & FXRC_ALPHA_IMAGE))) {
    383     if (!(m_RenderCaps & FXRC_GET_BITS)) {
    384       return FALSE;
    385     }
    386     int bg_pixel_width = FXSYS_round(dest_rect.Width() * fScaleX);
    387     int bg_pixel_height = FXSYS_round(dest_rect.Height() * fScaleY);
    388     CFX_DIBitmap background;
    389     if (!background.Create(
    390             bg_pixel_width, bg_pixel_height,
    391             (m_RenderCaps & FXRC_CMYK_OUTPUT) ? FXDIB_Cmyk : FXDIB_Rgb32)) {
    392       return FALSE;
    393     }
    394     if (!m_pDeviceDriver->GetDIBits(&background, dest_rect.left,
    395                                     dest_rect.top)) {
    396       return FALSE;
    397     }
    398     if (!background.CompositeBitmap(0, 0, bg_pixel_width, bg_pixel_height,
    399                                     pBitmap, src_rect.left, src_rect.top,
    400                                     blend_mode, NULL, FALSE, pIccTransform)) {
    401       return FALSE;
    402     }
    403     FX_RECT src_rect(0, 0, bg_pixel_width, bg_pixel_height);
    404     return m_pDeviceDriver->SetDIBits(&background, 0, &src_rect, dest_rect.left,
    405                                       dest_rect.top, FXDIB_BLEND_NORMAL);
    406   }
    407   return m_pDeviceDriver->SetDIBits(pBitmap, 0, &src_rect, dest_rect.left,
    408                                     dest_rect.top, blend_mode, 0,
    409                                     pIccTransform);
    410 }
    411 FX_BOOL CFX_RenderDevice::StretchDIBits(const CFX_DIBSource* pBitmap,
    412                                         int left,
    413                                         int top,
    414                                         int dest_width,
    415                                         int dest_height,
    416                                         FX_DWORD flags,
    417                                         void* pIccTransform,
    418                                         int blend_mode) {
    419   FX_RECT dest_rect(left, top, left + dest_width, top + dest_height);
    420   FX_RECT clip_box = m_ClipBox;
    421   clip_box.Intersect(dest_rect);
    422   if (clip_box.IsEmpty()) {
    423     return TRUE;
    424   }
    425   return m_pDeviceDriver->StretchDIBits(pBitmap, 0, left, top, dest_width,
    426                                         dest_height, &clip_box, flags, 0,
    427                                         pIccTransform, blend_mode);
    428 }
    429 FX_BOOL CFX_RenderDevice::SetBitMask(const CFX_DIBSource* pBitmap,
    430                                      int left,
    431                                      int top,
    432                                      FX_DWORD argb,
    433                                      int alpha_flag,
    434                                      void* pIccTransform) {
    435   FX_RECT src_rect(0, 0, pBitmap->GetWidth(), pBitmap->GetHeight());
    436   return m_pDeviceDriver->SetDIBits(pBitmap, argb, &src_rect, left, top,
    437                                     FXDIB_BLEND_NORMAL, alpha_flag,
    438                                     pIccTransform);
    439 }
    440 FX_BOOL CFX_RenderDevice::StretchBitMask(const CFX_DIBSource* pBitmap,
    441                                          int left,
    442                                          int top,
    443                                          int dest_width,
    444                                          int dest_height,
    445                                          FX_DWORD argb,
    446                                          FX_DWORD flags,
    447                                          int alpha_flag,
    448                                          void* pIccTransform) {
    449   FX_RECT dest_rect(left, top, left + dest_width, top + dest_height);
    450   FX_RECT clip_box = m_ClipBox;
    451   clip_box.Intersect(dest_rect);
    452   return m_pDeviceDriver->StretchDIBits(pBitmap, argb, left, top, dest_width,
    453                                         dest_height, &clip_box, flags,
    454                                         alpha_flag, pIccTransform);
    455 }
    456 FX_BOOL CFX_RenderDevice::StartDIBits(const CFX_DIBSource* pBitmap,
    457                                       int bitmap_alpha,
    458                                       FX_DWORD argb,
    459                                       const CFX_Matrix* pMatrix,
    460                                       FX_DWORD flags,
    461                                       void*& handle,
    462                                       int alpha_flag,
    463                                       void* pIccTransform,
    464                                       int blend_mode) {
    465   return m_pDeviceDriver->StartDIBits(pBitmap, bitmap_alpha, argb, pMatrix,
    466                                       flags, handle, alpha_flag, pIccTransform,
    467                                       blend_mode);
    468 }
    469 FX_BOOL CFX_RenderDevice::ContinueDIBits(void* handle, IFX_Pause* pPause) {
    470   return m_pDeviceDriver->ContinueDIBits(handle, pPause);
    471 }
    472 void CFX_RenderDevice::CancelDIBits(void* handle) {
    473   m_pDeviceDriver->CancelDIBits(handle);
    474 }
    475