summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorweili <weili@chromium.org>2016-12-12 10:21:19 -0800
committerCommit bot <commit-bot@chromium.org>2016-12-12 10:21:19 -0800
commitb1125f8daf52c750f6b642a343195c70f47f49f1 (patch)
tree52445831a25392c52ffb4374039a68535d32e180
parent5dbb129eb0e9f2ba9f0b897fd0589ca28add195d (diff)
downloadpdfium-b1125f8daf52c750f6b642a343195c70f47f49f1.tar.xz
Fix dotted line drawing for GDI device driver
When GDI device driver draws a dotted line, it also clip the line into the device context's bound before drawing. This CL includes a couple fixes: -- When this driver is used for EMF drawing, the drawing is not bound to the device context so clipping is not needed; -- Transformation needs to be applied before clipping since the transformation may move the line into the bound; -- While checking for out-of-bound flags, bit operations are needed to make sure the discarded line is completely out of bound, not partially inside the bound; BUG=chromium:539533 Review-Url: https://codereview.chromium.org/2562533002
-rw-r--r--core/fxge/win32/fx_win32_device.cpp74
-rw-r--r--core/fxge/win32/win32_int.h7
2 files changed, 42 insertions, 39 deletions
diff --git a/core/fxge/win32/fx_win32_device.cpp b/core/fxge/win32/fx_win32_device.cpp
index e0d2e60a15..2746587be2 100644
--- a/core/fxge/win32/fx_win32_device.cpp
+++ b/core/fxge/win32/fx_win32_device.cpp
@@ -738,7 +738,9 @@ CGdiDeviceDriver::CGdiDeviceDriver(HDC hDC, int device_class) {
CWin32Platform* pPlatform =
(CWin32Platform*)CFX_GEModule::Get()->GetPlatformData();
SetStretchBltMode(hDC, pPlatform->m_bHalfTone ? HALFTONE : COLORONCOLOR);
- if (GetObjectType(m_hDC) == OBJ_MEMDC) {
+ DWORD obj_type = GetObjectType(m_hDC);
+ m_bMetafileDCType = obj_type == OBJ_ENHMETADC || obj_type == OBJ_ENHMETAFILE;
+ if (obj_type == OBJ_MEMDC) {
HBITMAP hBitmap = CreateBitmap(1, 1, 1, 1, nullptr);
hBitmap = (HBITMAP)SelectObject(m_hDC, hBitmap);
BITMAP bitmap;
@@ -940,45 +942,45 @@ void* CGdiDeviceDriver::GetPlatformSurface() const {
void CGdiDeviceDriver::DrawLine(FX_FLOAT x1,
FX_FLOAT y1,
FX_FLOAT x2,
- FX_FLOAT y2,
- const CFX_Matrix* pMatrix) {
- bool bStartOutOfBounds = x1 < 0 || x1 > m_Width || y1 < 0 || y1 > m_Height;
- bool bEndOutOfBounds = x2 < 0 || x2 > m_Width || y2 < 0 || y2 > m_Height;
- if (bStartOutOfBounds & bEndOutOfBounds)
- return;
+ FX_FLOAT y2) {
+ if (!m_bMetafileDCType) { // EMF drawing is not bound to the DC.
+ int startOutOfBoundsFlag = (x1 < 0) | ((x1 > m_Width) << 1) |
+ ((y1 < 0) << 2) | ((y1 > m_Height) << 3);
+ int endOutOfBoundsFlag = (x2 < 0) | ((x2 > m_Width) << 1) |
+ ((y2 < 0) << 2) | ((y2 > m_Height) << 3);
+ if (startOutOfBoundsFlag & endOutOfBoundsFlag)
+ return;
- if (bStartOutOfBounds || bEndOutOfBounds) {
- FX_FLOAT x[2];
- FX_FLOAT y[2];
- int np;
+ if (startOutOfBoundsFlag || endOutOfBoundsFlag) {
+ FX_FLOAT x[2];
+ FX_FLOAT y[2];
+ int np;
#ifdef _SKIA_SUPPORT_
- // TODO(caryclark) temporary replacement of antigrain in line function
- // to permit removing antigrain altogether
- rect_base rect = {0.0f, 0.0f, (FX_FLOAT)(m_Width), (FX_FLOAT)(m_Height)};
- np = clip_liang_barsky(x1, y1, x2, y2, rect, x, y);
+ // TODO(caryclark) temporary replacement of antigrain in line function
+ // to permit removing antigrain altogether
+ rect_base rect = {0.0f, 0.0f, (FX_FLOAT)(m_Width), (FX_FLOAT)(m_Height)};
+ np = clip_liang_barsky(x1, y1, x2, y2, rect, x, y);
#else
- agg::rect_base<FX_FLOAT> rect(0.0f, 0.0f, (FX_FLOAT)(m_Width),
- (FX_FLOAT)(m_Height));
- np = agg::clip_liang_barsky<FX_FLOAT>(x1, y1, x2, y2, rect, x, y);
+ agg::rect_base<FX_FLOAT> rect(0.0f, 0.0f, (FX_FLOAT)(m_Width),
+ (FX_FLOAT)(m_Height));
+ np = agg::clip_liang_barsky<FX_FLOAT>(x1, y1, x2, y2, rect, x, y);
#endif
- if (np == 0)
- return;
+ if (np == 0)
+ return;
- if (np == 1) {
- x2 = x[0];
- y2 = y[0];
- } else {
- ASSERT(np == 2);
- x1 = x[0];
- y1 = y[0];
- x2 = x[1];
- y2 = y[1];
+ if (np == 1) {
+ x2 = x[0];
+ y2 = y[0];
+ } else {
+ ASSERT(np == 2);
+ x1 = x[0];
+ y1 = y[0];
+ x2 = x[1];
+ y2 = y[1];
+ }
}
}
- if (pMatrix) {
- pMatrix->Transform(x1, y1);
- pMatrix->Transform(x2, y2);
- }
+
MoveToEx(m_hDC, FXSYS_round(x1), FXSYS_round(y1), nullptr);
LineTo(m_hDC, FXSYS_round(x2), FXSYS_round(y2));
}
@@ -1057,7 +1059,11 @@ bool CGdiDeviceDriver::DrawPath(const CFX_PathData* pPathData,
FX_FLOAT y1 = pPathData->GetPointY(0);
FX_FLOAT x2 = pPathData->GetPointX(1);
FX_FLOAT y2 = pPathData->GetPointY(1);
- DrawLine(x1, y1, x2, y2, pMatrix);
+ if (pMatrix) {
+ pMatrix->Transform(x1, y1);
+ pMatrix->Transform(x2, y2);
+ }
+ DrawLine(x1, y1, x2, y2);
} else {
SetPathToDC(m_hDC, pPathData, pMatrix);
if (pGraphState && stroke_alpha) {
diff --git a/core/fxge/win32/win32_int.h b/core/fxge/win32/win32_int.h
index fa1cc6830e..ae090b72d3 100644
--- a/core/fxge/win32/win32_int.h
+++ b/core/fxge/win32/win32_int.h
@@ -152,11 +152,7 @@ class CGdiDeviceDriver : public IFX_RenderDeviceDriver {
bool GetClipBox(FX_RECT* pRect) override;
void* GetPlatformSurface() const override;
- void DrawLine(FX_FLOAT x1,
- FX_FLOAT y1,
- FX_FLOAT x2,
- FX_FLOAT y2,
- const CFX_Matrix* pMatrix);
+ void DrawLine(FX_FLOAT x1, FX_FLOAT y1, FX_FLOAT x2, FX_FLOAT y2);
bool GDI_SetDIBits(CFX_DIBitmap* pBitmap,
const FX_RECT* pSrcRect,
@@ -177,6 +173,7 @@ class CGdiDeviceDriver : public IFX_RenderDeviceDriver {
uint32_t flags);
HDC m_hDC;
+ bool m_bMetafileDCType;
int m_Width;
int m_Height;
int m_nBitsPerPixel;