1 11 package org.eclipse.swt.graphics; 12 13 14 import org.eclipse.swt.internal.*; 15 import org.eclipse.swt.internal.gdip.*; 16 import org.eclipse.swt.internal.win32.*; 17 import org.eclipse.swt.*; 18 19 25 public abstract class Device implements Drawable { 26 27 28 public static boolean DEBUG; 29 boolean debug = DEBUG; 30 boolean tracking = DEBUG; 31 Error [] errors; 32 Object [] objects; 33 34 44 public int hPalette = 0; 45 int [] colorRefCount; 46 47 48 int systemFont; 49 50 51 int nFonts = 256; 52 LOGFONT [] logFonts; 53 TEXTMETRIC metrics; 54 int[] pixels; 55 56 57 int [] scripts; 58 59 60 int [] gdipToken; 61 62 boolean disposed; 63 64 final static Object CREATE_LOCK = new Object (); 65 66 78 protected static Device CurrentDevice; 79 protected static Runnable DeviceFinder; 80 static { 81 try { 82 Class.forName ("org.eclipse.swt.widgets.Display"); } catch (Throwable e) {} 84 } 85 86 89 static synchronized Device getDevice () { 90 if (DeviceFinder != null) DeviceFinder.run(); 91 Device device = CurrentDevice; 92 CurrentDevice = null; 93 return device; 94 } 95 96 107 public Device() { 108 this(null); 109 } 110 111 123 public Device(DeviceData data) { 124 synchronized (CREATE_LOCK) { 125 if (data != null) { 126 debug = data.debug; 127 tracking = data.tracking; 128 } 129 create (data); 130 init (); 131 if (tracking) { 132 errors = new Error [128]; 133 objects = new Object [128]; 134 } 135 136 137 systemFont = getSystemFont().handle; 138 } 139 } 140 141 160 protected void checkDevice () { 161 if (disposed) SWT.error(SWT.ERROR_DEVICE_DISPOSED); 162 } 163 164 void checkGDIP() { 165 if (gdipToken != null) return; 166 if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED); 167 int oldErrorMode = OS.SetErrorMode (OS.SEM_FAILCRITICALERRORS); 168 try { 169 int [] token = new int [1]; 170 GdiplusStartupInput input = new GdiplusStartupInput (); 171 input.GdiplusVersion = 1; 172 if (Gdip.GdiplusStartup (token, input, 0) == 0) { 173 gdipToken = token; 174 } 175 } catch (Throwable t) { 176 SWT.error (SWT.ERROR_NO_GRAPHICS_LIBRARY, t, " [GDI+ is required]"); } finally { 178 OS.SetErrorMode (oldErrorMode); 179 } 180 } 181 182 197 protected void create (DeviceData data) { 198 } 199 200 int computePixels(float height) { 201 int hDC = internal_new_GC (null); 202 int pixels = -(int)(0.5f + (height * OS.GetDeviceCaps(hDC, OS.LOGPIXELSY) / 72f)); 203 internal_dispose_GC (hDC, null); 204 return pixels; 205 } 206 207 float computePoints(LOGFONT logFont, int hFont) { 208 int hDC = internal_new_GC (null); 209 int logPixelsY = OS.GetDeviceCaps(hDC, OS.LOGPIXELSY); 210 int pixels = 0; 211 if (logFont.lfHeight > 0) { 212 219 int oldFont = OS.SelectObject(hDC, hFont); 220 TEXTMETRIC lptm = OS.IsUnicode ? (TEXTMETRIC)new TEXTMETRICW() : new TEXTMETRICA(); 221 OS.GetTextMetrics(hDC, lptm); 222 OS.SelectObject(hDC, oldFont); 223 pixels = logFont.lfHeight - lptm.tmInternalLeading; 224 } else { 225 pixels = -logFont.lfHeight; 226 } 227 internal_dispose_GC (hDC, null); 228 return pixels * 72f / logPixelsY; 229 } 230 231 245 protected void destroy () { 246 } 247 248 258 public void dispose () { 259 if (isDisposed()) return; 260 checkDevice (); 261 release (); 262 destroy (); 263 disposed = true; 264 if (tracking) { 265 objects = null; 266 errors = null; 267 } 268 } 269 270 void dispose_Object (Object object) { 271 for (int i=0; i<objects.length; i++) { 272 if (objects [i] == object) { 273 objects [i] = null; 274 errors [i] = null; 275 return; 276 } 277 } 278 } 279 280 int EnumFontFamProc (int lpelfe, int lpntme, int FontType, int lParam) { 281 boolean isScalable = (FontType & OS.RASTER_FONTTYPE) == 0; 282 boolean scalable = lParam == 1; 283 if (isScalable == scalable) { 284 285 if (nFonts == logFonts.length) { 286 LOGFONT [] newLogFonts = new LOGFONT [logFonts.length + 128]; 287 System.arraycopy (logFonts, 0, newLogFonts, 0, nFonts); 288 logFonts = newLogFonts; 289 int[] newPixels = new int[newLogFonts.length]; 290 System.arraycopy (pixels, 0, newPixels, 0, nFonts); 291 pixels = newPixels; 292 } 293 LOGFONT logFont = logFonts [nFonts]; 294 if (logFont == null) logFont = OS.IsUnicode ? (LOGFONT)new LOGFONTW () : new LOGFONTA (); 295 OS.MoveMemory (logFont, lpelfe, LOGFONT.sizeof); 296 logFonts [nFonts] = logFont; 297 if (logFont.lfHeight > 0) { 298 306 OS.MoveMemory(metrics, lpntme, TEXTMETRIC.sizeof); 307 pixels[nFonts] = logFont.lfHeight - metrics.tmInternalLeading; 308 } else { 309 pixels[nFonts] = -logFont.lfHeight; 310 } 311 nFonts++; 312 } 313 return 1; 314 } 315 316 325 public Rectangle getBounds () { 326 checkDevice (); 327 int hDC = internal_new_GC (null); 328 int width = OS.GetDeviceCaps (hDC, OS.HORZRES); 329 int height = OS.GetDeviceCaps (hDC, OS.VERTRES); 330 internal_dispose_GC (hDC, null); 331 return new Rectangle (0, 0, width, height); 332 } 333 334 347 public DeviceData getDeviceData () { 348 checkDevice(); 349 DeviceData data = new DeviceData (); 350 data.debug = debug; 351 data.tracking = tracking; 352 int count = 0, length = 0; 353 if (tracking) length = objects.length; 354 for (int i=0; i<length; i++) { 355 if (objects [i] != null) count++; 356 } 357 int index = 0; 358 data.objects = new Object [count]; 359 data.errors = new Error [count]; 360 for (int i=0; i<length; i++) { 361 if (objects [i] != null) { 362 data.objects [index] = objects [i]; 363 data.errors [index] = errors [i]; 364 index++; 365 } 366 } 367 return data; 368 } 369 370 382 public Rectangle getClientArea () { 383 return getBounds (); 384 } 385 386 398 public int getDepth () { 399 checkDevice (); 400 int hDC = internal_new_GC (null); 401 int bits = OS.GetDeviceCaps (hDC, OS.BITSPIXEL); 402 int planes = OS.GetDeviceCaps (hDC, OS.PLANES); 403 internal_dispose_GC (hDC, null); 404 return bits * planes; 405 } 406 407 418 public Point getDPI () { 419 checkDevice (); 420 int hDC = internal_new_GC (null); 421 int dpiX = OS.GetDeviceCaps (hDC, OS.LOGPIXELSX); 422 int dpiY = OS.GetDeviceCaps (hDC, OS.LOGPIXELSY); 423 internal_dispose_GC (hDC, null); 424 return new Point (dpiX, dpiY); 425 } 426 427 440 public FontData [] getFontList (String faceName, boolean scalable) { 441 checkDevice (); 442 443 444 Callback callback = new Callback (this, "EnumFontFamProc", 4); int lpEnumFontFamProc = callback.getAddress (); 446 if (lpEnumFontFamProc == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS); 447 448 449 metrics = OS.IsUnicode ? (TEXTMETRIC)new TEXTMETRICW() : new TEXTMETRICA(); 450 pixels = new int[nFonts]; 451 logFonts = new LOGFONT [nFonts]; 452 for (int i=0; i<logFonts.length; i++) { 453 logFonts [i] = OS.IsUnicode ? (LOGFONT) new LOGFONTW () : new LOGFONTA (); 454 } 455 nFonts = 0; 456 457 458 int offset = 0; 459 int hDC = internal_new_GC (null); 460 if (faceName == null) { 461 462 OS.EnumFontFamilies (hDC, null, lpEnumFontFamProc, scalable ? 1 : 0); 463 464 469 offset = nFonts; 470 for (int i=0; i<offset; i++) { 471 LOGFONT lf = logFonts [i]; 472 477 if (OS.IsUnicode) { 478 OS.EnumFontFamiliesW (hDC, ((LOGFONTW)lf).lfFaceName, lpEnumFontFamProc, scalable ? 1 : 0); 479 } else { 480 OS.EnumFontFamiliesA (hDC, ((LOGFONTA)lf).lfFaceName, lpEnumFontFamProc, scalable ? 1 : 0); 481 } 482 } 483 } else { 484 485 TCHAR lpFaceName = new TCHAR (0, faceName, true); 486 491 OS.EnumFontFamilies (hDC, lpFaceName, lpEnumFontFamProc, scalable ? 1 : 0); 492 } 493 int logPixelsY = OS.GetDeviceCaps(hDC, OS.LOGPIXELSY); 494 internal_dispose_GC (hDC, null); 495 496 497 int count = 0; 498 FontData [] result = new FontData [nFonts - offset]; 499 for (int i=offset; i<nFonts; i++) { 500 FontData fd = FontData.win32_new (logFonts [i], pixels [i] * 72f / logPixelsY); 501 int j; 502 for (j = 0; j < count; j++) { 503 if (fd.equals (result [j])) break; 504 } 505 if (j == count) result [count++] = fd; 506 } 507 if (count != result.length) { 508 FontData [] newResult = new FontData [count]; 509 System.arraycopy (result, 0, newResult, 0, count); 510 result = newResult; 511 } 512 513 514 callback.dispose (); 515 logFonts = null; 516 pixels = null; 517 metrics = null; 518 return result; 519 } 520 521 String getLastError () { 522 int error = OS.GetLastError(); 523 if (error == 0) return ""; return " [GetLastError=0x" + Integer.toHexString(error) + "]"; } 526 527 String getLastErrorText () { 528 int error = OS.GetLastError(); 529 if (error == 0) return ""; int[] buffer = new int[1]; 531 int dwFlags = OS.FORMAT_MESSAGE_ALLOCATE_BUFFER | OS.FORMAT_MESSAGE_FROM_SYSTEM | OS.FORMAT_MESSAGE_IGNORE_INSERTS; 532 int length = OS.FormatMessage(dwFlags, 0, error, OS.LANG_USER_DEFAULT, buffer, 0, 0); 533 if (length == 0) return " [GetLastError=0x" + Integer.toHexString(error) + "]"; TCHAR buffer1 = new TCHAR(0, length); 535 OS.MoveMemory(buffer1, buffer[0], length * TCHAR.sizeof); 536 if (buffer[0] != 0) OS.LocalFree(buffer[0]); 537 return buffer1.toString(0, length); 538 } 539 540 558 public Color getSystemColor (int id) { 559 checkDevice (); 560 int pixel = 0x00000000; 561 switch (id) { 562 case SWT.COLOR_WHITE: pixel = 0x00FFFFFF; break; 563 case SWT.COLOR_BLACK: pixel = 0x00000000; break; 564 case SWT.COLOR_RED: pixel = 0x000000FF; break; 565 case SWT.COLOR_DARK_RED: pixel = 0x00000080; break; 566 case SWT.COLOR_GREEN: pixel = 0x0000FF00; break; 567 case SWT.COLOR_DARK_GREEN: pixel = 0x00008000; break; 568 case SWT.COLOR_YELLOW: pixel = 0x0000FFFF; break; 569 case SWT.COLOR_DARK_YELLOW: pixel = 0x00008080; break; 570 case SWT.COLOR_BLUE: pixel = 0x00FF0000; break; 571 case SWT.COLOR_DARK_BLUE: pixel = 0x00800000; break; 572 case SWT.COLOR_MAGENTA: pixel = 0x00FF00FF; break; 573 case SWT.COLOR_DARK_MAGENTA: pixel = 0x00800080; break; 574 case SWT.COLOR_CYAN: pixel = 0x00FFFF00; break; 575 case SWT.COLOR_DARK_CYAN: pixel = 0x00808000; break; 576 case SWT.COLOR_GRAY: pixel = 0x00C0C0C0; break; 577 case SWT.COLOR_DARK_GRAY: pixel = 0x00808080; break; 578 } 579 return Color.win32_new (this, pixel); 580 } 581 582 602 public Font getSystemFont () { 603 checkDevice (); 604 int hFont = OS.GetStockObject (OS.SYSTEM_FONT); 605 return Font.win32_new (this, hFont); 606 } 607 608 619 public boolean getWarnings () { 620 checkDevice (); 621 return false; 622 } 623 624 636 protected void init () { 637 if (debug) { 638 if (!OS.IsWinCE) OS.GdiSetBatchLimit(1); 639 } 640 641 642 if (!OS.IsWinCE) { 643 int [] ppSp = new int [1]; 644 int [] piNumScripts = new int [1]; 645 OS.ScriptGetProperties (ppSp, piNumScripts); 646 scripts = new int [piNumScripts [0]]; 647 OS.MoveMemory (scripts, ppSp [0], scripts.length * 4); 648 } 649 650 654 int hDC = internal_new_GC (null); 655 int rc = OS.GetDeviceCaps (hDC, OS.RASTERCAPS); 656 int bits = OS.GetDeviceCaps (hDC, OS.BITSPIXEL); 657 int planes = OS.GetDeviceCaps (hDC, OS.PLANES); 658 659 bits *= planes; 660 if ((rc & OS.RC_PALETTE) == 0 || bits != 8) { 661 internal_dispose_GC (hDC, null); 662 return; 663 } 664 665 int numReserved = OS.GetDeviceCaps (hDC, OS.NUMRESERVED); 666 int numEntries = OS.GetDeviceCaps (hDC, OS.SIZEPALETTE); 667 668 if (OS.IsWinCE) { 669 676 if (numReserved == 0 && numEntries >= 20) numReserved = 20; 677 } 678 679 680 colorRefCount = new int [numEntries]; 681 682 683 byte [] logPalette = new byte [4 + 4 * numEntries]; 684 685 686 logPalette [0] = 0x00; 687 logPalette [1] = 0x03; 688 689 690 logPalette [2] = 0; 691 logPalette [3] = 1; 692 693 701 byte[] lppe = new byte [4 * numEntries]; 702 OS.GetSystemPaletteEntries (hDC, 0, numEntries, lppe); 703 704 System.arraycopy (lppe, 0, logPalette, 4, 4 * numEntries); 705 706 for (int i = 0; i < numReserved / 2; i++) { 707 colorRefCount [i] = 1; 708 colorRefCount [numEntries - 1 - i] = 1; 709 } 710 internal_dispose_GC (hDC, null); 711 hPalette = OS.CreatePalette (logPalette); 712 } 713 726 public abstract int internal_new_GC (GCData data); 727 728 741 public abstract void internal_dispose_GC (int hDC, GCData data); 742 743 753 public boolean isDisposed () { 754 return disposed; 755 } 756 757 773 public boolean loadFont (String path) { 774 checkDevice(); 775 if (path == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); 776 if (OS.IsWinNT && OS.WIN32_VERSION >= OS.VERSION (4, 10)) { 777 TCHAR lpszFilename = new TCHAR (0, path, true); 778 return OS.AddFontResourceEx (lpszFilename, OS.FR_PRIVATE, 0) != 0; 779 } 780 return false; 781 } 782 783 void new_Object (Object object) { 784 for (int i=0; i<objects.length; i++) { 785 if (objects [i] == null) { 786 objects [i] = object; 787 errors [i] = new Error (); 788 return; 789 } 790 } 791 Object [] newObjects = new Object [objects.length + 128]; 792 System.arraycopy (objects, 0, newObjects, 0, objects.length); 793 newObjects [objects.length] = object; 794 objects = newObjects; 795 Error [] newErrors = new Error [errors.length + 128]; 796 System.arraycopy (errors, 0, newErrors, 0, errors.length); 797 newErrors [errors.length] = new Error (); 798 errors = newErrors; 799 } 800 801 824 protected void release () { 825 if (gdipToken != null) { 826 Gdip.GdiplusShutdown (gdipToken[0]); 827 } 828 gdipToken = null; 829 scripts = null; 830 if (hPalette != 0) OS.DeleteObject (hPalette); 831 hPalette = 0; 832 colorRefCount = null; 833 logFonts = null; 834 nFonts = 0; 835 } 836 837 849 public void setWarnings (boolean warnings) { 850 checkDevice (); 851 } 852 853 } 854 | Popular Tags |