OLD | NEW |
1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
6 | 6 |
7 #include "../../../include/fxcrt/fx_ext.h" | 7 #include "../../../include/fxcrt/fx_ext.h" |
8 #include "../../../include/fxge/fx_freetype.h" | 8 #include "../../../include/fxge/fx_freetype.h" |
9 #include "../../../include/fxge/fx_ge.h" | 9 #include "../../../include/fxge/fx_ge.h" |
10 #include "../agg/include/fx_agg_driver.h" | 10 #include "../agg/include/fx_agg_driver.h" |
11 #include "../dib/dib_int.h" | 11 #include "../dib/dib_int.h" |
12 #include "../ge/text_int.h" | 12 #include "../ge/text_int.h" |
13 | 13 |
14 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ | 14 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ |
15 #include "apple_int.h" | 15 #include "apple_int.h" |
16 #include "../../../include/fxge/fx_ge_apple.h" | 16 #include "../../../include/fxge/fx_ge_apple.h" |
17 #ifndef CGFLOAT_IS_DOUBLE | 17 #ifndef CGFLOAT_IS_DOUBLE |
18 #error Expected CGFLOAT_IS_DOUBLE to be defined by CoreGraphics headers | 18 #error Expected CGFLOAT_IS_DOUBLE to be defined by CoreGraphics headers |
19 #endif | 19 #endif |
20 void* CQuartz2D::createGraphics(CFX_DIBitmap* pBitmap) | 20 void* CQuartz2D::createGraphics(CFX_DIBitmap* pBitmap) { |
21 { | 21 if (!pBitmap) { |
22 if (!pBitmap) { | 22 return NULL; |
23 return NULL; | 23 } |
24 } | 24 CGBitmapInfo bmpInfo = kCGBitmapByteOrder32Little; |
25 CGBitmapInfo bmpInfo = kCGBitmapByteOrder32Little; | 25 switch (pBitmap->GetFormat()) { |
26 switch (pBitmap->GetFormat()) { | 26 case FXDIB_Rgb32: |
27 case FXDIB_Rgb32: | 27 bmpInfo |= kCGImageAlphaNoneSkipFirst; |
28 bmpInfo |= kCGImageAlphaNoneSkipFirst; | 28 break; |
29 break; | 29 case FXDIB_Argb: |
30 case FXDIB_Argb: | 30 default: |
31 default: | 31 return NULL; |
32 return NULL; | 32 } |
33 } | 33 CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); |
34 CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); | 34 CGContextRef context = CGBitmapContextCreate( |
35 CGContextRef context = CGBitmapContextCreate(pBitmap->GetBuffer(), | 35 pBitmap->GetBuffer(), pBitmap->GetWidth(), pBitmap->GetHeight(), 8, |
36 pBitmap->GetWidth(), | 36 pBitmap->GetPitch(), colorSpace, bmpInfo); |
37 pBitmap->GetHeight(), | 37 CGColorSpaceRelease(colorSpace); |
38 8, | 38 return context; |
39 pBitmap->GetPitch(), | 39 } |
40 colorSpace, | 40 void CQuartz2D::destroyGraphics(void* graphics) { |
41 bmpInfo); | 41 if (graphics) { |
42 CGColorSpaceRelease(colorSpace); | 42 CGContextRelease((CGContextRef)graphics); |
43 return context; | 43 } |
44 } | 44 } |
45 void CQuartz2D::destroyGraphics(void* graphics) | 45 void* CQuartz2D::CreateFont(const uint8_t* pFontData, FX_DWORD dwFontSize) { |
46 { | 46 CGDataProviderRef pDataProvider = |
47 if (graphics) { | 47 CGDataProviderCreateWithData(NULL, pFontData, (size_t)dwFontSize, NULL); |
48 CGContextRelease((CGContextRef) graphics); | 48 if (NULL == pDataProvider) { |
49 } | 49 return NULL; |
50 } | 50 } |
51 void* CQuartz2D::CreateFont(const uint8_t* pFontData, FX_DWORD dwFontSize) | 51 CGFontRef pCGFont = CGFontCreateWithDataProvider(pDataProvider); |
52 { | 52 CGDataProviderRelease(pDataProvider); |
53 CGDataProviderRef pDataProvider = CGDataProviderCreateWithData(NULL, pFontDa
ta, (size_t)dwFontSize, NULL); | 53 return pCGFont; |
54 if (NULL == pDataProvider) { | 54 } |
55 return NULL; | 55 void CQuartz2D::DestroyFont(void* pFont) { |
56 } | 56 CGFontRelease((CGFontRef)pFont); |
57 CGFontRef pCGFont = CGFontCreateWithDataProvider(pDataProvider); | 57 } |
58 CGDataProviderRelease(pDataProvider); | 58 void CQuartz2D::setGraphicsTextMatrix(void* graphics, |
59 return pCGFont; | 59 CFX_AffineMatrix* matrix) { |
60 } | 60 if (!graphics || !matrix) { |
61 void CQuartz2D::DestroyFont(void* pFont) | 61 return; |
62 { | 62 } |
63 CGFontRelease((CGFontRef)pFont); | 63 CGContextRef context = (CGContextRef)graphics; |
64 } | 64 CGFloat ty = CGBitmapContextGetHeight(context) - matrix->f; |
65 void CQuartz2D::setGraphicsTextMatrix(void* graphics, CFX_AffineMatrix* matrix) | 65 CGContextSetTextMatrix( |
66 { | 66 context, CGAffineTransformMake(matrix->a, matrix->b, matrix->c, matrix->d, |
67 if (!graphics || !matrix) { | 67 matrix->e, ty)); |
68 return; | 68 } |
69 } | 69 FX_BOOL CQuartz2D::drawGraphicsString(void* graphics, |
70 CGContextRef context = (CGContextRef) graphics; | 70 void* font, |
71 CGFloat ty = CGBitmapContextGetHeight(context) - matrix->f; | 71 FX_FLOAT fontSize, |
72 CGContextSetTextMatrix(context, CGAffineTransformMake(matrix->a, | 72 FX_WORD* glyphIndices, |
73 matrix->b, | 73 CGPoint* glyphPositions, |
74 matrix->c, | 74 int32_t charsCount, |
75 matrix->d, | 75 FX_ARGB argb, |
76 matrix->e, | 76 CFX_AffineMatrix* matrix) { |
77 ty)); | 77 if (!graphics) { |
78 } | 78 return FALSE; |
79 FX_BOOL CQuartz2D::drawGraphicsString(void* graphics, | 79 } |
80 void* font, | 80 CGContextRef context = (CGContextRef)graphics; |
81 FX_FLOAT fontSize, | 81 CGContextSetFont(context, (CGFontRef)font); |
82 FX_WORD* glyphIndices, | 82 CGContextSetFontSize(context, fontSize); |
83 CGPoint* glyphPositions, | 83 if (matrix) { |
84 int32_t charsCount, | 84 CGAffineTransform m = CGContextGetTextMatrix(context); |
85 FX_ARGB argb, | 85 m = CGAffineTransformConcat( |
86 CFX_AffineMatrix* matrix ) | 86 m, CGAffineTransformMake(matrix->a, matrix->b, matrix->c, matrix->d, |
87 { | 87 matrix->e, matrix->f)); |
88 if (!graphics) { | 88 CGContextSetTextMatrix(context, m); |
89 return FALSE; | 89 } |
90 } | 90 int32_t a, r, g, b; |
91 CGContextRef context = (CGContextRef) graphics; | 91 ArgbDecode(argb, a, r, g, b); |
92 CGContextSetFont(context, (CGFontRef)font); | 92 CGContextSetRGBFillColor(context, r / 255.f, g / 255.f, b / 255.f, a / 255.f); |
93 CGContextSetFontSize(context, fontSize); | 93 CGContextSaveGState(context); |
94 if (matrix) { | 94 #if CGFLOAT_IS_DOUBLE |
95 CGAffineTransform m = CGContextGetTextMatrix(context); | 95 CGPoint* glyphPositionsCG = new CGPoint[charsCount]; |
96 m = CGAffineTransformConcat(m, | 96 if (!glyphPositionsCG) { |
97 CGAffineTransformMake(matrix->a, | 97 return FALSE; |
98 matrix->b, | 98 } |
99 matrix->c, | 99 for (int index = 0; index < charsCount; ++index) { |
100 matrix->d, | 100 glyphPositionsCG[index].x = glyphPositions[index].x; |
101 matrix->e, | 101 glyphPositionsCG[index].y = glyphPositions[index].y; |
102 matrix->f)); | 102 } |
103 CGContextSetTextMatrix(context, m); | 103 #else |
104 } | 104 CGPoint* glyphPositionsCG = (CGPoint*)glyphPositions; |
105 int32_t a, r, g, b; | 105 #endif |
106 ArgbDecode(argb, a, r, g, b); | 106 CGContextShowGlyphsAtPositions(context, (CGGlyph*)glyphIndices, |
107 CGContextSetRGBFillColor(context, | 107 glyphPositionsCG, charsCount); |
108 r / 255.f, | 108 #if CGFLOAT_IS_DOUBLE |
109 g / 255.f, | 109 delete[] glyphPositionsCG; |
110 b / 255.f, | 110 #endif |
| 111 CGContextRestoreGState(context); |
| 112 return TRUE; |
| 113 } |
| 114 void CQuartz2D::saveGraphicsState(void* graphics) { |
| 115 if (graphics) { |
| 116 CGContextSaveGState((CGContextRef)graphics); |
| 117 } |
| 118 } |
| 119 void CQuartz2D::restoreGraphicsState(void* graphics) { |
| 120 if (graphics) { |
| 121 CGContextRestoreGState((CGContextRef)graphics); |
| 122 } |
| 123 } |
| 124 static CGContextRef createContextWithBitmap(CFX_DIBitmap* pBitmap) { |
| 125 if (!pBitmap || pBitmap->IsCmykImage() || pBitmap->GetBPP() < 32) { |
| 126 return NULL; |
| 127 } |
| 128 CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Little; |
| 129 if (pBitmap->HasAlpha()) { |
| 130 bitmapInfo |= kCGImageAlphaPremultipliedFirst; |
| 131 } else { |
| 132 bitmapInfo |= kCGImageAlphaNoneSkipFirst; |
| 133 } |
| 134 CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); |
| 135 CGContextRef context = CGBitmapContextCreate( |
| 136 pBitmap->GetBuffer(), pBitmap->GetWidth(), pBitmap->GetHeight(), 8, |
| 137 pBitmap->GetPitch(), colorSpace, bitmapInfo); |
| 138 CGColorSpaceRelease(colorSpace); |
| 139 return context; |
| 140 } |
| 141 CFX_QuartzDeviceDriver::CFX_QuartzDeviceDriver(CGContextRef context, |
| 142 int32_t deviceClass) { |
| 143 m_saveCount = 0; |
| 144 _context = context; |
| 145 _deviceClass = deviceClass; |
| 146 CGContextRetain(_context); |
| 147 CGRect r = CGContextGetClipBoundingBox(context); |
| 148 _width = FXSYS_round(r.size.width); |
| 149 _height = FXSYS_round(r.size.height); |
| 150 _renderCaps = FXRC_SOFT_CLIP | FXRC_BLEND_MODE | FXRC_ALPHA_PATH | |
| 151 FXRC_ALPHA_IMAGE | FXRC_BIT_MASK | FXRC_ALPHA_MASK; |
| 152 if (_deviceClass != FXDC_DISPLAY) { |
| 153 } else { |
| 154 CGImageRef image = CGBitmapContextCreateImage(_context); |
| 155 if (image) { |
| 156 _renderCaps |= FXRC_GET_BITS; |
| 157 _width = CGImageGetWidth(image); |
| 158 _height = CGImageGetHeight(image); |
| 159 CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(image); |
| 160 if (kCGImageAlphaPremultipliedFirst == alphaInfo || |
| 161 kCGImageAlphaPremultipliedLast == alphaInfo || |
| 162 kCGImageAlphaOnly == alphaInfo) { |
| 163 _renderCaps |= FXRC_ALPHA_OUTPUT; |
| 164 } |
| 165 } |
| 166 CGImageRelease(image); |
| 167 } |
| 168 CGAffineTransform ctm = CGContextGetCTM(_context); |
| 169 CGContextSaveGState(_context); |
| 170 m_saveCount++; |
| 171 if (ctm.d >= 0) { |
| 172 CGFloat offset_x, offset_y; |
| 173 offset_x = ctm.tx; |
| 174 offset_y = ctm.ty; |
| 175 CGContextTranslateCTM(_context, -offset_x, -offset_y); |
| 176 CGContextConcatCTM(_context, CGAffineTransformMake(1, 0, 0, -1, offset_x, |
| 177 _height + offset_y)); |
| 178 } |
| 179 _foxitDevice2User = CGAffineTransformIdentity; |
| 180 _user2FoxitDevice = CGAffineTransformInvert(_foxitDevice2User); |
| 181 } |
| 182 CFX_QuartzDeviceDriver::~CFX_QuartzDeviceDriver() { |
| 183 CGContextRestoreGState(_context); |
| 184 m_saveCount--; |
| 185 for (int i = 0; i < m_saveCount; ++i) { |
| 186 CGContextRestoreGState(_context); |
| 187 } |
| 188 if (_context) { |
| 189 CGContextRelease(_context); |
| 190 } |
| 191 } |
| 192 int CFX_QuartzDeviceDriver::GetDeviceCaps(int capsID) { |
| 193 switch (capsID) { |
| 194 case FXDC_DEVICE_CLASS: { |
| 195 return _deviceClass; |
| 196 } |
| 197 case FXDC_PIXEL_WIDTH: { |
| 198 return _width; |
| 199 } |
| 200 case FXDC_PIXEL_HEIGHT: { |
| 201 return _height; |
| 202 } |
| 203 case FXDC_BITS_PIXEL: { |
| 204 return 32; |
| 205 } |
| 206 case FXDC_RENDER_CAPS: { |
| 207 return _renderCaps; |
| 208 } |
| 209 default: { return 0; } |
| 210 } |
| 211 } |
| 212 CFX_Matrix CFX_QuartzDeviceDriver::GetCTM() const { |
| 213 CGAffineTransform ctm = CGContextGetCTM(_context); |
| 214 return CFX_Matrix(ctm.a, ctm.b, ctm.c, ctm.d, ctm.tx, ctm.ty); |
| 215 } |
| 216 void CFX_QuartzDeviceDriver::SaveState() { |
| 217 CGContextSaveGState(_context); |
| 218 m_saveCount++; |
| 219 } |
| 220 void CFX_QuartzDeviceDriver::RestoreState(FX_BOOL isKeepSaved) { |
| 221 CGContextRestoreGState(_context); |
| 222 if (isKeepSaved) { |
| 223 CGContextSaveGState(_context); |
| 224 } else { |
| 225 m_saveCount--; |
| 226 } |
| 227 } |
| 228 FX_BOOL CFX_QuartzDeviceDriver::SetClip_PathFill(const CFX_PathData* pathData, |
| 229 const CFX_AffineMatrix* matrix, |
| 230 int fillMode) { |
| 231 SaveState(); |
| 232 CGAffineTransform m = CGAffineTransformIdentity; |
| 233 if (matrix) { |
| 234 m = CGAffineTransformMake(matrix->GetA(), matrix->GetB(), matrix->GetC(), |
| 235 matrix->GetD(), matrix->GetE(), matrix->GetF()); |
| 236 } |
| 237 m = CGAffineTransformConcat(m, _foxitDevice2User); |
| 238 CGContextConcatCTM(_context, m); |
| 239 setPathToContext(pathData); |
| 240 RestoreState(FALSE); |
| 241 if ((fillMode & 3) == FXFILL_WINDING) { |
| 242 CGContextClip(_context); |
| 243 } else { |
| 244 CGContextEOClip(_context); |
| 245 } |
| 246 return TRUE; |
| 247 } |
| 248 FX_FLOAT CFX_QuartzDeviceDriver::getLineWidth( |
| 249 const CFX_GraphStateData* graphState, |
| 250 CGAffineTransform ctm) { |
| 251 FX_FLOAT lineWidth = graphState->m_LineWidth; |
| 252 if (graphState->m_LineWidth <= 0.f) { |
| 253 CGSize size; |
| 254 size.width = 1; |
| 255 size.height = 1; |
| 256 CGSize temp = CGSizeApplyAffineTransform(size, ctm); |
| 257 CGFloat x = 1 / temp.width; |
| 258 CGFloat y = 1 / temp.height; |
| 259 lineWidth = x > y ? x : y; |
| 260 } |
| 261 return lineWidth; |
| 262 } |
| 263 FX_BOOL CFX_QuartzDeviceDriver::SetClip_PathStroke( |
| 264 const CFX_PathData* pathData, |
| 265 const CFX_AffineMatrix* matrix, |
| 266 const CFX_GraphStateData* graphState) { |
| 267 SaveState(); |
| 268 CGAffineTransform m = CGAffineTransformIdentity; |
| 269 if (matrix) { |
| 270 m = CGAffineTransformMake(matrix->GetA(), matrix->GetB(), matrix->GetC(), |
| 271 matrix->GetD(), matrix->GetE(), matrix->GetF()); |
| 272 } |
| 273 m = CGAffineTransformConcat(m, _foxitDevice2User); |
| 274 CGContextConcatCTM(_context, m); |
| 275 FX_FLOAT lineWidth = getLineWidth(graphState, m); |
| 276 setStrokeInfo(graphState, 0xFF000000, lineWidth); |
| 277 setPathToContext(pathData); |
| 278 CGContextReplacePathWithStrokedPath(_context); |
| 279 RestoreState(FALSE); |
| 280 CGContextClip(_context); |
| 281 return TRUE; |
| 282 } |
| 283 static CGBlendMode GetCGBlendMode(int blend_type) { |
| 284 CGBlendMode mode = kCGBlendModeNormal; |
| 285 switch (blend_type) { |
| 286 case FXDIB_BLEND_NORMAL: |
| 287 mode = kCGBlendModeNormal; |
| 288 break; |
| 289 case FXDIB_BLEND_MULTIPLY: |
| 290 mode = kCGBlendModeMultiply; |
| 291 break; |
| 292 case FXDIB_BLEND_SCREEN: |
| 293 mode = kCGBlendModeScreen; |
| 294 break; |
| 295 case FXDIB_BLEND_OVERLAY: |
| 296 mode = kCGBlendModeOverlay; |
| 297 break; |
| 298 case FXDIB_BLEND_DARKEN: |
| 299 mode = kCGBlendModeDarken; |
| 300 break; |
| 301 case FXDIB_BLEND_LIGHTEN: |
| 302 mode = kCGBlendModeLighten; |
| 303 break; |
| 304 case FXDIB_BLEND_COLORDODGE: |
| 305 mode = kCGBlendModeColorDodge; |
| 306 break; |
| 307 case FXDIB_BLEND_COLORBURN: |
| 308 mode = kCGBlendModeColorBurn; |
| 309 break; |
| 310 case FXDIB_BLEND_HARDLIGHT: |
| 311 mode = kCGBlendModeHardLight; |
| 312 break; |
| 313 case FXDIB_BLEND_SOFTLIGHT: |
| 314 mode = kCGBlendModeSoftLight; |
| 315 break; |
| 316 case FXDIB_BLEND_DIFFERENCE: |
| 317 mode = kCGBlendModeDifference; |
| 318 break; |
| 319 case FXDIB_BLEND_EXCLUSION: |
| 320 mode = kCGBlendModeExclusion; |
| 321 break; |
| 322 case FXDIB_BLEND_HUE: |
| 323 mode = kCGBlendModeHue; |
| 324 break; |
| 325 case FXDIB_BLEND_SATURATION: |
| 326 mode = kCGBlendModeSaturation; |
| 327 break; |
| 328 case FXDIB_BLEND_COLOR: |
| 329 mode = kCGBlendModeColor; |
| 330 break; |
| 331 case FXDIB_BLEND_LUMINOSITY: |
| 332 mode = kCGBlendModeLuminosity; |
| 333 break; |
| 334 default: |
| 335 mode = kCGBlendModeNormal; |
| 336 break; |
| 337 } |
| 338 return mode; |
| 339 } |
| 340 FX_BOOL CFX_QuartzDeviceDriver::DrawPath(const CFX_PathData* pathData, |
| 341 const CFX_AffineMatrix* matrix, |
| 342 const CFX_GraphStateData* graphState, |
| 343 FX_DWORD fillArgb, |
| 344 FX_DWORD strokeArgb, |
| 345 int fillMode, |
| 346 int alpha_flag, |
| 347 void* pIccTransform, |
| 348 int blend_type) { |
| 349 SaveState(); |
| 350 CGBlendMode mode = GetCGBlendMode(blend_type); |
| 351 if (mode != kCGBlendModeNormal) { |
| 352 CGContextSetBlendMode(_context, mode); |
| 353 } |
| 354 CGAffineTransform m = CGAffineTransformIdentity; |
| 355 if (matrix) { |
| 356 m = CGAffineTransformMake(matrix->GetA(), matrix->GetB(), matrix->GetC(), |
| 357 matrix->GetD(), matrix->GetE(), matrix->GetF()); |
| 358 } |
| 359 m = CGAffineTransformConcat(m, _foxitDevice2User); |
| 360 CGContextConcatCTM(_context, m); |
| 361 int pathMode = 0; |
| 362 if (graphState && strokeArgb) { |
| 363 CGContextSetMiterLimit(_context, graphState->m_MiterLimit); |
| 364 FX_FLOAT lineWidth = getLineWidth(graphState, m); |
| 365 setStrokeInfo(graphState, strokeArgb, lineWidth); |
| 366 pathMode |= 4; |
| 367 } |
| 368 if (fillMode && fillArgb) { |
| 369 setFillInfo(fillArgb); |
| 370 if ((fillMode & 3) == FXFILL_WINDING) { |
| 371 pathMode |= 1; |
| 372 } else if ((fillMode & 3) == FXFILL_ALTERNATE) { |
| 373 pathMode |= 2; |
| 374 } |
| 375 } |
| 376 setPathToContext(pathData); |
| 377 if (fillMode & FXFILL_FULLCOVER) { |
| 378 CGContextSetShouldAntialias(_context, false); |
| 379 } |
| 380 if (pathMode == 4) { |
| 381 CGContextStrokePath(_context); |
| 382 } else if (pathMode == 1) { |
| 383 CGContextFillPath(_context); |
| 384 } else if (pathMode == 2) { |
| 385 CGContextEOFillPath(_context); |
| 386 } else if (pathMode == 5) { |
| 387 CGContextDrawPath(_context, kCGPathFillStroke); |
| 388 } else if (pathMode == 6) { |
| 389 CGContextDrawPath(_context, kCGPathEOFillStroke); |
| 390 } |
| 391 RestoreState(FALSE); |
| 392 return TRUE; |
| 393 } |
| 394 FX_BOOL CFX_QuartzDeviceDriver::FillRect(const FX_RECT* rect, |
| 395 FX_ARGB fillArgb, |
| 396 int alphaFlag, |
| 397 void* iccTransform, |
| 398 int blend_type) { |
| 399 CGBlendMode mode = GetCGBlendMode(blend_type); |
| 400 if (mode != kCGBlendModeNormal) { |
| 401 CGContextSetBlendMode(_context, mode); |
| 402 } |
| 403 CGRect rect_fx = |
| 404 CGRectMake(rect->left, rect->top, rect->Width(), rect->Height()); |
| 405 CGRect rect_usr = CGRectApplyAffineTransform(rect_fx, _foxitDevice2User); |
| 406 int32_t a, r, g, b; |
| 407 ArgbDecode(fillArgb, a, r, g, b); |
| 408 CGContextSetRGBFillColor(_context, r / 255.f, g / 255.f, b / 255.f, |
| 409 a / 255.f); |
| 410 CGContextFillRect(_context, rect_usr); |
| 411 if (mode != kCGBlendModeNormal) { |
| 412 CGContextSetBlendMode(_context, kCGBlendModeNormal); |
| 413 } |
| 414 return TRUE; |
| 415 } |
| 416 FX_BOOL CFX_QuartzDeviceDriver::DrawCosmeticLine(FX_FLOAT x1, |
| 417 FX_FLOAT y1, |
| 418 FX_FLOAT x2, |
| 419 FX_FLOAT y2, |
| 420 FX_DWORD argb, |
| 421 int alphaFlag, |
| 422 void* iccTransform, |
| 423 int blend_type) { |
| 424 CGBlendMode mode = GetCGBlendMode(blend_type); |
| 425 if (mode != kCGBlendModeNormal) { |
| 426 CGContextSetBlendMode(_context, mode); |
| 427 } |
| 428 CGPoint pt = |
| 429 CGPointApplyAffineTransform(CGPointMake(x1, y1), _foxitDevice2User); |
| 430 x1 = pt.x; |
| 431 y1 = pt.y; |
| 432 pt = CGPointApplyAffineTransform(CGPointMake(x2, y2), _foxitDevice2User); |
| 433 x2 = pt.x; |
| 434 y2 = pt.y; |
| 435 int32_t a, r, g, b; |
| 436 ArgbDecode(argb, a, r, g, b); |
| 437 CGContextSetRGBStrokeColor(_context, r / 255.f, g / 255.f, b / 255.f, |
111 a / 255.f); | 438 a / 255.f); |
112 CGContextSaveGState(context); | 439 CGContextMoveToPoint(_context, x1, y1); |
113 #if CGFLOAT_IS_DOUBLE | 440 CGContextAddLineToPoint(_context, x2, y2); |
114 CGPoint* glyphPositionsCG = new CGPoint[charsCount]; | 441 CGContextStrokePath(_context); |
115 if (!glyphPositionsCG) { | 442 if (mode != kCGBlendModeNormal) { |
116 return FALSE; | 443 CGContextSetBlendMode(_context, kCGBlendModeNormal); |
117 } | 444 } |
118 for (int index = 0; index < charsCount; ++index) { | 445 return TRUE; |
119 glyphPositionsCG[index].x = glyphPositions[index].x; | 446 } |
120 glyphPositionsCG[index].y = glyphPositions[index].y; | 447 FX_BOOL CFX_QuartzDeviceDriver::GetClipBox(FX_RECT* rect) { |
121 } | 448 CGRect r = CGContextGetClipBoundingBox(_context); |
122 #else | 449 r = CGRectApplyAffineTransform(r, _user2FoxitDevice); |
123 CGPoint* glyphPositionsCG = (CGPoint*)glyphPositions; | 450 rect->left = FXSYS_floor(r.origin.x); |
124 #endif | 451 rect->top = FXSYS_floor(r.origin.y); |
125 CGContextShowGlyphsAtPositions(context, | 452 rect->right = FXSYS_ceil(r.origin.x + r.size.width); |
126 (CGGlyph *) glyphIndices, | 453 rect->bottom = FXSYS_ceil(r.origin.y + r.size.height); |
127 glyphPositionsCG, | 454 return TRUE; |
128 charsCount); | 455 } |
129 #if CGFLOAT_IS_DOUBLE | 456 FX_BOOL CFX_QuartzDeviceDriver::GetDIBits(CFX_DIBitmap* bitmap, |
130 delete[] glyphPositionsCG; | 457 int32_t left, |
131 #endif | 458 int32_t top, |
132 CGContextRestoreGState(context); | 459 void* pIccTransform, |
133 return TRUE; | 460 FX_BOOL bDEdge) { |
134 } | 461 if (FXDC_PRINTER == _deviceClass) { |
135 void CQuartz2D::saveGraphicsState(void * graphics) | 462 return FALSE; |
136 { | 463 } |
137 if (graphics) { | 464 if (bitmap->GetBPP() < 32) { |
138 CGContextSaveGState((CGContextRef) graphics); | 465 return FALSE; |
139 } | 466 } |
140 } | 467 if (!(_renderCaps | FXRC_GET_BITS)) { |
141 void CQuartz2D::restoreGraphicsState(void * graphics) | 468 return FALSE; |
142 { | 469 } |
143 if (graphics) { | 470 CGPoint pt = CGPointMake(left, top); |
144 CGContextRestoreGState((CGContextRef) graphics); | 471 pt = CGPointApplyAffineTransform(pt, _foxitDevice2User); |
145 } | 472 CGAffineTransform ctm = CGContextGetCTM(_context); |
146 } | 473 pt.x *= FXSYS_fabs(ctm.a); |
147 static CGContextRef createContextWithBitmap(CFX_DIBitmap* pBitmap) | 474 pt.y *= FXSYS_fabs(ctm.d); |
148 { | 475 CGImageRef image = CGBitmapContextCreateImage(_context); |
149 if (!pBitmap || pBitmap->IsCmykImage() || pBitmap->GetBPP() < 32) { | 476 if (NULL == image) { |
150 return NULL; | 477 return FALSE; |
151 } | 478 } |
152 CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Little; | 479 CGFloat width = (CGFloat)bitmap->GetWidth(); |
153 if (pBitmap->HasAlpha()) { | 480 CGFloat height = (CGFloat)bitmap->GetHeight(); |
154 bitmapInfo |= kCGImageAlphaPremultipliedFirst; | 481 if (width + pt.x > _width) { |
| 482 width -= (width + pt.x - _width); |
| 483 } |
| 484 if (height + pt.y > _height) { |
| 485 height -= (height + pt.y - _height); |
| 486 } |
| 487 CGImageRef subImage = CGImageCreateWithImageInRect( |
| 488 image, CGRectMake(pt.x, pt.y, width, height)); |
| 489 CGContextRef context = createContextWithBitmap(bitmap); |
| 490 CGRect rect = CGContextGetClipBoundingBox(context); |
| 491 CGContextClearRect(context, rect); |
| 492 CGContextDrawImage(context, rect, subImage); |
| 493 CGContextRelease(context); |
| 494 CGImageRelease(subImage); |
| 495 CGImageRelease(image); |
| 496 if (bitmap->HasAlpha()) { |
| 497 for (int row = 0; row < bitmap->GetHeight(); row++) { |
| 498 uint8_t* pScanline = (uint8_t*)bitmap->GetScanline(row); |
| 499 for (int col = 0; col < bitmap->GetWidth(); col++) { |
| 500 if (pScanline[3] > 0) { |
| 501 pScanline[0] = (pScanline[0] * 255.f / pScanline[3] + .5f); |
| 502 pScanline[1] = (pScanline[1] * 255.f / pScanline[3] + .5f); |
| 503 pScanline[2] = (pScanline[2] * 255.f / pScanline[3] + .5f); |
| 504 } |
| 505 pScanline += 4; |
| 506 } |
| 507 } |
| 508 } |
| 509 return TRUE; |
| 510 } |
| 511 FX_BOOL CFX_QuartzDeviceDriver::SetDIBits(const CFX_DIBSource* pBitmap, |
| 512 FX_ARGB argb, |
| 513 const FX_RECT* srcRect, |
| 514 int dest_left, |
| 515 int dest_top, |
| 516 int blendType, |
| 517 int alphaFlag, |
| 518 void* iccTransform) { |
| 519 SaveState(); |
| 520 CGFloat src_left, src_top, src_width, src_height; |
| 521 if (srcRect) { |
| 522 src_left = srcRect->left; |
| 523 src_top = srcRect->top; |
| 524 src_width = srcRect->Width(); |
| 525 src_height = srcRect->Height(); |
| 526 } else { |
| 527 src_left = src_top = 0; |
| 528 src_width = pBitmap->GetWidth(); |
| 529 src_height = pBitmap->GetHeight(); |
| 530 } |
| 531 CGAffineTransform ctm = CGContextGetCTM(_context); |
| 532 CGFloat scale_x = FXSYS_fabs(ctm.a); |
| 533 CGFloat scale_y = FXSYS_fabs(ctm.d); |
| 534 src_left /= scale_x; |
| 535 src_top /= scale_y; |
| 536 src_width /= scale_x; |
| 537 src_height /= scale_y; |
| 538 CGRect rect_fx = CGRectMake(dest_left, dest_top, src_width, src_height); |
| 539 CGRect rect_usr = CGRectApplyAffineTransform(rect_fx, _foxitDevice2User); |
| 540 CGContextBeginPath(_context); |
| 541 CGContextAddRect(_context, rect_usr); |
| 542 CGContextClip(_context); |
| 543 rect_usr.size = |
| 544 CGSizeMake(pBitmap->GetWidth() / scale_x, pBitmap->GetHeight() / scale_y); |
| 545 rect_usr = CGRectOffset(rect_usr, -src_left, -src_top); |
| 546 CG_SetImageTransform(dest_left, dest_top, src_width, src_height, &rect_usr); |
| 547 CFX_DIBitmap* pBitmap1 = NULL; |
| 548 if (pBitmap->IsAlphaMask()) { |
| 549 if (pBitmap->GetBuffer()) { |
| 550 pBitmap1 = (CFX_DIBitmap*)pBitmap; |
155 } else { | 551 } else { |
156 bitmapInfo |= kCGImageAlphaNoneSkipFirst; | 552 pBitmap1 = pBitmap->Clone(); |
157 } | 553 } |
158 CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); | 554 if (NULL == pBitmap1) { |
159 CGContextRef context = CGBitmapContextCreate(pBitmap->GetBuffer(), | 555 RestoreState(FALSE); |
160 pBitmap->GetWidth(), | 556 return FALSE; |
161 pBitmap->GetHeight(), | 557 } |
162 8, | 558 CGDataProviderRef pBitmapProvider = CGDataProviderCreateWithData( |
163 pBitmap->GetPitch(), | 559 NULL, pBitmap1->GetBuffer(), |
164 colorSpace, | 560 pBitmap1->GetPitch() * pBitmap1->GetHeight(), NULL); |
165 bitmapInfo); | 561 CGColorSpaceRef pColorSpace = CGColorSpaceCreateDeviceGray(); |
166 CGColorSpaceRelease(colorSpace); | 562 CGBitmapInfo bitmapInfo = kCGImageAlphaNone | kCGBitmapByteOrderDefault; |
167 return context; | 563 CGImageRef pImage = CGImageCreate( |
168 } | 564 pBitmap1->GetWidth(), pBitmap1->GetHeight(), pBitmap1->GetBPP(), |
169 CFX_QuartzDeviceDriver::CFX_QuartzDeviceDriver(CGContextRef context, int32_t dev
iceClass) | 565 pBitmap1->GetBPP(), pBitmap1->GetPitch(), pColorSpace, bitmapInfo, |
170 { | 566 pBitmapProvider, NULL, true, kCGRenderingIntentDefault); |
171 m_saveCount = 0; | 567 CGContextClipToMask(_context, rect_usr, pImage); |
172 _context = context; | 568 CGContextSetRGBFillColor(_context, FXARGB_R(argb) / 255.f, |
173 _deviceClass = deviceClass; | 569 FXARGB_G(argb) / 255.f, FXARGB_B(argb) / 255.f, |
174 CGContextRetain(_context); | 570 FXARGB_A(argb) / 255.f); |
175 CGRect r = CGContextGetClipBoundingBox(context); | 571 CGContextFillRect(_context, rect_usr); |
176 _width = FXSYS_round(r.size.width); | 572 CGImageRelease(pImage); |
177 _height = FXSYS_round(r.size.height); | 573 CGColorSpaceRelease(pColorSpace); |
178 _renderCaps = FXRC_SOFT_CLIP | FXRC_BLEND_MODE | | 574 CGDataProviderRelease(pBitmapProvider); |
179 FXRC_ALPHA_PATH | FXRC_ALPHA_IMAGE | | 575 if (pBitmap1 != pBitmap) { |
180 FXRC_BIT_MASK | FXRC_ALPHA_MASK; | 576 delete pBitmap1; |
181 if (_deviceClass != FXDC_DISPLAY) { | |
182 } else { | |
183 CGImageRef image = CGBitmapContextCreateImage(_context); | |
184 if (image) { | |
185 _renderCaps |= FXRC_GET_BITS; | |
186 _width = CGImageGetWidth(image); | |
187 _height = CGImageGetHeight(image); | |
188 CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(image); | |
189 if (kCGImageAlphaPremultipliedFirst == alphaInfo || | |
190 kCGImageAlphaPremultipliedLast == alphaInfo || | |
191 kCGImageAlphaOnly == alphaInfo) { | |
192 _renderCaps |= FXRC_ALPHA_OUTPUT; | |
193 } | |
194 } | |
195 CGImageRelease(image); | |
196 } | |
197 CGAffineTransform ctm = CGContextGetCTM(_context); | |
198 CGContextSaveGState(_context); | |
199 m_saveCount++; | |
200 if (ctm.d >= 0) { | |
201 CGFloat offset_x, offset_y; | |
202 offset_x = ctm.tx; | |
203 offset_y = ctm.ty; | |
204 CGContextTranslateCTM(_context, -offset_x, -offset_y); | |
205 CGContextConcatCTM(_context, CGAffineTransformMake(1, 0, 0, -1, offset_x
, _height + offset_y)); | |
206 } | |
207 _foxitDevice2User = CGAffineTransformIdentity; | |
208 _user2FoxitDevice = CGAffineTransformInvert(_foxitDevice2User); | |
209 } | |
210 CFX_QuartzDeviceDriver::~CFX_QuartzDeviceDriver() | |
211 { | |
212 CGContextRestoreGState(_context); | |
213 m_saveCount--; | |
214 for (int i = 0; i < m_saveCount; ++i) { | |
215 CGContextRestoreGState(_context); | |
216 } | |
217 if (_context) { | |
218 CGContextRelease(_context); | |
219 } | |
220 } | |
221 int CFX_QuartzDeviceDriver::GetDeviceCaps(int capsID) | |
222 { | |
223 switch (capsID) { | |
224 case FXDC_DEVICE_CLASS: { | |
225 return _deviceClass; | |
226 } | |
227 case FXDC_PIXEL_WIDTH: { | |
228 return _width; | |
229 } | |
230 case FXDC_PIXEL_HEIGHT: { | |
231 return _height; | |
232 } | |
233 case FXDC_BITS_PIXEL: { | |
234 return 32; | |
235 } | |
236 case FXDC_RENDER_CAPS: { | |
237 return _renderCaps; | |
238 } | |
239 default: { | |
240 return 0; | |
241 } | |
242 } | |
243 } | |
244 CFX_Matrix CFX_QuartzDeviceDriver::GetCTM() const | |
245 { | |
246 CGAffineTransform ctm = CGContextGetCTM(_context); | |
247 return CFX_Matrix(ctm.a, ctm.b, ctm.c, ctm.d, ctm.tx, ctm.ty); | |
248 } | |
249 void CFX_QuartzDeviceDriver::SaveState() | |
250 { | |
251 CGContextSaveGState(_context); | |
252 m_saveCount++; | |
253 } | |
254 void CFX_QuartzDeviceDriver::RestoreState(FX_BOOL isKeepSaved ) | |
255 { | |
256 CGContextRestoreGState(_context); | |
257 if (isKeepSaved) { | |
258 CGContextSaveGState(_context); | |
259 } else { | |
260 m_saveCount--; | |
261 } | |
262 } | |
263 FX_BOOL CFX_QuartzDeviceDriver::SetClip_PathFill(const CFX_PathData* pathData
, | |
264 const CFX_AffineMatrix* matrix, | |
265 int fillMode ) | |
266 { | |
267 SaveState(); | |
268 CGAffineTransform m = CGAffineTransformIdentity; | |
269 if (matrix) { | |
270 m = CGAffineTransformMake(matrix->GetA(), matrix->GetB(), matrix->GetC()
, matrix->GetD(), matrix->GetE(), matrix->GetF()); | |
271 } | |
272 m = CGAffineTransformConcat(m, _foxitDevice2User); | |
273 CGContextConcatCTM(_context, m); | |
274 setPathToContext(pathData); | |
275 RestoreState(FALSE); | |
276 if ((fillMode & 3) == FXFILL_WINDING) { | |
277 CGContextClip(_context); | |
278 } else { | |
279 CGContextEOClip(_context); | |
280 } | |
281 return TRUE; | |
282 } | |
283 FX_FLOAT CFX_QuartzDeviceDriver::getLineWidth(const CFX_GraphStateData * graphSt
ate, CGAffineTransform ctm) | |
284 { | |
285 FX_FLOAT lineWidth = graphState->m_LineWidth; | |
286 if (graphState->m_LineWidth <= 0.f) { | |
287 CGSize size; | |
288 size.width = 1; | |
289 size.height = 1; | |
290 CGSize temp = CGSizeApplyAffineTransform(size, ctm); | |
291 CGFloat x = 1 / temp.width; | |
292 CGFloat y = 1 / temp.height; | |
293 lineWidth = x > y ? x : y; | |
294 } | |
295 return lineWidth; | |
296 } | |
297 FX_BOOL CFX_QuartzDeviceDriver::SetClip_PathStroke(const CFX_PathData* path
Data, | |
298 const CFX_AffineMatrix* matrix, | |
299 const CFX_GraphStateData* graphState ) | |
300 { | |
301 SaveState(); | |
302 CGAffineTransform m = CGAffineTransformIdentity; | |
303 if (matrix) { | |
304 m = CGAffineTransformMake(matrix->GetA(), matrix->GetB(), matrix->GetC()
, matrix->GetD(), matrix->GetE(), matrix->GetF()); | |
305 } | |
306 m = CGAffineTransformConcat(m, _foxitDevice2User); | |
307 CGContextConcatCTM(_context, m); | |
308 FX_FLOAT lineWidth = getLineWidth(graphState, m); | |
309 setStrokeInfo(graphState, 0xFF000000, lineWidth); | |
310 setPathToContext(pathData); | |
311 CGContextReplacePathWithStrokedPath(_context); | |
312 RestoreState(FALSE); | |
313 CGContextClip(_context); | |
314 return TRUE; | |
315 } | |
316 static CGBlendMode GetCGBlendMode(int blend_type) | |
317 { | |
318 CGBlendMode mode = kCGBlendModeNormal; | |
319 switch (blend_type) { | |
320 case FXDIB_BLEND_NORMAL: | |
321 mode = kCGBlendModeNormal; | |
322 break; | |
323 case FXDIB_BLEND_MULTIPLY: | |
324 mode = kCGBlendModeMultiply; | |
325 break; | |
326 case FXDIB_BLEND_SCREEN: | |
327 mode = kCGBlendModeScreen; | |
328 break; | |
329 case FXDIB_BLEND_OVERLAY: | |
330 mode = kCGBlendModeOverlay; | |
331 break; | |
332 case FXDIB_BLEND_DARKEN: | |
333 mode = kCGBlendModeDarken; | |
334 break; | |
335 case FXDIB_BLEND_LIGHTEN: | |
336 mode = kCGBlendModeLighten; | |
337 break; | |
338 case FXDIB_BLEND_COLORDODGE: | |
339 mode = kCGBlendModeColorDodge; | |
340 break; | |
341 case FXDIB_BLEND_COLORBURN: | |
342 mode = kCGBlendModeColorBurn; | |
343 break; | |
344 case FXDIB_BLEND_HARDLIGHT: | |
345 mode = kCGBlendModeHardLight; | |
346 break; | |
347 case FXDIB_BLEND_SOFTLIGHT: | |
348 mode = kCGBlendModeSoftLight; | |
349 break; | |
350 case FXDIB_BLEND_DIFFERENCE: | |
351 mode = kCGBlendModeDifference; | |
352 break; | |
353 case FXDIB_BLEND_EXCLUSION: | |
354 mode = kCGBlendModeExclusion; | |
355 break; | |
356 case FXDIB_BLEND_HUE: | |
357 mode = kCGBlendModeHue; | |
358 break; | |
359 case FXDIB_BLEND_SATURATION: | |
360 mode = kCGBlendModeSaturation; | |
361 break; | |
362 case FXDIB_BLEND_COLOR: | |
363 mode = kCGBlendModeColor; | |
364 break; | |
365 case FXDIB_BLEND_LUMINOSITY: | |
366 mode = kCGBlendModeLuminosity; | |
367 break; | |
368 default: | |
369 mode = kCGBlendModeNormal; | |
370 break; | |
371 } | |
372 return mode; | |
373 } | |
374 FX_BOOL CFX_QuartzDeviceDriver::DrawPath(const CFX_PathData* pathData, | |
375 const CFX_AffineMatrix* matrix, | |
376 const CFX_GraphStateData* graphState, | |
377 FX_DWORD fillArgb, | |
378 FX_DWORD strokeArgb, | |
379 int fillMode, | |
380 int alpha_flag, | |
381 void* pIccTransform, | |
382 int blend_type | |
383 ) | |
384 { | |
385 SaveState(); | |
386 CGBlendMode mode = GetCGBlendMode(blend_type); | |
387 if (mode != kCGBlendModeNormal) { | |
388 CGContextSetBlendMode(_context, mode); | |
389 } | |
390 CGAffineTransform m = CGAffineTransformIdentity; | |
391 if (matrix) { | |
392 m = CGAffineTransformMake(matrix->GetA(), matrix->GetB(), matrix->GetC()
, matrix->GetD(), matrix->GetE(), matrix->GetF()); | |
393 } | |
394 m = CGAffineTransformConcat(m, _foxitDevice2User); | |
395 CGContextConcatCTM(_context, m); | |
396 int pathMode = 0; | |
397 if (graphState && strokeArgb) { | |
398 CGContextSetMiterLimit(_context, graphState->m_MiterLimit); | |
399 FX_FLOAT lineWidth = getLineWidth(graphState, m); | |
400 setStrokeInfo(graphState, strokeArgb, lineWidth); | |
401 pathMode |= 4; | |
402 } | |
403 if (fillMode && fillArgb) { | |
404 setFillInfo(fillArgb); | |
405 if ((fillMode & 3) == FXFILL_WINDING) { | |
406 pathMode |= 1; | |
407 } else if ((fillMode & 3) == FXFILL_ALTERNATE) { | |
408 pathMode |= 2; | |
409 } | |
410 } | |
411 setPathToContext(pathData); | |
412 if (fillMode & FXFILL_FULLCOVER) { | |
413 CGContextSetShouldAntialias(_context, false); | |
414 } | |
415 if (pathMode == 4) { | |
416 CGContextStrokePath(_context); | |
417 } else if (pathMode == 1) { | |
418 CGContextFillPath(_context); | |
419 } else if (pathMode == 2) { | |
420 CGContextEOFillPath(_context); | |
421 } else if (pathMode == 5) { | |
422 CGContextDrawPath(_context, kCGPathFillStroke); | |
423 } else if (pathMode == 6) { | |
424 CGContextDrawPath(_context, kCGPathEOFillStroke); | |
425 } | 577 } |
426 RestoreState(FALSE); | 578 RestoreState(FALSE); |
427 return TRUE; | 579 return TRUE; |
428 } | 580 } |
429 FX_BOOL CFX_QuartzDeviceDriver::FillRect(const FX_RECT* rect, | 581 if (pBitmap->GetBPP() < 32) { |
430 FX_ARGB fillArgb, | 582 pBitmap1 = pBitmap->CloneConvert(FXDIB_Rgb32); |
431 int alphaFlag» , | 583 } else { |
432 void* iccTransform , | 584 if (pBitmap->GetBuffer()) { |
433 int» » » » » » blend_type ) | 585 pBitmap1 = (CFX_DIBitmap*)pBitmap; |
434 { | |
435 CGBlendMode mode = GetCGBlendMode(blend_type); | |
436 if (mode != kCGBlendModeNormal) { | |
437 CGContextSetBlendMode(_context, mode); | |
438 } | |
439 CGRect rect_fx = CGRectMake(rect->left, rect->top, rect->Width(), rect->Heig
ht()); | |
440 CGRect rect_usr = CGRectApplyAffineTransform(rect_fx, _foxitDevice2User); | |
441 int32_t a, r, g, b; | |
442 ArgbDecode(fillArgb, a, r, g, b); | |
443 CGContextSetRGBFillColor(_context, | |
444 r / 255.f, | |
445 g / 255.f, | |
446 b / 255.f, | |
447 a / 255.f); | |
448 CGContextFillRect(_context, rect_usr); | |
449 if (mode != kCGBlendModeNormal) { | |
450 CGContextSetBlendMode(_context, kCGBlendModeNormal); | |
451 } | |
452 return TRUE; | |
453 } | |
454 FX_BOOL CFX_QuartzDeviceDriver::DrawCosmeticLine(FX_FLOAT x1, | |
455 FX_FLOAT y1, | |
456 FX_FLOAT x2, | |
457 FX_FLOAT y2, | |
458 FX_DWORD argb, | |
459 int alphaFlag , | |
460 void* iccTransform , | |
461 int» » » » » blend_type ) | |
462 { | |
463 CGBlendMode mode = GetCGBlendMode(blend_type); | |
464 if (mode != kCGBlendModeNormal) { | |
465 CGContextSetBlendMode(_context, mode); | |
466 } | |
467 CGPoint pt = CGPointApplyAffineTransform(CGPointMake(x1, y1), _foxitDevice2U
ser); | |
468 x1 = pt.x; | |
469 y1 = pt.y; | |
470 pt = CGPointApplyAffineTransform(CGPointMake(x2, y2), _foxitDevice2User); | |
471 x2 = pt.x; | |
472 y2 = pt.y; | |
473 int32_t a, r, g, b; | |
474 ArgbDecode(argb, a, r, g, b); | |
475 CGContextSetRGBStrokeColor(_context, | |
476 r / 255.f, | |
477 g / 255.f, | |
478 b / 255.f, | |
479 a / 255.f); | |
480 CGContextMoveToPoint(_context, x1, y1); | |
481 CGContextAddLineToPoint(_context, x2, y2); | |
482 CGContextStrokePath(_context); | |
483 if (mode != kCGBlendModeNormal) { | |
484 CGContextSetBlendMode(_context, kCGBlendModeNormal); | |
485 } | |
486 return TRUE; | |
487 } | |
488 FX_BOOL CFX_QuartzDeviceDriver::GetClipBox(FX_RECT* rect) | |
489 { | |
490 CGRect r = CGContextGetClipBoundingBox(_context); | |
491 r = CGRectApplyAffineTransform(r, _user2FoxitDevice); | |
492 rect->left» » = FXSYS_floor(r.origin.x); | |
493 rect->top» » = FXSYS_floor(r.origin.y); | |
494 rect->right»» = FXSYS_ceil(r.origin.x + r.size.width); | |
495 rect->bottom» = FXSYS_ceil(r.origin.y + r.size.height); | |
496 return TRUE; | |
497 } | |
498 FX_BOOL CFX_QuartzDeviceDriver::GetDIBits(CFX_DIBitmap* bitmap, | |
499 int32_t left, | |
500 int32_t top, | |
501 void* pIccTransform, | |
502 FX_BOOL bDEdge) | |
503 { | |
504 if (FXDC_PRINTER == _deviceClass) { | |
505 return FALSE; | |
506 } | |
507 if (bitmap->GetBPP() < 32) { | |
508 return FALSE; | |
509 } | |
510 if (!(_renderCaps | FXRC_GET_BITS)) { | |
511 return FALSE; | |
512 } | |
513 CGPoint pt = CGPointMake(left, top); | |
514 pt = CGPointApplyAffineTransform(pt, _foxitDevice2User); | |
515 CGAffineTransform ctm = CGContextGetCTM(_context); | |
516 pt.x *= FXSYS_fabs(ctm.a); | |
517 pt.y *= FXSYS_fabs(ctm.d); | |
518 CGImageRef image = CGBitmapContextCreateImage(_context); | |
519 if (NULL == image) { | |
520 return FALSE; | |
521 } | |
522 CGFloat width» = (CGFloat) bitmap->GetWidth(); | |
523 CGFloat height» = (CGFloat) bitmap->GetHeight(); | |
524 if (width + pt.x > _width) { | |
525 width -= (width + pt.x - _width); | |
526 } | |
527 if (height + pt.y > _height) { | |
528 height -= (height + pt.y - _height); | |
529 } | |
530 CGImageRef subImage = CGImageCreateWithImageInRect(image, | |
531 CGRectMake(pt.x, | |
532 pt.y, | |
533 width, | |
534 height)); | |
535 CGContextRef context = createContextWithBitmap(bitmap); | |
536 CGRect rect = CGContextGetClipBoundingBox(context); | |
537 CGContextClearRect(context, rect); | |
538 CGContextDrawImage(context, rect, subImage); | |
539 CGContextRelease(context); | |
540 CGImageRelease(subImage); | |
541 CGImageRelease(image); | |
542 if (bitmap->HasAlpha()) { | |
543 for (int row = 0; row < bitmap->GetHeight(); row ++) { | |
544 uint8_t* pScanline = (uint8_t*)bitmap->GetScanline(row); | |
545 for (int col = 0; col < bitmap->GetWidth(); col ++) { | |
546 if (pScanline[3] > 0) { | |
547 pScanline[0] = (pScanline[0] * 255.f / pScanline[3] + .5f); | |
548 pScanline[1] = (pScanline[1] * 255.f / pScanline[3] + .5f); | |
549 pScanline[2] = (pScanline[2] * 255.f / pScanline[3] + .5f); | |
550 } | |
551 pScanline += 4; | |
552 } | |
553 } | |
554 } | |
555 return TRUE; | |
556 } | |
557 FX_BOOL CFX_QuartzDeviceDriver::SetDIBits(const CFX_DIBSource* pBitmap, | |
558 FX_ARGB argb, | |
559 const FX_RECT* srcRect, | |
560 int dest_left, | |
561 int dest_top, | |
562 int blendType, | |
563 int alphaFlag , | |
564 void* iccTransform ) | |
565 { | |
566 SaveState(); | |
567 CGFloat src_left, src_top, src_width, src_height; | |
568 if (srcRect) { | |
569 src_left = srcRect->left; | |
570 src_top = srcRect->top; | |
571 src_width = srcRect->Width(); | |
572 src_height = srcRect->Height(); | |
573 } else { | 586 } else { |
574 src_left = src_top = 0; | 587 pBitmap1 = pBitmap->Clone(); |
575 src_width = pBitmap->GetWidth(); | 588 } |
576 src_height = pBitmap->GetHeight(); | 589 } |
577 } | 590 if (NULL == pBitmap1) { |
578 CGAffineTransform ctm = CGContextGetCTM(_context); | 591 RestoreState(FALSE); |
579 CGFloat scale_x = FXSYS_fabs(ctm.a); | 592 return FALSE; |
580 CGFloat scale_y = FXSYS_fabs(ctm.d); | 593 } |
581 src_left /= scale_x; | 594 if (pBitmap1->HasAlpha()) { |
582 src_top /= scale_y; | 595 if (pBitmap1 == pBitmap) { |
583 src_width /= scale_x; | 596 pBitmap1 = pBitmap->Clone(); |
584 src_height /= scale_y; | 597 if (!pBitmap1) { |
585 CGRect rect_fx = CGRectMake(dest_left, dest_top, src_width, src_height); | |
586 CGRect rect_usr = CGRectApplyAffineTransform(rect_fx, _foxitDevice2User); | |
587 CGContextBeginPath(_context); | |
588 CGContextAddRect(_context, rect_usr); | |
589 CGContextClip(_context); | |
590 rect_usr.size = CGSizeMake(pBitmap->GetWidth() / scale_x, pBitmap->GetHeight
() / scale_y); | |
591 rect_usr = CGRectOffset(rect_usr, -src_left, -src_top); | |
592 CG_SetImageTransform(dest_left, dest_top, src_width, src_height, &rect_usr); | |
593 CFX_DIBitmap* pBitmap1 = NULL; | |
594 if (pBitmap->IsAlphaMask()) { | |
595 if (pBitmap->GetBuffer()) { | |
596 pBitmap1 = (CFX_DIBitmap*)pBitmap; | |
597 } else { | |
598 pBitmap1 = pBitmap->Clone(); | |
599 } | |
600 if (NULL == pBitmap1) { | |
601 RestoreState(FALSE); | |
602 return FALSE; | |
603 } | |
604 CGDataProviderRef pBitmapProvider = CGDataProviderCreateWithData(NULL, | |
605 pBitmap1->GetBuffer(), | |
606 pBitmap1->GetPitch() * pBitmap1->Get
Height(), | |
607 NULL); | |
608 CGColorSpaceRef pColorSpace = CGColorSpaceCreateDeviceGray(); | |
609 CGBitmapInfo bitmapInfo = kCGImageAlphaNone | kCGBitmapByteOrderDefault; | |
610 CGImageRef pImage = CGImageCreate(pBitmap1->GetWidth(), | |
611 pBitmap1->GetHeight(), | |
612 pBitmap1->GetBPP(), | |
613 pBitmap1->GetBPP(), | |
614 pBitmap1->GetPitch(), | |
615 pColorSpace, | |
616 bitmapInfo, | |
617 pBitmapProvider, NULL, true, | |
618 kCGRenderingIntentDefault); | |
619 CGContextClipToMask(_context, rect_usr, pImage); | |
620 CGContextSetRGBFillColor(_context, | |
621 FXARGB_R(argb) / 255.f, | |
622 FXARGB_G(argb) / 255.f, | |
623 FXARGB_B(argb) / 255.f, | |
624 FXARGB_A(argb) / 255.f); | |
625 CGContextFillRect(_context, rect_usr); | |
626 CGImageRelease(pImage); | |
627 CGColorSpaceRelease(pColorSpace); | |
628 CGDataProviderRelease(pBitmapProvider); | |
629 if (pBitmap1 != pBitmap) { | |
630 delete pBitmap1; | |
631 } | |
632 RestoreState(FALSE); | |
633 return TRUE; | |
634 } | |
635 if (pBitmap->GetBPP() < 32) { | |
636 pBitmap1 = pBitmap->CloneConvert(FXDIB_Rgb32); | |
637 } else { | |
638 if (pBitmap->GetBuffer()) { | |
639 pBitmap1 = (CFX_DIBitmap*)pBitmap; | |
640 } else { | |
641 pBitmap1 = pBitmap->Clone(); | |
642 } | |
643 } | |
644 if (NULL == pBitmap1) { | |
645 RestoreState(FALSE); | 598 RestoreState(FALSE); |
646 return FALSE; | 599 return FALSE; |
647 } | 600 } |
648 if (pBitmap1->HasAlpha()) { | 601 } |
649 if (pBitmap1 == pBitmap) { | 602 for (int row = 0; row < pBitmap1->GetHeight(); row++) { |
650 pBitmap1 = pBitmap->Clone(); | 603 uint8_t* pScanline = (uint8_t*)pBitmap1->GetScanline(row); |
651 if (!pBitmap1) { | 604 for (int col = 0; col < pBitmap1->GetWidth(); col++) { |
652 RestoreState(FALSE); | 605 pScanline[0] = (uint8_t)(pScanline[0] * pScanline[3] / 255.f + .5f); |
653 return FALSE; | 606 pScanline[1] = (uint8_t)(pScanline[1] * pScanline[3] / 255.f + .5f); |
654 } | 607 pScanline[2] = (uint8_t)(pScanline[2] * pScanline[3] / 255.f + .5f); |
655 } | 608 pScanline += 4; |
656 for (int row = 0; row < pBitmap1->GetHeight(); row ++) { | 609 } |
657 uint8_t* pScanline = (uint8_t*)pBitmap1->GetScanline(row); | 610 } |
658 for (int col = 0; col < pBitmap1->GetWidth(); col ++) { | 611 } |
659 pScanline[0] = (uint8_t)(pScanline[0] * pScanline[3] / 255.f + .
5f); | 612 CGContextRef ctx = createContextWithBitmap(pBitmap1); |
660 pScanline[1] = (uint8_t)(pScanline[1] * pScanline[3] / 255.f + .
5f); | 613 CGImageRef image = CGBitmapContextCreateImage(ctx); |
661 pScanline[2] = (uint8_t)(pScanline[2] * pScanline[3] / 255.f + .
5f); | 614 int blend_mode = blendType; |
662 pScanline += 4; | 615 if (FXDIB_BLEND_HARDLIGHT == blendType) { |
663 } | 616 blend_mode = kCGBlendModeSoftLight; |
664 } | 617 } else if (FXDIB_BLEND_SOFTLIGHT == blendType) { |
665 } | 618 blend_mode = kCGBlendModeHardLight; |
666 CGContextRef ctx = createContextWithBitmap(pBitmap1); | 619 } else if (blendType >= FXDIB_BLEND_NONSEPARABLE && |
667 CGImageRef image = CGBitmapContextCreateImage(ctx); | 620 blendType <= FXDIB_BLEND_LUMINOSITY) { |
668 int blend_mode = blendType; | 621 blend_mode = blendType - 9; |
669 if (FXDIB_BLEND_HARDLIGHT == blendType) { | 622 } else if (blendType > FXDIB_BLEND_LUMINOSITY || blendType < 0) { |
670 blend_mode = kCGBlendModeSoftLight; | 623 blend_mode = kCGBlendModeNormal; |
671 } else if (FXDIB_BLEND_SOFTLIGHT == blendType) { | 624 } |
672 blend_mode = kCGBlendModeHardLight; | 625 CGContextSetBlendMode(_context, (CGBlendMode)blend_mode); |
673 } else if (blendType >= FXDIB_BLEND_NONSEPARABLE && blendType <= FXDIB_BLEND
_LUMINOSITY) { | 626 CGContextDrawImage(_context, rect_usr, image); |
674 blend_mode = blendType - 9; | 627 CGImageRelease(image); |
675 } else if (blendType > FXDIB_BLEND_LUMINOSITY || blendType < 0) { | 628 CGContextRelease(ctx); |
676 blend_mode = kCGBlendModeNormal; | 629 if (pBitmap1 != pBitmap) { |
677 } | 630 delete pBitmap1; |
678 CGContextSetBlendMode(_context, (CGBlendMode)blend_mode); | 631 } |
679 CGContextDrawImage(_context, rect_usr, image); | 632 RestoreState(FALSE); |
680 CGImageRelease(image); | 633 return TRUE; |
681 CGContextRelease(ctx); | 634 } |
| 635 FX_BOOL CFX_QuartzDeviceDriver::StretchDIBits(const CFX_DIBSource* pBitmap, |
| 636 FX_ARGB argb, |
| 637 int dest_left, |
| 638 int dest_top, |
| 639 int dest_width, |
| 640 int dest_height, |
| 641 const FX_RECT* clipRect, |
| 642 FX_DWORD flags, |
| 643 int alphaFlag, |
| 644 void* iccTransform, |
| 645 int blend_type) { |
| 646 SaveState(); |
| 647 if (clipRect) { |
| 648 CGContextBeginPath(_context); |
| 649 CGRect rect_clip = CGRectMake(clipRect->left, clipRect->top, |
| 650 clipRect->Width(), clipRect->Height()); |
| 651 rect_clip = CGRectApplyAffineTransform(rect_clip, _foxitDevice2User); |
| 652 CGContextAddRect(_context, rect_clip); |
| 653 CGContextClip(_context); |
| 654 } |
| 655 CGRect rect = CGRectMake(dest_left, dest_top, dest_width, dest_height); |
| 656 rect = CGRectApplyAffineTransform(rect, _foxitDevice2User); |
| 657 if (FXDIB_BICUBIC_INTERPOL == flags) { |
| 658 CGContextSetInterpolationQuality(_context, kCGInterpolationHigh); |
| 659 } else if (FXDIB_DOWNSAMPLE == flags) { |
| 660 CGContextSetInterpolationQuality(_context, kCGInterpolationNone); |
| 661 } else { |
| 662 CGContextSetInterpolationQuality(_context, kCGInterpolationMedium); |
| 663 } |
| 664 CG_SetImageTransform(dest_left, dest_top, dest_width, dest_height); |
| 665 CFX_DIBitmap* pBitmap1 = NULL; |
| 666 if (pBitmap->IsAlphaMask()) { |
| 667 if (pBitmap->GetBuffer()) { |
| 668 pBitmap1 = (CFX_DIBitmap*)pBitmap; |
| 669 } else { |
| 670 pBitmap1 = pBitmap->Clone(); |
| 671 } |
| 672 if (NULL == pBitmap1) { |
| 673 RestoreState(FALSE); |
| 674 return FALSE; |
| 675 } |
| 676 CGDataProviderRef pBitmapProvider = CGDataProviderCreateWithData( |
| 677 NULL, pBitmap1->GetBuffer(), |
| 678 pBitmap1->GetPitch() * pBitmap1->GetHeight(), NULL); |
| 679 CGColorSpaceRef pColorSpace = CGColorSpaceCreateDeviceGray(); |
| 680 CGBitmapInfo bitmapInfo = kCGImageAlphaNone | kCGBitmapByteOrderDefault; |
| 681 CGImageRef pImage = CGImageCreate( |
| 682 pBitmap1->GetWidth(), pBitmap1->GetHeight(), pBitmap1->GetBPP(), |
| 683 pBitmap1->GetBPP(), pBitmap1->GetPitch(), pColorSpace, bitmapInfo, |
| 684 pBitmapProvider, NULL, true, kCGRenderingIntentDefault); |
| 685 CGContextClipToMask(_context, rect, pImage); |
| 686 CGContextSetRGBFillColor(_context, FXARGB_R(argb) / 255.f, |
| 687 FXARGB_G(argb) / 255.f, FXARGB_B(argb) / 255.f, |
| 688 FXARGB_A(argb) / 255.f); |
| 689 CGContextFillRect(_context, rect); |
| 690 CGImageRelease(pImage); |
| 691 CGColorSpaceRelease(pColorSpace); |
| 692 CGDataProviderRelease(pBitmapProvider); |
682 if (pBitmap1 != pBitmap) { | 693 if (pBitmap1 != pBitmap) { |
683 delete pBitmap1; | 694 delete pBitmap1; |
684 } | 695 } |
685 RestoreState(FALSE); | 696 RestoreState(FALSE); |
686 return TRUE; | 697 return TRUE; |
687 } | 698 } |
688 FX_BOOL CFX_QuartzDeviceDriver::StretchDIBits(const CFX_DIBSource* pBitmap, | 699 if (pBitmap->GetBPP() < 32) { |
689 FX_ARGB argb, | 700 pBitmap1 = pBitmap->CloneConvert(FXDIB_Rgb32); |
690 int dest_left, | 701 } else { |
691 int dest_top, | 702 if (pBitmap->GetBuffer()) { |
692 int dest_width, | 703 pBitmap1 = (CFX_DIBitmap*)pBitmap; |
693 int dest_height, | |
694 const FX_RECT* clipRect, | |
695 FX_DWORD flags, | |
696 int alphaFlag» , | |
697 void* iccTransform , | |
698 int» » » » » » » blend_type) | |
699 { | |
700 SaveState(); | |
701 if (clipRect) { | |
702 CGContextBeginPath(_context); | |
703 CGRect rect_clip = CGRectMake(clipRect->left, clipRect->top, clipRect->W
idth(), clipRect->Height()); | |
704 rect_clip = CGRectApplyAffineTransform(rect_clip, _foxitDevice2User); | |
705 CGContextAddRect(_context, rect_clip); | |
706 CGContextClip(_context); | |
707 } | |
708 CGRect rect = CGRectMake(dest_left, dest_top, dest_width, dest_height); | |
709 rect = CGRectApplyAffineTransform(rect, _foxitDevice2User); | |
710 if (FXDIB_BICUBIC_INTERPOL == flags) { | |
711 CGContextSetInterpolationQuality(_context, kCGInterpolationHigh); | |
712 } else if (FXDIB_DOWNSAMPLE == flags) { | |
713 CGContextSetInterpolationQuality(_context, kCGInterpolationNone); | |
714 } else { | 704 } else { |
715 CGContextSetInterpolationQuality(_context, kCGInterpolationMedium); | 705 pBitmap1 = pBitmap->Clone(); |
716 } | 706 } |
717 CG_SetImageTransform(dest_left, dest_top, dest_width, dest_height); | 707 } |
718 CFX_DIBitmap* pBitmap1 = NULL; | 708 if (NULL == pBitmap1) { |
719 if (pBitmap->IsAlphaMask()) { | 709 RestoreState(FALSE); |
720 if (pBitmap->GetBuffer()) { | 710 return FALSE; |
721 pBitmap1 = (CFX_DIBitmap*)pBitmap; | 711 } |
722 } else { | 712 if (pBitmap1->HasAlpha()) { |
723 pBitmap1 = pBitmap->Clone(); | 713 if (pBitmap1 == pBitmap) { |
724 } | 714 pBitmap1 = pBitmap->Clone(); |
725 if (NULL == pBitmap1) { | 715 if (!pBitmap1) { |
726 RestoreState(FALSE); | |
727 return FALSE; | |
728 } | |
729 CGDataProviderRef pBitmapProvider = CGDataProviderCreateWithData(NULL, | |
730 pBitmap1->GetBuffer(), | |
731 pBitmap1->GetPitch() * pBitmap1->Get
Height(), | |
732 NULL); | |
733 CGColorSpaceRef pColorSpace = CGColorSpaceCreateDeviceGray(); | |
734 CGBitmapInfo bitmapInfo = kCGImageAlphaNone | kCGBitmapByteOrderDefault; | |
735 CGImageRef pImage = CGImageCreate(pBitmap1->GetWidth(), | |
736 pBitmap1->GetHeight(), | |
737 pBitmap1->GetBPP(), | |
738 pBitmap1->GetBPP(), | |
739 pBitmap1->GetPitch(), | |
740 pColorSpace, | |
741 bitmapInfo, | |
742 pBitmapProvider, NULL, true, | |
743 kCGRenderingIntentDefault); | |
744 CGContextClipToMask(_context, rect, pImage); | |
745 CGContextSetRGBFillColor(_context, | |
746 FXARGB_R(argb) / 255.f, | |
747 FXARGB_G(argb) / 255.f, | |
748 FXARGB_B(argb) / 255.f, | |
749 FXARGB_A(argb) / 255.f); | |
750 CGContextFillRect(_context, rect); | |
751 CGImageRelease(pImage); | |
752 CGColorSpaceRelease(pColorSpace); | |
753 CGDataProviderRelease(pBitmapProvider); | |
754 if (pBitmap1 != pBitmap) { | |
755 delete pBitmap1; | |
756 } | |
757 RestoreState(FALSE); | |
758 return TRUE; | |
759 } | |
760 if (pBitmap->GetBPP() < 32) { | |
761 pBitmap1 = pBitmap->CloneConvert(FXDIB_Rgb32); | |
762 } else { | |
763 if (pBitmap->GetBuffer()) { | |
764 pBitmap1 = (CFX_DIBitmap*)pBitmap; | |
765 } else { | |
766 pBitmap1 = pBitmap->Clone(); | |
767 } | |
768 } | |
769 if (NULL == pBitmap1) { | |
770 RestoreState(FALSE); | 716 RestoreState(FALSE); |
771 return FALSE; | 717 return FALSE; |
772 } | 718 } |
773 if (pBitmap1->HasAlpha()) { | 719 } |
774 if (pBitmap1 == pBitmap) { | 720 for (int row = 0; row < pBitmap1->GetHeight(); row++) { |
775 pBitmap1 = pBitmap->Clone(); | 721 uint8_t* pScanline = (uint8_t*)pBitmap1->GetScanline(row); |
776 if (!pBitmap1) { | 722 for (int col = 0; col < pBitmap1->GetWidth(); col++) { |
777 RestoreState(FALSE); | 723 pScanline[0] = (uint8_t)(pScanline[0] * pScanline[3] / 255.f + .5f); |
778 return FALSE; | 724 pScanline[1] = (uint8_t)(pScanline[1] * pScanline[3] / 255.f + .5f); |
779 } | 725 pScanline[2] = (uint8_t)(pScanline[2] * pScanline[3] / 255.f + .5f); |
| 726 pScanline += 4; |
| 727 } |
| 728 } |
| 729 } |
| 730 CGContextRef ctx = createContextWithBitmap(pBitmap1); |
| 731 CGImageRef image = CGBitmapContextCreateImage(ctx); |
| 732 CGContextDrawImage(_context, rect, image); |
| 733 CGImageRelease(image); |
| 734 CGContextRelease(ctx); |
| 735 if (pBitmap1 != pBitmap) { |
| 736 delete pBitmap1; |
| 737 } |
| 738 RestoreState(FALSE); |
| 739 return TRUE; |
| 740 } |
| 741 FX_BOOL CFX_QuartzDeviceDriver::CG_DrawGlypRun( |
| 742 int nChars, |
| 743 const FXTEXT_CHARPOS* pCharPos, |
| 744 CFX_Font* pFont, |
| 745 CFX_FontCache* pCache, |
| 746 const CFX_AffineMatrix* pGlyphMatrix, |
| 747 const CFX_AffineMatrix* pObject2Device, |
| 748 FX_FLOAT font_size, |
| 749 FX_DWORD argb, |
| 750 int alpha_flag, |
| 751 void* pIccTransform) { |
| 752 if (nChars == 0) { |
| 753 return TRUE; |
| 754 } |
| 755 CQuartz2D& quartz2d = |
| 756 ((CApplePlatform*)CFX_GEModule::Get()->GetPlatformData())->_quartz2d; |
| 757 if (!pFont->m_pPlatformFont) { |
| 758 if (pFont->GetPsName() == CFX_WideString::FromLocal("DFHeiStd-W5")) { |
| 759 return FALSE; |
| 760 } |
| 761 pFont->m_pPlatformFont = |
| 762 quartz2d.CreateFont(pFont->m_pFontData, pFont->m_dwSize); |
| 763 if (NULL == pFont->m_pPlatformFont) { |
| 764 return FALSE; |
| 765 } |
| 766 } |
| 767 CFX_FixedBufGrow<FX_WORD, 32> glyph_indices(nChars); |
| 768 CFX_FixedBufGrow<CGPoint, 32> glyph_positions(nChars); |
| 769 for (int i = 0; i < nChars; i++) { |
| 770 glyph_indices[i] = pCharPos[i].m_ExtGID; |
| 771 glyph_positions[i].x = pCharPos[i].m_OriginX; |
| 772 glyph_positions[i].y = pCharPos[i].m_OriginY; |
| 773 } |
| 774 CFX_AffineMatrix text_matrix; |
| 775 if (pObject2Device) { |
| 776 text_matrix.Concat(*pObject2Device); |
| 777 } |
| 778 CGAffineTransform matrix_cg = |
| 779 CGAffineTransformMake(text_matrix.a, text_matrix.b, text_matrix.c, |
| 780 text_matrix.d, text_matrix.e, text_matrix.f); |
| 781 matrix_cg = CGAffineTransformConcat(matrix_cg, _foxitDevice2User); |
| 782 CGContextSetTextMatrix(_context, matrix_cg); |
| 783 CGContextSetFont(_context, (CGFontRef)pFont->m_pPlatformFont); |
| 784 CGContextSetFontSize(_context, FXSYS_fabs(font_size)); |
| 785 int32_t a, r, g, b; |
| 786 ArgbDecode(argb, a, r, g, b); |
| 787 CGContextSetRGBFillColor(_context, r / 255.f, g / 255.f, b / 255.f, |
| 788 a / 255.f); |
| 789 SaveState(); |
| 790 if (pGlyphMatrix) { |
| 791 CGPoint origin = CGPointMake(glyph_positions[0].x, glyph_positions[0].y); |
| 792 origin = CGPointApplyAffineTransform(origin, matrix_cg); |
| 793 CGContextTranslateCTM(_context, origin.x, origin.y); |
| 794 CGAffineTransform glyph_matrix = CGAffineTransformMake( |
| 795 pGlyphMatrix->a, pGlyphMatrix->b, pGlyphMatrix->c, pGlyphMatrix->d, |
| 796 pGlyphMatrix->e, pGlyphMatrix->f); |
| 797 if (_foxitDevice2User.d < 0) { |
| 798 glyph_matrix = CGAffineTransformInvert(glyph_matrix); |
| 799 } |
| 800 CGContextConcatCTM(_context, glyph_matrix); |
| 801 CGContextTranslateCTM(_context, -origin.x, -origin.y); |
| 802 } |
| 803 CGContextShowGlyphsAtPositions(_context, (CGGlyph*)glyph_indices, |
| 804 glyph_positions, nChars); |
| 805 RestoreState(FALSE); |
| 806 return TRUE; |
| 807 } |
| 808 FX_BOOL CFX_QuartzDeviceDriver::DrawDeviceText( |
| 809 int nChars, |
| 810 const FXTEXT_CHARPOS* pCharPos, |
| 811 CFX_Font* pFont, |
| 812 CFX_FontCache* pCache, |
| 813 const CFX_AffineMatrix* pObject2Device, |
| 814 FX_FLOAT font_size, |
| 815 FX_DWORD color, |
| 816 int alpha_flag, |
| 817 void* pIccTransform) { |
| 818 if (NULL == pFont || NULL == _context) { |
| 819 return FALSE; |
| 820 } |
| 821 FX_BOOL bBold = pFont->IsBold(); |
| 822 if (!bBold && pFont->GetSubstFont() && |
| 823 pFont->GetSubstFont()->m_Weight >= 500 && |
| 824 pFont->GetSubstFont()->m_Weight <= 600) { |
| 825 return FALSE; |
| 826 } |
| 827 SaveState(); |
| 828 CGContextSetTextDrawingMode(_context, kCGTextFillClip); |
| 829 FX_BOOL ret = FALSE; |
| 830 int32_t i = 0; |
| 831 while (i < nChars) { |
| 832 if (pCharPos[i].m_bGlyphAdjust || font_size < 0) { |
| 833 if (i > 0) { |
| 834 ret = CG_DrawGlypRun(i, pCharPos, pFont, pCache, NULL, pObject2Device, |
| 835 font_size, color, alpha_flag, pIccTransform); |
| 836 if (!ret) { |
| 837 RestoreState(FALSE); |
| 838 return ret; |
780 } | 839 } |
781 for (int row = 0; row < pBitmap1->GetHeight(); row ++) { | 840 } |
782 uint8_t* pScanline = (uint8_t*)pBitmap1->GetScanline(row); | 841 const FXTEXT_CHARPOS* char_pos = pCharPos + i; |
783 for (int col = 0; col < pBitmap1->GetWidth(); col ++) { | 842 CFX_AffineMatrix glphy_matrix; |
784 pScanline[0] = (uint8_t)(pScanline[0] * pScanline[3] / 255.f + .
5f); | 843 if (font_size < 0) { |
785 pScanline[1] = (uint8_t)(pScanline[1] * pScanline[3] / 255.f + .
5f); | 844 glphy_matrix.Concat(-1, 0, 0, -1, 0, 0); |
786 pScanline[2] = (uint8_t)(pScanline[2] * pScanline[3] / 255.f + .
5f); | 845 } |
787 pScanline += 4; | 846 if (char_pos->m_bGlyphAdjust) { |
788 } | 847 glphy_matrix.Concat( |
789 } | 848 char_pos->m_AdjustMatrix[0], char_pos->m_AdjustMatrix[1], |
790 } | 849 char_pos->m_AdjustMatrix[2], char_pos->m_AdjustMatrix[3], 0, 0); |
791 CGContextRef ctx = createContextWithBitmap(pBitmap1); | 850 } |
792 CGImageRef image = CGBitmapContextCreateImage(ctx); | 851 ret = CG_DrawGlypRun(1, char_pos, pFont, pCache, &glphy_matrix, |
793 CGContextDrawImage(_context, rect, image); | 852 pObject2Device, font_size, color, alpha_flag, |
794 CGImageRelease(image); | 853 pIccTransform); |
795 CGContextRelease(ctx); | 854 if (!ret) { |
796 if (pBitmap1 != pBitmap) { | 855 RestoreState(FALSE); |
797 delete pBitmap1; | 856 return ret; |
798 } | 857 } |
799 RestoreState(FALSE); | 858 i++; |
800 return TRUE; | 859 pCharPos += i; |
801 } | 860 nChars -= i; |
802 FX_BOOL CFX_QuartzDeviceDriver::CG_DrawGlypRun(int nChars
, | 861 i = 0; |
803 const FXTEXT_CHARPOS* pCharPos, | 862 } else { |
804 CFX_Font* pFont, | 863 i++; |
805 CFX_FontCache* pCache, | 864 } |
806 const CFX_AffineMatrix* pGlyphMatrix, | 865 } |
807 const CFX_AffineMatrix* pObject2Device, | 866 if (i > 0) { |
808 FX_FLOAT font_size, | 867 ret = CG_DrawGlypRun(i, pCharPos, pFont, pCache, NULL, pObject2Device, |
809 FX_DWORD argb, | 868 font_size, color, alpha_flag, pIccTransform); |
810 int alpha_flag, | 869 } |
811 void* pIccTransform) | 870 RestoreState(FALSE); |
812 { | 871 return ret; |
813 if (nChars == 0) { | 872 } |
814 return TRUE; | 873 void CFX_QuartzDeviceDriver::setStrokeInfo(const CFX_GraphStateData* graphState, |
815 } | 874 FX_ARGB argb, |
816 CQuartz2D& quartz2d = ((CApplePlatform *) CFX_GEModule::Get()->GetPlatformDa
ta())->_quartz2d; | 875 FX_FLOAT lineWidth) { |
817 if (!pFont->m_pPlatformFont) { | 876 if (NULL == graphState) { |
818 if (pFont->GetPsName() == CFX_WideString::FromLocal("DFHeiStd-W5")) { | 877 return; |
819 return FALSE; | 878 } |
820 } | 879 CGContextSetLineWidth(_context, lineWidth); |
821 pFont->m_pPlatformFont = quartz2d.CreateFont(pFont->m_pFontData, pFont->
m_dwSize); | 880 CGLineCap cap; |
822 if (NULL == pFont->m_pPlatformFont) { | 881 switch (graphState->m_LineCap) { |
823 return FALSE; | 882 case CFX_GraphStateData::LineCapRound: { |
824 } | 883 cap = kCGLineCapRound; |
825 } | 884 break; |
826 CFX_FixedBufGrow<FX_WORD, 32> glyph_indices(nChars); | 885 } |
827 CFX_FixedBufGrow<CGPoint, 32> glyph_positions(nChars); | 886 case CFX_GraphStateData::LineCapSquare: { |
828 for (int i = 0; i < nChars; i++ ) { | 887 cap = kCGLineCapSquare; |
829 glyph_indices[i] = pCharPos[i].m_ExtGID; | 888 break; |
830 glyph_positions[i].x = pCharPos[i].m_OriginX; | 889 } |
831 glyph_positions[i].y = pCharPos[i].m_OriginY; | 890 case CFX_GraphStateData::LineCapButt: |
832 } | 891 default: { cap = kCGLineCapButt; } |
833 CFX_AffineMatrix text_matrix; | 892 } |
834 if (pObject2Device) { | 893 CGContextSetLineCap(_context, cap); |
835 text_matrix.Concat(*pObject2Device); | 894 CGLineJoin join; |
836 } | 895 switch (graphState->m_LineJoin) { |
837 CGAffineTransform matrix_cg = CGAffineTransformMake(text_matrix.a, | 896 case CFX_GraphStateData::LineJoinRound: { |
838 text_matrix.b, | 897 join = kCGLineJoinRound; |
839 text_matrix.c, | 898 break; |
840 text_matrix.d, | 899 } |
841 text_matrix.e, | 900 case CFX_GraphStateData::LineJoinBevel: { |
842 text_matrix.f); | 901 join = kCGLineJoinBevel; |
843 matrix_cg = CGAffineTransformConcat(matrix_cg, _foxitDevice2User); | 902 break; |
844 CGContextSetTextMatrix(_context, matrix_cg); | 903 } |
845 CGContextSetFont(_context, (CGFontRef)pFont->m_pPlatformFont); | 904 case CFX_GraphStateData::LineJoinMiter: |
846 CGContextSetFontSize(_context, FXSYS_fabs(font_size)); | 905 default: { join = kCGLineJoinMiter; } |
847 int32_t a, r, g, b; | 906 } |
848 ArgbDecode(argb, a, r, g, b); | 907 CGContextSetLineJoin(_context, join); |
849 CGContextSetRGBFillColor(_context, | 908 if (graphState->m_DashCount) { |
850 r / 255.f, | 909 #if CGFLOAT_IS_DOUBLE |
851 g / 255.f, | 910 CGFloat* dashArray = new CGFloat[graphState->m_DashCount]; |
852 b / 255.f, | 911 if (!dashArray) { |
| 912 return; |
| 913 } |
| 914 for (int index = 0; index < graphState->m_DashCount; ++index) { |
| 915 dashArray[index] = graphState->m_DashArray[index]; |
| 916 } |
| 917 #else |
| 918 CGFloat* dashArray = (CGFloat*)graphState->m_DashArray; |
| 919 #endif |
| 920 CGContextSetLineDash(_context, graphState->m_DashPhase, dashArray, |
| 921 graphState->m_DashCount); |
| 922 #if CGFLOAT_IS_DOUBLE |
| 923 delete[] dashArray; |
| 924 #endif |
| 925 } |
| 926 int32_t a, r, g, b; |
| 927 ArgbDecode(argb, a, r, g, b); |
| 928 CGContextSetRGBStrokeColor(_context, r / 255.f, g / 255.f, b / 255.f, |
853 a / 255.f); | 929 a / 255.f); |
854 SaveState(); | 930 } |
855 if (pGlyphMatrix) { | 931 void CFX_QuartzDeviceDriver::setFillInfo(FX_ARGB argb) { |
856 CGPoint origin = CGPointMake( glyph_positions[0].x, glyph_positions[0].
y); | 932 int32_t a, r, g, b; |
857 origin = CGPointApplyAffineTransform(origin, matrix_cg); | 933 ArgbDecode(argb, a, r, g, b); |
858 CGContextTranslateCTM(_context, origin.x, origin.y); | 934 CGContextSetRGBFillColor(_context, r / 255.f, g / 255.f, b / 255.f, |
859 CGAffineTransform glyph_matrix = CGAffineTransformMake(pGlyphMatrix->a, | 935 a / 255.f); |
860 pGlyphMatrix->b, | 936 } |
861 pGlyphMatrix->c, | 937 void CFX_QuartzDeviceDriver::setPathToContext(const CFX_PathData* pathData) { |
862 pGlyphMatrix->d, | 938 int32_t count = pathData->GetPointCount(); |
863 pGlyphMatrix->e, | 939 FX_PATHPOINT* points = pathData->GetPoints(); |
864 pGlyphMatrix->f); | 940 CGContextBeginPath(_context); |
865 if (_foxitDevice2User.d < 0) { | 941 for (int32_t i = 0; i < count; i++) { |
866 glyph_matrix = CGAffineTransformInvert(glyph_matrix); | 942 switch (points[i].m_Flag & FXPT_TYPE) { |
867 } | 943 case FXPT_MOVETO: |
868 CGContextConcatCTM(_context, glyph_matrix); | 944 CGContextMoveToPoint(_context, points[i].m_PointX, points[i].m_PointY); |
869 CGContextTranslateCTM(_context, -origin.x, -origin.y); | 945 break; |
870 } | 946 case FXPT_LINETO: |
871 CGContextShowGlyphsAtPositions(_context, | 947 CGContextAddLineToPoint(_context, points[i].m_PointX, |
872 (CGGlyph*)glyph_indices, | 948 points[i].m_PointY); |
873 glyph_positions, | 949 break; |
874 nChars); | 950 case FXPT_BEZIERTO: { |
875 RestoreState(FALSE); | 951 CGContextAddCurveToPoint(_context, points[i].m_PointX, |
876 return TRUE; | 952 points[i].m_PointY, points[i + 1].m_PointX, |
877 } | 953 points[i + 1].m_PointY, points[i + 2].m_PointX, |
878 FX_BOOL CFX_QuartzDeviceDriver::DrawDeviceText(int nChars, | 954 points[i + 2].m_PointY); |
879 const FXTEXT_CHARPOS* pCharPos, | 955 i += 2; |
880 CFX_Font* pFont, | 956 } |
881 CFX_FontCache* pCache, | 957 } |
882 const CFX_AffineMatrix* pObject2Device, | 958 if (points[i].m_Flag & FXPT_CLOSEFIGURE) { |
883 FX_FLOAT font_size, | 959 CGContextClosePath(_context); |
884 FX_DWORD color, | 960 } |
885 int alpha_flag , | 961 } |
886 void* pIccTransform) | 962 } |
887 { | 963 void CFX_QuartzDeviceDriver::CG_SetImageTransform(int dest_left, |
888 if (NULL == pFont || NULL == _context) { | 964 int dest_top, |
889 return FALSE; | 965 int dest_width, |
890 } | 966 int dest_height, |
891 FX_BOOL bBold = pFont->IsBold(); | 967 CGRect* rect) { |
892 if (!bBold && pFont->GetSubstFont() && | 968 int flip_y = _foxitDevice2User.d * dest_height < 0 ? 1 : -1; |
893 pFont->GetSubstFont()->m_Weight >= 500 && | 969 int flip_x = _foxitDevice2User.a * dest_width > 0 ? 1 : -1; |
894 pFont->GetSubstFont()->m_Weight <= 600) { | 970 if (flip_y < 0 || flip_x < 0) { |
895 return FALSE; | 971 if (dest_height < 0) { |
896 } | 972 dest_height = -dest_height; |
897 SaveState(); | 973 dest_top -= dest_height; |
898 CGContextSetTextDrawingMode(_context, kCGTextFillClip); | 974 } |
899 FX_BOOL ret = FALSE; | 975 CGRect rt = CGRectApplyAffineTransform( |
900 int32_t i = 0; | 976 CGRectMake(dest_left, dest_top, dest_width, dest_height), |
901 while (i < nChars) { | 977 _foxitDevice2User); |
902 if (pCharPos[i].m_bGlyphAdjust || font_size < 0) { | 978 CGFloat offset_x = (rt.origin.x) + rt.size.width / 2.f, |
903 if (i > 0) { | 979 offset_y = (rt.origin.y) + rt.size.height / 2.f; |
904 ret = CG_DrawGlypRun(i, pCharPos, pFont, pCache, NULL, pObject2D
evice, font_size, color, alpha_flag, pIccTransform); | 980 CGAffineTransform transform = CGAffineTransformIdentity; |
905 if (!ret) { | 981 transform = CGAffineTransformConcat( |
906 RestoreState(FALSE); | 982 transform, CGAffineTransformMake(1, 0, 0, 1, -offset_x, -offset_y)); |
907 return ret; | 983 transform = CGAffineTransformConcat( |
908 } | 984 transform, CGAffineTransformMake(flip_x, 0, 0, flip_y, 0, 0)); |
909 } | 985 transform = CGAffineTransformConcat( |
910 const FXTEXT_CHARPOS* char_pos = pCharPos + i; | 986 transform, CGAffineTransformMake(1, 0, 0, 1, offset_x, offset_y)); |
911 CFX_AffineMatrix glphy_matrix; | 987 CGContextConcatCTM(_context, transform); |
912 if (font_size < 0) { | 988 if (rect) { |
913 glphy_matrix.Concat(-1, 0, 0, -1, 0, 0); | 989 *rect = CGRectApplyAffineTransform(*rect, transform); |
914 } | 990 } |
915 if (char_pos->m_bGlyphAdjust) { | 991 } |
916 glphy_matrix.Concat(char_pos->m_AdjustMatrix[0], | 992 } |
917 char_pos->m_AdjustMatrix[1], | 993 void CFX_QuartzDeviceDriver::ClearDriver() { |
918 char_pos->m_AdjustMatrix[2], | 994 if (NULL == _context) { |
919 char_pos->m_AdjustMatrix[3], 0, 0); | 995 return; |
920 } | 996 } |
921 ret = CG_DrawGlypRun(1, char_pos, pFont, pCache, &glphy_matrix, pObj
ect2Device, font_size, color, alpha_flag, pIccTransform); | 997 for (int i = 0; i < m_saveCount; ++i) { |
922 if (!ret) { | 998 CGContextRestoreGState(_context); |
923 RestoreState(FALSE); | 999 } |
924 return ret; | 1000 m_saveCount = 0; |
925 } | 1001 if (_context) { |
926 i ++; | 1002 CGContextRelease(_context); |
927 pCharPos += i; | 1003 } |
928 nChars -= i; | 1004 } |
929 i = 0; | 1005 CFX_QuartzDevice::CFX_QuartzDevice() { |
930 } else { | 1006 m_bOwnedBitmap = FALSE; |
931 i ++; | 1007 m_pContext = NULL; |
932 } | 1008 } |
933 } | 1009 CFX_QuartzDevice::~CFX_QuartzDevice() { |
934 if (i > 0) { | 1010 if (m_pContext) { |
935 ret = CG_DrawGlypRun(i, pCharPos, pFont, pCache, NULL, pObject2Device, f
ont_size, color, alpha_flag, pIccTransform); | 1011 CGContextRelease(m_pContext); |
936 } | 1012 } |
937 RestoreState(FALSE); | 1013 if (m_bOwnedBitmap) { |
938 return ret; | 1014 delete GetBitmap(); |
939 } | 1015 } |
940 void CFX_QuartzDeviceDriver::setStrokeInfo(const CFX_GraphStateData* graphState,
FX_ARGB argb, FX_FLOAT lineWidth) | 1016 } |
941 { | 1017 CGContextRef CFX_QuartzDevice::GetContext() { |
942 if (NULL == graphState) { | 1018 return m_pContext; |
943 return; | 1019 } |
944 } | 1020 FX_BOOL CFX_QuartzDevice::Attach(CGContextRef context, int32_t nDeviceClass) { |
945 CGContextSetLineWidth(_context, lineWidth); | 1021 if (m_pContext) { |
946 CGLineCap cap; | 1022 CGContextRelease(m_pContext); |
947 switch (graphState->m_LineCap) { | 1023 } |
948 case CFX_GraphStateData::LineCapRound: { | 1024 m_pContext = context; |
949 cap = kCGLineCapRound; | 1025 CGContextRetain(m_pContext); |
950 break; | 1026 IFX_RenderDeviceDriver* pDriver = |
951 } | 1027 new CFX_QuartzDeviceDriver(m_pContext, nDeviceClass); |
952 case CFX_GraphStateData::LineCapSquare: { | 1028 SetDeviceDriver(pDriver); |
953 cap = kCGLineCapSquare; | 1029 return TRUE; |
954 break; | 1030 } |
955 } | 1031 FX_BOOL CFX_QuartzDevice::Attach(CFX_DIBitmap* pBitmap) { |
956 case CFX_GraphStateData::LineCapButt: | 1032 SetBitmap(pBitmap); |
957 default: { | 1033 m_pContext = createContextWithBitmap(pBitmap); |
958 cap = kCGLineCapButt; | 1034 if (NULL == m_pContext) { |
959 } | 1035 return FALSE; |
960 } | 1036 } |
961 CGContextSetLineCap(_context, cap); | 1037 IFX_RenderDeviceDriver* pDriver = |
962 CGLineJoin join; | 1038 new CFX_QuartzDeviceDriver(m_pContext, FXDC_DISPLAY); |
963 switch (graphState->m_LineJoin) { | 1039 SetDeviceDriver(pDriver); |
964 case CFX_GraphStateData::LineJoinRound: { | 1040 return TRUE; |
965 join = kCGLineJoinRound; | 1041 } |
966 break; | 1042 FX_BOOL CFX_QuartzDevice::Create(int32_t width, |
967 } | 1043 int32_t height, |
968 case CFX_GraphStateData::LineJoinBevel: { | 1044 FXDIB_Format format) { |
969 join = kCGLineJoinBevel; | 1045 if ((uint8_t)format < 32) { |
970 break; | 1046 return FALSE; |
971 } | 1047 } |
972 case CFX_GraphStateData::LineJoinMiter: | 1048 CFX_DIBitmap* pBitmap = new CFX_DIBitmap; |
973 default: { | 1049 if (!pBitmap->Create(width, height, format)) { |
974 join = kCGLineJoinMiter; | 1050 delete pBitmap; |
975 } | 1051 return FALSE; |
976 } | 1052 } |
977 CGContextSetLineJoin(_context, join); | 1053 m_bOwnedBitmap = TRUE; |
978 if (graphState->m_DashCount) { | 1054 return Attach(pBitmap); |
979 #if CGFLOAT_IS_DOUBLE | |
980 CGFloat* dashArray = new CGFloat[graphState->m_DashCount]; | |
981 if (!dashArray) { | |
982 return; | |
983 } | |
984 for (int index = 0; index < graphState->m_DashCount; ++index) { | |
985 dashArray[index] = graphState->m_DashArray[index]; | |
986 } | |
987 #else | |
988 CGFloat* dashArray = (CGFloat*)graphState->m_DashArray; | |
989 #endif | |
990 CGContextSetLineDash(_context, graphState->m_DashPhase, dashArray, graph
State->m_DashCount); | |
991 #if CGFLOAT_IS_DOUBLE | |
992 delete[] dashArray; | |
993 #endif | |
994 } | |
995 int32_t a, r, g, b; | |
996 ArgbDecode(argb, a, r, g, b); | |
997 CGContextSetRGBStrokeColor(_context, | |
998 r / 255.f, | |
999 g / 255.f, | |
1000 b / 255.f, | |
1001 a / 255.f); | |
1002 } | |
1003 void CFX_QuartzDeviceDriver::setFillInfo(FX_ARGB argb) | |
1004 { | |
1005 int32_t a, r, g, b; | |
1006 ArgbDecode(argb, a, r, g, b); | |
1007 CGContextSetRGBFillColor(_context, | |
1008 r / 255.f, | |
1009 g / 255.f, | |
1010 b / 255.f, | |
1011 a / 255.f); | |
1012 } | |
1013 void CFX_QuartzDeviceDriver::setPathToContext(const CFX_PathData* pathData) | |
1014 { | |
1015 int32_t count = pathData->GetPointCount(); | |
1016 FX_PATHPOINT* points = pathData->GetPoints(); | |
1017 CGContextBeginPath(_context); | |
1018 for (int32_t i = 0; i < count; i ++) { | |
1019 switch (points[i].m_Flag & FXPT_TYPE) { | |
1020 case FXPT_MOVETO: | |
1021 CGContextMoveToPoint(_context, points[i].m_PointX, points[i].m_P
ointY); | |
1022 break; | |
1023 case FXPT_LINETO: | |
1024 CGContextAddLineToPoint(_context, points[i].m_PointX, points[i].
m_PointY); | |
1025 break; | |
1026 case FXPT_BEZIERTO: { | |
1027 CGContextAddCurveToPoint(_context, | |
1028 points[i].m_PointX, points[i].m_Poi
ntY, | |
1029 points[i + 1].m_PointX, points[i +
1].m_PointY, | |
1030 points[i + 2].m_PointX, points[i +
2].m_PointY); | |
1031 i += 2; | |
1032 } | |
1033 } | |
1034 if (points[i].m_Flag & FXPT_CLOSEFIGURE) { | |
1035 CGContextClosePath(_context); | |
1036 } | |
1037 } | |
1038 } | |
1039 void CFX_QuartzDeviceDriver::CG_SetImageTransform(int dest_left, int dest_top, i
nt dest_width, int dest_height, | |
1040 CGRect* rect ) | |
1041 { | |
1042 int flip_y = _foxitDevice2User.d * dest_height < 0 ? 1 : -1; | |
1043 int flip_x = _foxitDevice2User.a * dest_width > 0 ? 1 : -1; | |
1044 if (flip_y < 0 || flip_x < 0) { | |
1045 if (dest_height < 0) { | |
1046 dest_height = -dest_height; | |
1047 dest_top -= dest_height; | |
1048 } | |
1049 CGRect rt = CGRectApplyAffineTransform(CGRectMake(dest_left, dest_top, d
est_width, dest_height), _foxitDevice2User); | |
1050 CGFloat offset_x = (rt.origin.x) + rt.size.width / 2.f, | |
1051 offset_y = (rt.origin.y) + rt.size.height / 2.f; | |
1052 CGAffineTransform transform = CGAffineTransformIdentity; | |
1053 transform = CGAffineTransformConcat(transform, CGAffineTransformMake(1,
0, 0, 1, -offset_x, -offset_y)); | |
1054 transform = CGAffineTransformConcat(transform, CGAffineTransformMake(fli
p_x, 0, 0, flip_y, 0, 0)); | |
1055 transform = CGAffineTransformConcat(transform, CGAffineTransformMake(1,
0, 0, 1, offset_x, offset_y)); | |
1056 CGContextConcatCTM(_context, transform); | |
1057 if (rect) { | |
1058 *rect = CGRectApplyAffineTransform(*rect, transform); | |
1059 } | |
1060 } | |
1061 } | |
1062 void CFX_QuartzDeviceDriver::ClearDriver() | |
1063 { | |
1064 if (NULL == _context) { | |
1065 return; | |
1066 } | |
1067 for (int i = 0; i < m_saveCount; ++i) { | |
1068 CGContextRestoreGState(_context); | |
1069 } | |
1070 m_saveCount = 0; | |
1071 if (_context) { | |
1072 CGContextRelease(_context); | |
1073 } | |
1074 } | |
1075 CFX_QuartzDevice::CFX_QuartzDevice() | |
1076 { | |
1077 m_bOwnedBitmap = FALSE; | |
1078 m_pContext = NULL; | |
1079 } | |
1080 CFX_QuartzDevice::~CFX_QuartzDevice() | |
1081 { | |
1082 if (m_pContext) { | |
1083 CGContextRelease(m_pContext); | |
1084 } | |
1085 if (m_bOwnedBitmap) { | |
1086 delete GetBitmap(); | |
1087 } | |
1088 } | |
1089 CGContextRef CFX_QuartzDevice::GetContext() | |
1090 { | |
1091 return m_pContext; | |
1092 } | |
1093 FX_BOOL CFX_QuartzDevice::Attach(CGContextRef context, int32_t nDeviceClass) | |
1094 { | |
1095 if (m_pContext) { | |
1096 CGContextRelease(m_pContext); | |
1097 } | |
1098 m_pContext = context; | |
1099 CGContextRetain(m_pContext); | |
1100 IFX_RenderDeviceDriver* pDriver = new CFX_QuartzDeviceDriver(m_pContext, nDe
viceClass); | |
1101 SetDeviceDriver(pDriver); | |
1102 return TRUE; | |
1103 } | |
1104 FX_BOOL CFX_QuartzDevice::Attach(CFX_DIBitmap* pBitmap) | |
1105 { | |
1106 SetBitmap(pBitmap); | |
1107 m_pContext = createContextWithBitmap(pBitmap); | |
1108 if (NULL == m_pContext) { | |
1109 return FALSE; | |
1110 } | |
1111 IFX_RenderDeviceDriver* pDriver = new CFX_QuartzDeviceDriver(m_pContext, FXD
C_DISPLAY); | |
1112 SetDeviceDriver(pDriver); | |
1113 return TRUE; | |
1114 } | |
1115 FX_BOOL CFX_QuartzDevice::Create(int32_t width, int32_t height, FXDIB_Format for
mat) | |
1116 { | |
1117 if ((uint8_t)format < 32) { | |
1118 return FALSE; | |
1119 } | |
1120 CFX_DIBitmap* pBitmap = new CFX_DIBitmap; | |
1121 if (!pBitmap->Create(width, height, format)) { | |
1122 delete pBitmap; | |
1123 return FALSE; | |
1124 } | |
1125 m_bOwnedBitmap = TRUE; | |
1126 return Attach(pBitmap); | |
1127 } | 1055 } |
1128 #endif // _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ | 1056 #endif // _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ |
OLD | NEW |