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