summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordkf <donal.k.fellows@manchester.ac.uk>2008-11-22 18:08:51 (GMT)
committerdkf <donal.k.fellows@manchester.ac.uk>2008-11-22 18:08:51 (GMT)
commit08d210474dcf15c239160ca885bd7799ac618787 (patch)
treea79e10925b1fe14d042ef56ea012b2e1e56407de
parent76c04ee36744e2a988a33f9d8ccb9d3b7e2359c2 (diff)
downloadtk-08d210474dcf15c239160ca885bd7799ac618787.zip
tk-08d210474dcf15c239160ca885bd7799ac618787.tar.gz
tk-08d210474dcf15c239160ca885bd7799ac618787.tar.bz2
TIP#119 implementation. [Patch 1611359]
-rw-r--r--ChangeLog327
-rw-r--r--generic/tkCanvText.c298
-rw-r--r--generic/tkFont.c388
-rw-r--r--generic/tkInt.h28
-rw-r--r--library/prolog.ps12
-rw-r--r--macosx/tkMacOSXFont.c70
-rw-r--r--tests/canvText.test581
-rw-r--r--unix/tkUnixFont.c283
-rw-r--r--unix/tkUnixRFont.c292
-rw-r--r--win/tkWinFont.c303
10 files changed, 1922 insertions, 660 deletions
diff --git a/ChangeLog b/ChangeLog
index b753a3b..81b169e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,29 +1,42 @@
-2008-11-22 Pat Thoyts <patthoyts@users.sourceforge.net>
+2008-11-22 Donal K. Fellows <dkf@users.sf.net>
+
+ TIP #119 IMPLEMENTATION
+
+ * generic/tkCanvText.c: Added -angle configuration option to canvas
+ * generic/tkFont.c: text items. This required reengineering the
+ * library/prolog.ps: whole text rendering engine to be able to
+ * macosx/tkMacOSXFont.c: handle an angle! No change to any external
+ * unix/tkUnixFont.c: API. Note, this feature was originally
+ * unix/tkUnixRFont.c: approved for Tk 8.5, but it has proved much
+ * win/tkWinFont.c: harder to implement than originally
+ * generic/tkInt.h: estimated. [Patch 1611359]
+ * tests/canvText.test:
+
+2008-11-22 Pat Thoyts <patthoyts@users.sourceforge.net>
- * test/winDialog.test: [Bug 2307837] avoid some locale-dependent
- * win/tkWinTest.c: failures by using id's or an english constraint
+ * test/winDialog.test: Avoid some locale-dependent failures by using
+ * win/tkWinTest.c: id's or an english constraint. [Bug 2307837]
-2008-11-19 Joe English <jenglish@users.sourceforge.net>
+2008-11-19 Joe English <jenglish@users.sourceforge.net>
- * doc/ttk_panedwindow.n: Remove inoperative text
- stating that slave windows must be direct children
- of the master [Bug 1824996].
+ * doc/ttk_panedwindow.n: Remove inoperative text stating that slave
+ windows must be direct children of the master. [Bug 1824996]
2008-11-19 Jan Nijtmans <nijtmans@users.sf.net>
- * generic/tkImgPhoto.c Minor simplification in fix for [Bug 2312027]:
- no need to malloc and copy photo type name because
- it is a constant to begin with.
- * generic/tkOldConfig.c Convert Tcl_SetResult(......, TCL_DYNAMIC) to
- * mac/tkMacOSXWm.c Tcl_SetResult(......, TCL_VOLATILE), in preparation
- * unix/tkUnixWm.c for TIP #340
+ * generic/tkImgPhoto.c Minor simplification in fix for [Bug 2312027]
+ no need to malloc and copy photo type name
+ because it is a constant to begin with.
+ * generic/tkOldConfig.c Convert Tcl_SetResult(......, TCL_DYNAMIC) to
+ * mac/tkMacOSXWm.c Tcl_SetResult(......, TCL_VOLATILE), in
+ * unix/tkUnixWm.c preparation for TIP #340
* unix/tkUnixSend.c
* win/tkWinWm.c
-2008-11-16 Joe English <jenglish@users.sourceforge.net>
-
- * generic/ttk/ttkWidget.c: Widget self-destruction is
- not necessarily an error [Bug 2298720].
+2008-11-16 Joe English <jenglish@users.sourceforge.net>
+
+ * generic/ttk/ttkWidget.c: Widget self-destruction is not necessarily
+ an error. [Bug 2298720]
2008-11-16 Donal K. Fellows <dkf@users.sf.net>
@@ -31,17 +44,17 @@
avoid making unwarranted assumptions about how magical it is.
Triggered by [Bug 2282861] discussion.
-2008-11-14 Pat Thoyts <patthoyts@users.sourceforge.net>
+2008-11-14 Pat Thoyts <patthoyts@users.sourceforge.net>
- * generic/tk.h: The TIP 125 implementation permits the
+ * generic/tk.h: The TIP 125 implementation permits the
* generic/tkFrame.c: [wm manage] command to manage any widget but
* macosx/tkMacOSXWm.c: only those with Frame instance data should be
* unix/tkUnixWm.c: permitted. We now check for the suitability and
* win/tkWinWm.c: raise an error for non-frame widgets. Updated
- * test/wm.test: the tests and documentation. See also [Bug
- * doc/wm.n: 2239034]
+ * test/wm.test: the tests and documentation. See also [Bug
+ * doc/wm.n: 2239034]
-2008-11-12 Joe English <jenglish@users.sourceforge.net>
+2008-11-12 Joe English <jenglish@users.sourceforge.net>
* generic/ttk/ttkWidget.c: Reworked widget construction and
destruction sequence; fixes [Bug 2207435] and several other problems
@@ -50,42 +63,44 @@
initializeProc being called earlier in the construction sequence now.
* tests/ttk/ttk.test: Updated test suite.
-2008-11-12 Pat Thoyts <patthoyts@users.sourceforge.net>
+2008-11-12 Pat Thoyts <patthoyts@users.sourceforge.net>
* library/text.tcl: Handle windows with funky names by avoiding use of
* test/text.test: the window path for anchors. [Bug 1777362]
2008-11-11 Jan Nijtmans <nijtmans@users.sf.net>
- * generic/tkImgPhoto.c Fix [Bug 2265860] new test failures
+ * generic/tkImgPhoto.c Fix [Bug 2265860] new test failures
-2008-11-11 Joe English <jenglish@users.sourceforge.net>
+2008-11-11 Joe English <jenglish@users.sourceforge.net>
* generic/ttk/ttkWidget.c(BeginDrawing): Don't crash when application
uses nondefault visual. [Bug 2264732]
2008-11-11 Jan Nijtmans <nijtmans@users.sf.net>
- * win/tcl.m4: reverted change from 2008-11-06 (was under the impression
- that "-Wno-implicit-int" added an extra warning)
- * win/configure (regenerated)
- * unix/tcl.m4: Use -O2 as gcc optimization compiler flag, and get
- rid of -Wno-implicit-int for UNIX
+ * win/tcl.m4: Reverted change from 2008-11-06 (was under the
+ impression that "-Wno-implicit-int" added an extra
+ warning)
+ * win/configure (regenerated)
+ * unix/tcl.m4: Use -O2 as gcc optimization compiler flag, and get
+ rid of -Wno-implicit-int for UNIX
* unix/configure (regenerated)
- * generic/tk.decls modify Tk_Create(Old)ImageType signature, relaxing
- * generic/tk.h the constraint that every Tk_ImageType can only
- * generic/tkImage.c be passed to this function once. This allows
- * generic/tkImgBmap.c tkImg to be loaded in multiple interpreters
+ * generic/tk.decls Modify Tk_Create(Old)ImageType signature,
+ * generic/tk.h relaxing the constraint that every Tk_ImageType
+ * generic/tkImage.c can only be passed to this function once. This
+ * generic/tkImgBmap.c lets tkImg be loaded in multiple interpreters
* generic/tkImgPhoto.c in a thread-enabled build of Tk. [Bug 2312027]
- * generic/tkTest.c This CONSTification complies with TIP #27. It is
- * doc/CrtImgType.3 binary compatible with the old interface, but not
- fully source compatible (although tkImg does not suffer).
+ * generic/tkTest.c This CONSTification complies with TIP #27. It
+ * doc/CrtImgType.3 is binary compatible with the old interface,
+ but not fully source compatible (although tkImg
+ does not suffer).
* generic/tkDecls.h (regenerated)
*** POTENTIAL INCOMPATIBILITY ***
-2008-11-09 Joe English <jenglish@users.sourceforge.net>
+2008-11-09 Joe English <jenglish@users.sourceforge.net>
* generic/ttk/ttkWidget.c: Remove unnecessary casts.
@@ -101,16 +116,16 @@
2008-11-09 Jan Nijtmans <nijtmans@users.sf.net>
- * generic/tkCanvas.c: Make all Tk_CustomOption tables const and
- * generic/tkCanvBmap.c: remove unnecessary type cast.
+ * generic/tkCanvas.c: Make all Tk_CustomOption tables const and
+ * generic/tkCanvBmap.c: remove unnecessary type cast.
* generic/tkCanvImg.c:
* generic/tkCanvPoly.c:
* generic/tkCanvText.c:
* generic/tkCanvWind.c:
* generic/tkRectOval.c:
* generic/tkScrollbar.c:
- * generic/tk.decls: Two more (hopefully the last) signature
- * generic/tkInt.h: changes in Tk_CreateSmoothMethod and
+ * generic/tk.decls: Two more (hopefully the last) signature
+ * generic/tkInt.h: changes in Tk_CreateSmoothMethod and
* generic/tkCanvLine.c: Tk_CreatePhotoImageFormat
* generic/tkCanvUtil.c:
* generic/tkImgPhoto.c:
@@ -150,10 +165,10 @@
2008-11-03 Jan Nijtmans <nijtmans@users.sf.net>
* generic/ttk/ttkEntry.c: Fix warning: unused variable `currentValue'
- * generic/tkOldTest.c: Fix warning: assignment discards qualifiers
- * win/tkWinTest.c: from pointer target type
+ * generic/tkOldTest.c: Fix warning: assignment discards qualifiers
+ * win/tkWinTest.c: from pointer target type
-2008-11-03 Pat Thoyts <patthoyts@users.sourceforge.net>
+2008-11-03 Pat Thoyts <patthoyts@users.sourceforge.net>
* tests/winClipboard.test: testclipboard no longer returns strings
with embedded \r but now returns Tcl strings
@@ -163,7 +178,7 @@
2008-11-02 Jan Nijtmans <nijtmans@users.sf.net>
- * generic/tkFont.h: More internal -Wwrite-strings warning fixes
+ * generic/tkFont.h: More internal -Wwrite-strings warning fixes
* generic/tkFont.c
* generic/ttk/ttkTheme.h
* generic/ttk/ttkDefaultTheme.c
@@ -182,7 +197,7 @@
whether they support finding and moving individual coordinates.
* doc/canvas.n, tests/canvas.test: Docs 'n' tests.
-2008-11-01 Pat Thoyts <patthoyts@users.sourceforge.net>
+2008-11-01 Pat Thoyts <patthoyts@users.sourceforge.net>
* generic/ttk/ttkEntry.c: Implemented the themed spinbox
* library/ttk/altTheme.tcl: widget.
@@ -199,13 +214,13 @@
* doc/ttk_spinbox.n:
* tests/ttk/spinbox.test:
-2008-10-31 Joe English <jenglish@users.sourceforge.net>
+2008-10-31 Joe English <jenglish@users.sourceforge.net>
* generic/widget.c: Temporary workaround for [Bug 2207435]
2008-10-30 Jan Nijtmans <nijtmans@users.sf.net>
- * generic/tkAtom.c: more internal -Wwrite-strings warning fixes
+ * generic/tkAtom.c: more internal -Wwrite-strings warning fixes
* generic/tkBusy.c
* generic/tkButton.c
* generic/tkCanvPoly.c
@@ -222,26 +237,26 @@
* generic/tkText.c
* generic/tkTextImage.c
-2008-10-30 Don Porter <dgp@users.sourceforge.net>
+2008-10-30 Don Porter <dgp@users.sourceforge.net>
* tests/unixSelect.test: Revise the unixSelect-1.* tests so that
they test the ability of Tk's selection mechanism to faithfully pass
valid Tcl values without corruption, and stop testing details of
- Tcl's internal encoding scheme. With this change, the Tk test suite
+ Tcl's internal encoding scheme. With this change, the Tk test suite
no longer uses the identity encoding or [string bytelength].
2008-10-30 Jan Nijtmans <nijtmans@users.sf.net>
- * generic/tk.h: CONSTify return value of
- * generic/tkInt.h Tk_OptionPrintProc, and customPtr
- * generic/tk.decls field of Tk_ConfigSpec.
- * generic/tkCanvArc.c See [Bug 2190619]: Warnings due to
- * generic/tkCanvLine.c Tk_SmoothMethod name constness change
+ * generic/tk.h: CONSTify return value of
+ * generic/tkInt.h Tk_OptionPrintProc, and customPtr
+ * generic/tk.decls field of Tk_ConfigSpec.
+ * generic/tkCanvArc.c See [Bug 2190619]: Warnings due to
+ * generic/tkCanvLine.c Tk_SmoothMethod name constness change
* generic/tkCanvUtil.c
* generic/tkUtil.c
- * generic/tkDecls.h: (regenerated)
+ * generic/tkDecls.h: (regenerated)
-2008-10-29 Joe English <jenglish@users.sourceforge.net>
+2008-10-29 Joe English <jenglish@users.sourceforge.net>
* generic/tkAtom.c(Tk_GetAtomName): Remove incorrect 'const' qualifier.
Remove useless 'register' declarations too, while we're at it.
@@ -266,7 +281,7 @@
* generic/tkWindow.c:
* win/tkWinTest.c: fix compilation under mingw32
-2008-10-28 Joe English <jenglish@users.sourceforge.net>
+2008-10-28 Joe English <jenglish@users.sourceforge.net>
* library/ttk/cursors.tcl, library/ttk/combobox.tcl,
library/ttk/entry.tcl, library/ttk/paned.tcl, library/ttk/sizegrip.tcl,
@@ -275,27 +290,27 @@
Expanded set of symbolic cursors. Use correct cursor for
ttk::entry and ttk::combobox widgets [Bug 1534835]
-2008-10-28 Don Porter <dgp@users.sourceforge.net>
+2008-10-28 Don Porter <dgp@users.sourceforge.net>
* win/tkWinTest.c: Revise [testclipboard] to form that
* tests/winClipboard.test: handles encodings. [Bug 2191960]
* tests/constraints.tcl: [tcltest::bytestring] no longer used.
-2008-10-24 Joe English <jenglish@users.sourceforge.net>
+2008-10-24 Joe English <jenglish@users.sourceforge.net>
- * tests/ttk/ttk.test: Disable test ttk-6.3, it's not
- applicable [Bug 2175411].
+ * tests/ttk/ttk.test: Disable test ttk-6.3, it's not applicable. [Bug
+ 2175411]
- * generic/ttk/ttkTheme.c: Use different Tcl_AssocData key
- so the tile extension can be loaded into an 8.6 interp,
- in the off-chance that anyone wants to do this.
+ * generic/ttk/ttkTheme.c: Use different Tcl_AssocData key so the tile
+ extension can be loaded into an 8.6 interp, in the off-chance that
+ anyone wants to do this.
2008-10-24 Donal K. Fellows <dkf@users.sf.net>
* generic/tkCanvUtil.c (TkSmoothPrintProc): Corrected 'const'ness to
quell warning. [Bug 2190619]
-2008-10-23 Don Porter <dgp@users.sourceforge.net>
+2008-10-23 Don Porter <dgp@users.sourceforge.net>
* README: Bump version number to 8.6a4
* generic/tk.h:
@@ -309,11 +324,11 @@
2008-10-22 Jan Nijtmans <nijtmans@users.sf.net>
- * generic/tk.h: CONST -> const and white-spacing
+ * generic/tk.h: CONST -> const and white-spacing
* generic/tk.decls
* generic/tkInt.decls
- * generic/tkDecls.h: (regenerated)
- * generic/tkIntDecls.h: (regenerated)
+ * generic/tkDecls.h: (regenerated)
+ * generic/tkIntDecls.h: (regenerated)
* generic/tkIntPlatDecls.h: (regenerated)
* generic/tkIntXlibDecls.h: (regenerated)
* generic/tkPlatDecls.h: (regenerated)
@@ -334,7 +349,7 @@
* generic/tkBusy.c, doc/busy.n, tests/busy.test: Implementation of the
[tk busy] command. [Patch 1997907]
-2008-10-18 Pat Thoyts <patthoyts@users.sourceforge.net>
+2008-10-18 Pat Thoyts <patthoyts@users.sourceforge.net>
* win/tkWinFont.c: [Bug 1825353] To fix a problem with tiny fonts on
Russian versions of Windows we will avoid removing the internal
@@ -342,10 +357,10 @@
2008-10-15 Jan Nijtmans <nijtmans@users.sf.net>
- * generic/tk.h: Add "const" to many internal const tables, so
- * generic/tkBind.c: those will be put by the C-compiler in the
- * generic/tkButton.c: TEXT segment instead of the DATA segment.
- * generic/tkCanvas.c: This makes those tables as being shareable in
+ * generic/tk.h: Add "const" to many internal const tables, so
+ * generic/tkBind.c: those will be put by the C-compiler in the
+ * generic/tkButton.c: TEXT segment instead of the DATA segment.
+ * generic/tkCanvas.c: This makes those tables as being shareable in
* generic/tkClipboard.c: shared libraries.
* generic/tkCmds.c:
* generic/tkConsole.c:
@@ -390,17 +405,17 @@
* win/tkWinWm.c:
* xlib/xcolors.c:
-2008-10-17 Pat Thoyts <patthoyts@users.sourceforge.net>
+2008-10-17 Pat Thoyts <patthoyts@users.sourceforge.net>
* library/ttk/scale.tcl: Implemented keyboard bindings for ttk::scale
2008-10-15 Jan Nijtmans <nijtmans@users.sf.net>
- * generic/tkInt.h: Add "const" to many internal const tables, so
- * generic/tk3d.c: those will be put by the C-compiler in the
- * generic/tkBitmap.c: TEXT segment instead of the DATA segment.
- * generic/tkColor.c: This makes those tables as being shareable in
- * generic/tkConfig.c: shared libraries.
+ * generic/tkInt.h: Add "const" to many internal const tables, so
+ * generic/tk3d.c: those will be put by the C-compiler in the
+ * generic/tkBitmap.c: TEXT segment instead of the DATA segment.
+ * generic/tkColor.c: This makes those tables as being shareable in
+ * generic/tkConfig.c: shared libraries.
* generic/tkCursor.c:
* generic/tkFont.c:
* generic/tkObj.c:
@@ -418,13 +433,13 @@
* generic/tkCanvas.c (CanvasWidgetCmd): Corrected result generation.
-2008-10-10 Don Porter <dgp@users.sourceforge.net>
+2008-10-10 Don Porter <dgp@users.sourceforge.net>
*** 8.6a3 TAGGED FOR RELEASE ***
* changes: Updates for 8.6a3 release.
-2008-10-09 Don Porter <dgp@users.sourceforge.net>
+2008-10-09 Don Porter <dgp@users.sourceforge.net>
* generic/tkListbox.c: Make literal return values consistent with
those generated by Tcl_PrintDouble().
@@ -438,7 +453,7 @@
* unix/tcl.m4: Fix for bug [2073255]
* unix/configure: regenerated
-2008-10-08 Don Porter <dgp@users.sourceforge.net>
+2008-10-08 Don Porter <dgp@users.sourceforge.net>
* tests/textDisp.test (textDisp-16.34): Update test that tested string
equality of double values based on an assumption of tcl_precision==12.
@@ -454,9 +469,9 @@
* unix/tkUnixWm.c: Restored consistency of error messages from
* macosx/tkMacOSXWm.c: [wm iconphoto] with the test suite and across
- * tests/unixWm.test: all platforms. [Bug 2021443]
+ * tests/unixWm.test: all platforms. [Bug 2021443]
-2008-10-07 Pat Thoyts <patthoyts@users.sourceforge.net>
+2008-10-07 Pat Thoyts <patthoyts@users.sourceforge.net>
* tests/canvImg.test: Removed dependency on precision in results
* tests/canvRect.test:
@@ -468,7 +483,7 @@
* tests/winWm.test: Fixed incorrect error strings
* tests/wm.test:
-2008-10-06 Pat Thoyts <patthoyts@users.sourceforge.net>
+2008-10-06 Pat Thoyts <patthoyts@users.sourceforge.net>
* tests/winDialog.test: Fixed tests for Vista+
* win/tkWinWm.c: corrected some errors from the previous commit
@@ -538,7 +553,7 @@
* doc/menu.n: Fix typo in docs. [Bug 2098425]
-2008-09-03 Don Porter <dgp@users.sourceforge.net>
+2008-09-03 Don Porter <dgp@users.sourceforge.net>
* generic/tk.h: Dropped use of _ANSI_ARGS_ macro to preserve
* generic/tkSelect.h: Tk's TCL_NO_DEPRECATED build.
@@ -559,9 +574,9 @@
* tests/winMsbox.test:
* tests/winWm.test:
-2008-08-28 Don Porter <dgp@users.sourceforge.net>
+2008-08-28 Don Porter <dgp@users.sourceforge.net>
- * unix/tkConfig.sh.in: Added @XFT_LIBS@ to the definition of TK_LIBS
+ * unix/tkConfig.sh.in: Added @XFT_LIBS@ to the definition of TK_LIBS
to avoid link failures when a "big wish" program links against a
--disable-shared build of libtk. (Discovered building expectTk.)
@@ -636,7 +651,7 @@
the interaction with the script level) and the photo instances (which
handle display).
-2008-08-22 Don Porter <dgp@users.sourceforge.net>
+2008-08-22 Don Porter <dgp@users.sourceforge.net>
*** 8.6a2 TAGGED FOR RELEASE ***
@@ -682,7 +697,7 @@
* win/tkWinWindow.c: Remove TkpWindowWasRecentlyDeleted.
* tests/id.test: Remove this unnecessary test.
-2008-08-19 Joe English <jenglish@users.sourceforge.net>
+2008-08-19 Joe English <jenglish@users.sourceforge.net>
* generic/ttk/ttkScroll.c: Don't use sprintf "%g" to format floating
point numbers in -[xy]scrollcommand callbacks or [xy]view methods.
@@ -738,7 +753,7 @@
* unix/tcl.m4 (SC_PATH_X): Check for libX11.dylib in addition to
libX11.so et al.
- * unix/configure: autoconf-2.59
+ * unix/configure: autoconf-2.59
2008-08-12 Ania Pawelczyk <aniap@users.sourceforge.net>
@@ -747,7 +762,7 @@
* tests/embed.test:
* tests/main.test:
-2008-08-12 Don Porter <dgp@users.sourceforge.net>
+2008-08-12 Don Porter <dgp@users.sourceforge.net>
* README: Bump version number to 8.6a2
* generic/tk.h:
@@ -774,7 +789,7 @@
* tests/config.test:
* tests/canvas.test:
-2008-08-05 Joe English <jenglish@users.sourceforge.net>
+2008-08-05 Joe English <jenglish@users.sourceforge.net>
* generic/tk.h, generic/tkEvent.c: Fix for [Bug 2010422] "no event
type or button # or keysym while executing "bind Listbox
@@ -787,12 +802,12 @@
* tests/get.test:
* tests/text.test: Update to tcltest2; report: 33.11 fails
-2008-08-01 Pat Thoyts <patthoyts@users.sourceforge.net>
+2008-08-01 Pat Thoyts <patthoyts@users.sourceforge.net>
* win/tkWinWm.c: Check wmPtr is valid in TopLevelReqProc to fix
* tests/wm.test: [Bug 2028703]
-2008-07-31 Don Porter <dgp@users.sourceforge.net>
+2008-07-31 Don Porter <dgp@users.sourceforge.net>
* generic/tk.h: Added missing EXTERN for the Tcl_PkgInitStubsCheck
declaration to fix inability to embed non-stub-enabled Tk on Windows.
@@ -807,12 +822,12 @@
* tests/cursor.test: Update to tcltest2
* tests/message.test:
-2008-07-26 Pat Thoyts <patthoyts@users.sourceforge.net>
+2008-07-26 Pat Thoyts <patthoyts@users.sourceforge.net>
* doc/options.n: Direct to the font manual for -font. [Bug 1686012]
* tests/constraints.tcl: Add a nonwin contraint.
- * tests/listbox.test: Conform to testing policy. [Bug 2024753]
+ * tests/listbox.test: Conform to testing policy. [Bug 2024753]
* win/tkWinWm.c: Check that the parent has been mapped before
* tests/wm.test: calling RemapWindows. [Bug 2009788]
@@ -849,11 +864,11 @@
* macosx/tkMacOSXHLEvents.c: Factor out common code; formatting.
-2008-07-08 Pat Thoyts <patthoyts@users.sourceforge.net>
+2008-07-08 Pat Thoyts <patthoyts@users.sourceforge.net>
* doc/*.n: Fixed broken line endings from last doc commit.
-2008-07-04 Joe English <jenglish@users.sourceforge.net>
+2008-07-04 Joe English <jenglish@users.sourceforge.net>
* generic/ttk/ttkDefaultTheme.c, generic/ttk/ttkClamTheme.c,
* generic/ttk/ttkClassicTheme.c, generic/ttk/ttkElements.c: Audit:
@@ -870,18 +885,18 @@
* doc/*.1, doc/*.3, doc/*.n: Remove out of date changebars, make
formatting of typedefs consistent, other small changes.
-2008-06-25 Don Porter <dgp@users.sourceforge.net>
+2008-06-25 Don Porter <dgp@users.sourceforge.net>
*** 8.6a1 TAGGED FOR RELEASE ***
* changes: Updates for 8.6a1 release.
-2008-06-24 Pat Thoyts <patthoyts@users.sourceforge.net>
+2008-06-24 Pat Thoyts <patthoyts@users.sourceforge.net>
* library/demos/ttkpane.tcl: Work around missing timezones
* doc/text.n: Fix documentation of text tag options. [Bug 1997293]
-2008-06-19 Don Porter <dgp@users.sourceforge.net>
+2008-06-19 Don Porter <dgp@users.sourceforge.net>
* changes: Updates for 8.6a1 release.
@@ -925,7 +940,7 @@
incorrect conversion to points of font sizes already in points; factor
out retrieval of font family name from font family ID.
-2008-06-13 Jeff Hobbs <jeffh@ActiveState.com>
+2008-06-13 Jeff Hobbs <jeffh@ActiveState.com>
* win/configure, win/configure.in (TK_WIN_VERSION): Fix handling of
interim a/b versioning for manifest usage.
@@ -962,7 +977,7 @@
* macosx/Wish.xcode/default.pbxuser:
* macosx/README: Document new build configs.
-2008-06-10 Joe English <jenglish@users.sourceforge.net>
+2008-06-10 Joe English <jenglish@users.sourceforge.net>
* unix/tkUnixKey.c: Use Xutf8LookupString if available. This should
fix problems (like [Bug 1908443]) where Xlib's idea of the system
@@ -974,12 +989,12 @@
* macosx/README: debug configs with gcov;
update to Xcode 3.1.
-2008-05-27 Pat Thoyts <patthoyts@users.sourceforge.net>
+2008-05-27 Pat Thoyts <patthoyts@users.sourceforge.net>
* generic/ttk/ttkTheme.c: [ttk::style theme use] without an argument
* doc/ttk_style.n: now returns the current theme.
-2008-05-23 Joe English <jenglish@users.sourceforge.net>
+2008-05-23 Joe English <jenglish@users.sourceforge.net>
* doc/ttk_treeview.n, generic/ttk/ttkTreeview.c,
* generic/ttk/ttkTagSet.c, generic/ttk/ttkLayout.c,
@@ -997,16 +1012,16 @@
Don't need separate 'Item', 'Cell', and 'Row' style settings anymore,
only the base "Treeview" style is used.
-2008-05-23 Joe English <jenglish@users.sourceforge.net>
+2008-05-23 Joe English <jenglish@users.sourceforge.net>
* generic/ttk/ttkLabel.c: Avoid passing width or height <= 0 to
Tk_RedrawImage, as this leads to a panic on Windows. [Bug 1967576]
-2008-05-16 Pat Thoyts <patthoyts@users.sourceforge.net>
+2008-05-16 Pat Thoyts <patthoyts@users.sourceforge.net>
* library/ttk/xpTheme.tcl: Add correct border to combobox on Vista
-2008-05-15 Pat Thoyts <patthoyts@users.sourceforge.net>
+2008-05-15 Pat Thoyts <patthoyts@users.sourceforge.net>
* win/makefile.vc: We should use the thread allocator for threaded
* win/rules.vc: builds. Added 'tclalloc' option to disable.
@@ -1017,22 +1032,22 @@
(DisplayPanedWindow): Ensure that a zero width never gets fed to the
underlying window system. [Bug 1639824]
-2008-05-13 Pat Thoyts <patthoyts@users.sourceforge.net>
+2008-05-13 Pat Thoyts <patthoyts@users.sourceforge.net>
* library/console.tcl: Support pixel sized font in +/- keybinding.
* tests/listbox.test: -activestyle default is underline on windows.
* tests/winDialog.test: Fixed hanging tk_chooseColor tests.
-2008-05-11 Pat Thoyts <patthoyts@users.sourceforge.net>
+2008-05-11 Pat Thoyts <patthoyts@users.sourceforge.net>
* library/tk.tcl: Support for ttk widgets in AmpWidget
* doc/button.n: Note negative widths for button. [Patch 1883418]
-2008-05-09 Pat Thoyts <patthoyts@users.sourceforge.net>
+2008-05-09 Pat Thoyts <patthoyts@users.sourceforge.net>
* doc/ttk_*: 'identify' widget command is on all ttk widgets.
-2008-05-04 Joe English <jenglish@users.sourceforge.net>
+2008-05-04 Joe English <jenglish@users.sourceforge.net>
* macosx/ttkMacOSAquaTheme.c: "default" and "focus" adornments should
not be disjoint [Bug 1942785]
@@ -1045,12 +1060,12 @@
files allow building things that link against Tcl with really ancient
compilers still; the requirement is just when building Tcl itself.)
-2008-04-25 Joe English <jenglish@users.sourceforge.net>
+2008-04-25 Joe English <jenglish@users.sourceforge.net>
* library/ttk/treeview.tcl: BUGFIX: [$tv selection] takes a list of
items, not a single item. [Bug 1951733]
-2008-04-20 Pat Thoyts <patthoyts@users.sourceforge.net>
+2008-04-20 Pat Thoyts <patthoyts@users.sourceforge.net>
* win/makefile.vc: Include ws2_32 in the link list. [Bug 1900872]
* doc/menu.n: Minor change regarding the system menu. [Bug 1887169]
@@ -1061,7 +1076,7 @@
* doc/text.n: Correct description of when -relief option is ignored on
a tag. Thanks to emiliano for spotting.
-2008-04-17 Don Porter <dgp@users.sourceforge.net>
+2008-04-17 Don Porter <dgp@users.sourceforge.net>
* generic/tkCanvas.c: Fix logic that determines when canvas item
<Enter> event should fire. Thanks to Sebastian Wangnick. [Bug 1327482]
@@ -1072,7 +1087,7 @@
* generic/tkWindow.c (Initialize): and export only a module-scope
pointer to to the main stubs table (for package init). [Patch 1938497]
-2008-04-14 Pat Thoyts <patthoyts@users.sourceforge.net>
+2008-04-14 Pat Thoyts <patthoyts@users.sourceforge.net>
* win/tkWinDialog.c: Fix [tk_chooseColor -title]. [Bug 1941740]
* win/tkWinTest.c: Added parent to testgetwininfo
@@ -1082,9 +1097,9 @@
* generic/tkImgGIF.c: Let the GIF writer use a real LZW compressor.
-2008-04-08 Pat Thoyts <patthoyts@users.sourceforge.net>
+2008-04-08 Pat Thoyts <patthoyts@users.sourceforge.net>
- * win/ttkWinXpTheme.c: Provide a visual-styles API element engine
+ * win/ttkWinXpTheme.c: Provide a visual-styles API element engine
* tests/ttk/vsapi.test: to permit scripts to create any available
* doc/ttk_vsapi.n: windows xp/vista element. Plus basic tests.
@@ -1096,27 +1111,27 @@
* generic/tkIntXlibDecls.h:
* generic/tkPlatDecls.h:
-2008-04-08 Kevin Kenny <kennykb@acm.org>
+2008-04-08 Kevin Kenny <kennykb@acm.org>
- * tkWinEmbed.c: Removed #if 0 code. Trust the revision control
+ * tkWinEmbed.c: Removed #if 0 code. Trust the revision control
system, if you need it again, you can find it.
- * tkWinSend.c: Added conditional compilation to silence several
+ * tkWinSend.c: Added conditional compilation to silence several
compiler warnings.
-2008-04-07 Jeff Hobbs <jeffh@ActiveState.com>
+2008-04-07 Jeff Hobbs <jeffh@ActiveState.com>
* generic/tkWindow.c (Initialize): Fix double-free on Tk_ParseArgv
* tests/main.test (main-3.*): error. [Bug 1937135]
* generic/tkArgv.c: Fix -help mem explosion. [Bug 1936238] (kenny)
-2008-04-04 Pat Thoyts <patthoyts@users.sourceforge.net>
+2008-04-04 Pat Thoyts <patthoyts@users.sourceforge.net>
* library/ttk/sizegrip.tcl: Don't resize if the toplevel is not
resizable or the sizegrip has been disabled.
-2008-04-03 Pat Thoyts <patthoyts@users.sourceforge.net>
+2008-04-03 Pat Thoyts <patthoyts@users.sourceforge.net>
* win/makefile.vc: Fixed stubs usage
* library/ttk/xpTheme.tcl: fix the colour of labelframe in xp
@@ -1146,7 +1161,7 @@
* unix/configure: autoconf-2.59
-2008-04-01 Don Porter <dgp@users.sourceforge.net>
+2008-04-01 Don Porter <dgp@users.sourceforge.net>
* generic/tkStubLib.c (Tk_InitStubs): Added missing error
* generic/tkWindow.c (Tk_PkgInitStubsCheck): message and removed
@@ -1181,7 +1196,7 @@
* generic/tkIntXlibDecls.h:
* generic/tkPlatDecls.h:
-2008-03-28 Don Porter <dgp@users.sourceforge.net>
+2008-03-28 Don Porter <dgp@users.sourceforge.net>
*** 8.5.2 TAGGED FOR RELEASE ***
@@ -1197,7 +1212,7 @@
* changes: Updates for 8.5.2 release.
-2008-03-27 Jeff Hobbs <jeffh@ActiveState.com>
+2008-03-27 Jeff Hobbs <jeffh@ActiveState.com>
* library/safetk.tcl (::safe::tkInterpInit): Make sure tk_library and
its subdirs (eg, ttk) are on the "safe" access path.
@@ -1216,20 +1231,20 @@
* generic/ttk/ttkDecls.h: Fix incorrect number of arguments in
Ttk_InitStubs macro definition.
-2008-03-26 Don Porter <dgp@users.sourceforge.net>
+2008-03-26 Don Porter <dgp@users.sourceforge.net>
* changes: Updates for 8.5.2 release.
* unix/tkUnixCursor.c: Stop crash in [. configure -cursor] on X11.
Thanks to emiliano gavilán. [Bug 1922466]
-2008-03-26 Joe English <jenglish@users.sourceforge.net>
+2008-03-26 Joe English <jenglish@users.sourceforge.net>
* generic/tkInt.h, generic/tkEvent.c, unix/tkUnixEvent.c,
* unix/tkUnixKey.c: XIM reorganization and cleanup; see
[Patch 1919791] for details.
-2008-03-21 Joe English <jenglish@users.sourceforge.net>
+2008-03-21 Joe English <jenglish@users.sourceforge.net>
* generic/tk.decls, generic/ttk/ttkStubLib.c, unix/Makefile.in: Keep
ttkStubLib.o in libtkstub instead of libtk. [Bug 1920030]
@@ -1244,7 +1259,7 @@
* doc/GetClrmap.3: Documented Tk_PreserveColormap. [Bug 220809]
-2008-03-17 Joe English <jenglish@users.sourceforge.net>
+2008-03-17 Joe English <jenglish@users.sourceforge.net>
* unix/Makefile.in, win/Makefile.in, win/makefile.vc: Put ttkStubLib.o
in libtkstub instead of libtk. [Bug 1863007]
@@ -1260,7 +1275,7 @@
* unix/tcl.m4: for lib paths in tkConfig.sh. [Bug 1913622]
* unix/configure: autoconf-2.59
-2008-03-13 Don Porter <dgp@users.sourceforge.net>
+2008-03-13 Don Porter <dgp@users.sourceforge.net>
* changes: Updates for 8.5.2 release.
@@ -1270,7 +1285,7 @@
* macosx/Wish.xcodeproj/default.pbxuser: CODE_SIGN_IDENTITY and
* macosx/Wish-Common.xcconfig: 'xcodebuild install'.
-2008-03-12 Joe English <jenglish@users.sourceforge.net>
+2008-03-12 Joe English <jenglish@users.sourceforge.net>
* unix/tkUnixRFont.c: Try a fallback font if XftFontOpenPattern()
fails in GetFont (workaround for [Bug 1090382]).
@@ -1298,7 +1313,7 @@
* unix/Makefile.in (install-strip): Strip non-global symbols from
dynamic library.
-2008-03-10 Don Porter <dgp@users.sourceforge.net>
+2008-03-10 Don Porter <dgp@users.sourceforge.net>
* changes: Updates for 8.5.2 release.
@@ -1306,14 +1321,14 @@
* doc/colors.n: Reworked to produce nicer HTML output.
-2008-03-06 Joe English <jenglish@users.sourceforge.net>
+2008-03-06 Joe English <jenglish@users.sourceforge.net>
* doc/ttk_notebook.n: Move "TAB IDENTIFIERS" section above "WIDGET
COMMAND" section. [Bug 1882011]
-2008-02-29 Pat Thoyts <patthoyts@users.sourceforge.net>
+2008-02-29 Pat Thoyts <patthoyts@users.sourceforge.net>
- * library/demos/widget: Added a Knight's tour canvas demo.
+ * library/demos/widget: Added a Knight's tour canvas demo.
* library/demos/knightstour.tcl:
2008-02-27 Daniel Steffen <das@users.sourceforge.net>
@@ -1321,14 +1336,14 @@
* macosx/tkMacOSXDraw.c: Workaround leak in Carbon SetPortPenPixPat()
API [Bug 1863346]; avoid repeated PixPat allocation/deallocation.
-2008-02-23 Joe English <jenglish@users.sourceforge.net>
+2008-02-23 Joe English <jenglish@users.sourceforge.net>
* library/ttk/combobox.tcl, doc/ttk_combobox.n,
* tests/ttk/combobox.test: Arrange to deliver <<ComboboxSelected>>
event after listbox is unposted, as intended [Bug 1890211]. Clarified
documentation.
-2008-02-23 Joe English <jenglish@users.sourceforge.net>
+2008-02-23 Joe English <jenglish@users.sourceforge.net>
* generic/ttk/ttkPanedWindow.c: Don't enforce minimum sash thickness
of 5 pixels, just use 5 as a default. [FR 1898288]
@@ -1341,7 +1356,7 @@
* doc/ttk_scale.n (new file): Added basic documentation. [Bug 1881925]
-2008-02-04 Don Porter <dgp@users.sourceforge.net>
+2008-02-04 Don Porter <dgp@users.sourceforge.net>
*** 8.5.1 TAGGED FOR RELEASE ***
@@ -1362,14 +1377,14 @@
2008-02-02 Daniel Steffen <das@users.sourceforge.net>
* macosx/Wish-Info.plist.in: Add CFBundleLocalizations key, listing
- * unix/configure.in (Darwin): all library/msgs locales.
+ * unix/configure.in (Darwin): all library/msgs locales.
* unix/configure.in (Darwin): Correct Info.plist year substitution
in non-framework builds.
* unix/configure: autoconf-2.59
-2008-02-01 Don Porter <dgp@users.sourceforge.net>
+2008-02-01 Don Porter <dgp@users.sourceforge.net>
* changes: Updates for 8.5.1 release.
@@ -1378,7 +1393,7 @@
* generic/tkImgGIF.c: Fixed a buffer overflow (CVE-2008-0553).
* tests/imgPhoto.test: Added a test for the above.
-2008-01-31 Jeff Hobbs <jeffh@ActiveState.com>
+2008-01-31 Jeff Hobbs <jeffh@ActiveState.com>
* library/msgbox.tcl (::tk::MessageBox): Don't use ttk::label in low
depth/aqua fallback, as it doesn't support -bitmap.
@@ -1396,7 +1411,7 @@
* doc/canvas.n, doc/listbox.n, doc/message.n: Fix erroneous listing of
"standard" options. [Bug 1882495]
-2008-01-29 Joe English <jenglish@users.sourceforge.net>
+2008-01-29 Joe English <jenglish@users.sourceforge.net>
* library/treeview.tcl: Fix bug in Shift-ButtonPress-1 binding (error
if no current focus item; reported on c.l.t.)
@@ -1407,17 +1422,17 @@
Ttk manual pages so that they are documented in the correct location.
[Bug 1876493]
-2008-01-28 Joe English <jenglish@users.sourceforge.net>
+2008-01-28 Joe English <jenglish@users.sourceforge.net>
* unix/tkUnixRFont.c: Re-fix strict-aliasing warnings reintroduced by
last patch.
-2008-01-27 Joe English <jenglish@users.sourceforge.net>
+2008-01-27 Joe English <jenglish@users.sourceforge.net>
* generic/ttk/ttkNotebook.c: Make sure to schedule a redisplay when
adding and/or hiding tabs. [Bug 1878298]
-2008-01-27 Joe English <jenglish@users.sourceforge.net>
+2008-01-27 Joe English <jenglish@users.sourceforge.net>
* unix/tkUnixRFont.c: Merged common code from InitFont() and
TkpGetFontAttrsForChar(), factored into GetTkFontAttributes() and
@@ -1426,33 +1441,33 @@
TkFontAttributes.family member is a Tk_Uid, as specified. Use
FcTypeDouble for XFT_SIZE attribute. Finally: fix [Bug 1835848]
-2008-01-25 Don Porter <dgp@users.sourceforge.net>
+2008-01-25 Don Porter <dgp@users.sourceforge.net>
* changes: Updates for 8.5.1 release.
-2008-01-08 Joe English <jenglish@users.sourceforge.net>
+2008-01-08 Joe English <jenglish@users.sourceforge.net>
* generic/ttk/ttkFrame.c: BUGFIX: fix crash in [ttk::labelframe] when
-style option specified. [Bug 1867122]
-2008-01-08 Joe English <jenglish@users.sourceforge.net>
+2008-01-08 Joe English <jenglish@users.sourceforge.net>
* win/ttkWinTheme.c: Add tristate support to checkbuttons and
radiobuttons. [Bug 1865898]
Fix check and radio indicator size. [Bug 1679067]
-2008-01-06 Joe English <jenglish@users.sourceforge.net>
+2008-01-06 Joe English <jenglish@users.sourceforge.net>
* generic/ttk/ttkWidget.c, generic/ttk/ttkWidget.h: Call
Tk_MakeWindowExist() in widget constructor. Removed now-unnecessary
initial ConfigureNotify processing.
-2008-01-06 Joe English <jenglish@users.sourceforge.net>
+2008-01-06 Joe English <jenglish@users.sourceforge.net>
* library/ttk/treeview.tcl, library/ttk/utils.tcl: Fix MouseWheel
bindings for ttk::treeview widget. [Bugs 1442006, 1821939, 1862692]
-2008-01-02 Don Porter <dgp@users.sourceforge.net>
+2008-01-02 Don Porter <dgp@users.sourceforge.net>
* generic/tk.h: Bump version number to 8.5.1b1 to distinguish
* library/tk.tcl: CVS development snapshots from the 8.5.0 and
diff --git a/generic/tkCanvText.c b/generic/tkCanvText.c
index efa2b70..474ed25 100644
--- a/generic/tkCanvText.c
+++ b/generic/tkCanvText.c
@@ -9,7 +9,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkCanvText.c,v 1.32 2008/11/09 20:51:28 nijtmans Exp $
+ * RCS: @(#) $Id: tkCanvText.c,v 1.33 2008/11/22 18:08:51 dkf Exp $
*/
#include <stdio.h>
@@ -57,6 +57,8 @@ typedef struct TextItem {
* means no word-wrap. */
int underline; /* Index of character to put underline beneath
* or -1 for no underlining. */
+ double angle; /* What angle, in degrees, to draw the text
+ * at. */
/*
* Fields whose values are derived from the current values of the
@@ -66,18 +68,18 @@ typedef struct TextItem {
int numChars; /* Length of text in characters. */
int numBytes; /* Length of text in bytes. */
Tk_TextLayout textLayout; /* Cached text layout information. */
- int leftEdge; /* Pixel location of the left edge of the text
- * item; where the left border of the text
- * layout is drawn. */
- int rightEdge; /* Pixel just to right of right edge of area
- * of text item. Used for selecting up to end
- * of line. */
+ int actualWidth; /* Width of text as computed. Used to make
+ * selections of wrapped text display
+ * right. */
+ double drawOrigin[2]; /* Where we start drawing from. */
GC gc; /* Graphics context for drawing text. */
GC selTextGC; /* Graphics context for selected text. */
GC cursorOffGC; /* If not None, this gives a graphics context
* to use to draw the insertion cursor when
* it's off. Used if the selection and
* insertion cursor colors are the same. */
+ double sine; /* Sine of angle field. */
+ double cosine; /* Cosine of angle field. */
} TextItem;
/*
@@ -101,6 +103,8 @@ static Tk_ConfigSpec configSpecs[] = {
NULL, Tk_Offset(TextItem, activeStipple), TK_CONFIG_NULL_OK},
{TK_CONFIG_ANCHOR, "-anchor", NULL, NULL,
"center", Tk_Offset(TextItem, anchor), TK_CONFIG_DONT_SET_DEFAULT},
+ {TK_CONFIG_DOUBLE, "-angle", NULL, NULL,
+ "0.0", Tk_Offset(TextItem, angle), TK_CONFIG_DONT_SET_DEFAULT},
{TK_CONFIG_COLOR, "-disabledfill", NULL, NULL,
NULL, Tk_Offset(TextItem, disabledColor), TK_CONFIG_NULL_OK},
{TK_CONFIG_BITMAP, "-disabledstipple", NULL, NULL,
@@ -199,6 +203,8 @@ Tk_ItemType tkTextType = {
TextDeleteChars, /* dTextProc */
NULL, /* nextPtr */
};
+
+#define ROUND(d) ((int) floor((d) + 0.5))
/*
*--------------------------------------------------------------
@@ -258,15 +264,18 @@ CreateText(
textPtr->text = NULL;
textPtr->width = 0;
textPtr->underline = -1;
+ textPtr->angle = 0.0;
textPtr->numChars = 0;
textPtr->numBytes = 0;
textPtr->textLayout = NULL;
- textPtr->leftEdge = 0;
- textPtr->rightEdge = 0;
+ textPtr->actualWidth = 0;
+ textPtr->drawOrigin[0] = textPtr->drawOrigin[1] = 0.0;
textPtr->gc = None;
textPtr->selTextGC = None;
textPtr->cursorOffGC = None;
+ textPtr->sine = 0.0;
+ textPtr->cosine = 1.0;
/*
* Process the arguments to fill in the item record. Only 1 (list) or 2 (x
@@ -325,14 +334,14 @@ TextCoords(
if (objc == 0) {
Tcl_Obj *obj = Tcl_NewObj();
-
Tcl_Obj *subobj = Tcl_NewDoubleObj(textPtr->x);
+
Tcl_ListObjAppendElement(interp, obj, subobj);
subobj = Tcl_NewDoubleObj(textPtr->y);
Tcl_ListObjAppendElement(interp, obj, subobj);
Tcl_SetObjResult(interp, obj);
} else if (objc < 3) {
- if (objc==1) {
+ if (objc == 1) {
if (Tcl_ListObjGetElements(interp, objv[0], &objc,
(Tcl_Obj ***) &objv) != TCL_OK) {
return TCL_ERROR;
@@ -415,24 +424,24 @@ ConfigureText(
itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;
}
- if(state == TK_STATE_NULL) {
+ if (state == TK_STATE_NULL) {
state = Canvas(canvas)->canvas_state;
}
color = textPtr->color;
stipple = textPtr->stipple;
if (Canvas(canvas)->currentItemPtr == itemPtr) {
- if (textPtr->activeColor!=NULL) {
+ if (textPtr->activeColor != NULL) {
color = textPtr->activeColor;
}
- if (textPtr->activeStipple!=None) {
+ if (textPtr->activeStipple != None) {
stipple = textPtr->activeStipple;
}
- } else if (state==TK_STATE_DISABLED) {
- if (textPtr->disabledColor!=NULL) {
+ } else if (state == TK_STATE_DISABLED) {
+ if (textPtr->disabledColor != NULL) {
color = textPtr->disabledColor;
}
- if (textPtr->disabledStipple!=None) {
+ if (textPtr->disabledStipple != None) {
stipple = textPtr->disabledStipple;
}
}
@@ -513,6 +522,22 @@ ConfigureText(
textPtr->insertPos = textPtr->numChars;
}
+ /*
+ * Restrict so that 0.0 <= angle < 360.0, and then recompute the cached
+ * sine and cosine of the angle. Note that fmod() can produce negative
+ * results, and we try to avoid negative zero as well.
+ */
+
+ textPtr->angle = fmod(textPtr->angle, 360.0);
+ if (textPtr->angle < 0.0) {
+ textPtr->angle += 360.0;
+ }
+ if (textPtr->angle == 0.0) {
+ textPtr->angle = 0.0;
+ }
+ textPtr->sine = sin(textPtr->angle * PI/180.0);
+ textPtr->cosine = cos(textPtr->angle * PI/180.0);
+
ComputeTextBbox(canvas, textPtr);
return TCL_OK;
}
@@ -603,10 +628,11 @@ ComputeTextBbox(
TextItem *textPtr) /* Item whose bbox is to be recomputed. */
{
Tk_CanvasTextInfo *textInfoPtr;
- int leftX, topY, width, height, fudge;
+ int leftX, topY, width, height, fudge, i;
Tk_State state = textPtr->header.state;
+ double x[4], y[4], dx[4], dy[4], sinA, cosA, tmp;
- if(state == TK_STATE_NULL) {
+ if (state == TK_STATE_NULL) {
state = Canvas(canvas)->canvas_state;
}
@@ -624,8 +650,11 @@ ComputeTextBbox(
* bounding box for the text item.
*/
- leftX = (int) floor(textPtr->x + 0.5);
- topY = (int) floor(textPtr->y + 0.5);
+ leftX = ROUND(textPtr->x);
+ topY = ROUND(textPtr->y);
+ for (i=0 ; i<4 ; i++) {
+ dx[i] = dy[i] = 0.0;
+ }
switch (textPtr->anchor) {
case TK_ANCHOR_NW:
case TK_ANCHOR_N:
@@ -636,12 +665,18 @@ ComputeTextBbox(
case TK_ANCHOR_CENTER:
case TK_ANCHOR_E:
topY -= height / 2;
+ for (i=0 ; i<4 ; i++) {
+ dy[i] = -height / 2;
+ }
break;
case TK_ANCHOR_SW:
case TK_ANCHOR_S:
case TK_ANCHOR_SE:
topY -= height;
+ for (i=0 ; i<4 ; i++) {
+ dy[i] = -height;
+ }
break;
}
switch (textPtr->anchor) {
@@ -654,17 +689,27 @@ ComputeTextBbox(
case TK_ANCHOR_CENTER:
case TK_ANCHOR_S:
leftX -= width / 2;
+ for (i=0 ; i<4 ; i++) {
+ dx[i] = -width / 2;
+ }
break;
case TK_ANCHOR_NE:
case TK_ANCHOR_E:
case TK_ANCHOR_SE:
leftX -= width;
+ for (i=0 ; i<4 ; i++) {
+ dx[i] = -width;
+ }
break;
}
- textPtr->leftEdge = leftX;
- textPtr->rightEdge = leftX + width;
+ textPtr->actualWidth = width;
+
+ sinA = textPtr->sine;
+ cosA = textPtr->cosine;
+ textPtr->drawOrigin[0] = textPtr->x + dx[0]*cosA + dy[0]*sinA;
+ textPtr->drawOrigin[1] = textPtr->y + dy[0]*cosA - dx[0]*sinA;
/*
* Last of all, update the bounding box for the item. The item's bounding
@@ -677,10 +722,50 @@ ComputeTextBbox(
if (textInfoPtr->selBorderWidth > fudge) {
fudge = textInfoPtr->selBorderWidth;
}
- textPtr->header.x1 = leftX - fudge;
- textPtr->header.y1 = topY;
- textPtr->header.x2 = leftX + width + fudge;
- textPtr->header.y2 = topY + height;
+
+ /*
+ * Apply the rotation before computing the bounding box.
+ */
+
+ dx[0] -= fudge;
+ dx[1] += width + fudge;
+ dx[2] += width + fudge;
+ dy[2] += height;
+ dx[3] -= fudge;
+ dy[3] += height;
+ for (i=0 ; i<4 ; i++) {
+ x[i] = textPtr->x + dx[i] * cosA + dy[i] * sinA;
+ y[i] = textPtr->y + dy[i] * cosA - dx[i] * sinA;
+ }
+
+ /*
+ * Convert to a rectilinear bounding box.
+ */
+
+ for (i=1,tmp=x[0] ; i<4 ; i++) {
+ if (x[i] < tmp) {
+ tmp = x[i];
+ }
+ }
+ textPtr->header.x1 = ROUND(tmp);
+ for (i=1,tmp=y[0] ; i<4 ; i++) {
+ if (y[i] < tmp) {
+ tmp = y[i];
+ }
+ }
+ textPtr->header.y1 = ROUND(tmp);
+ for (i=1,tmp=x[0] ; i<4 ; i++) {
+ if (x[i] > tmp) {
+ tmp = x[i];
+ }
+ }
+ textPtr->header.x2 = ROUND(tmp);
+ for (i=1,tmp=y[0] ; i<4 ; i++) {
+ if (y[i] > tmp) {
+ tmp = y[i];
+ }
+ }
+ textPtr->header.y2 = ROUND(tmp);
}
/*
@@ -720,16 +805,16 @@ DisplayCanvText(
textPtr = (TextItem *) itemPtr;
textInfoPtr = textPtr->textInfoPtr;
- if(state == TK_STATE_NULL) {
+ if (state == TK_STATE_NULL) {
state = Canvas(canvas)->canvas_state;
}
stipple = textPtr->stipple;
if (Canvas(canvas)->currentItemPtr == itemPtr) {
- if (textPtr->activeStipple!=None) {
+ if (textPtr->activeStipple != None) {
stipple = textPtr->activeStipple;
}
- } else if (state==TK_STATE_DISABLED) {
- if (textPtr->disabledStipple!=None) {
+ } else if (state == TK_STATE_DISABLED) {
+ if (textPtr->disabledStipple != None) {
stipple = textPtr->disabledStipple;
}
}
@@ -750,6 +835,8 @@ DisplayCanvText(
selFirstChar = -1;
selLastChar = 0; /* lint. */
+ Tk_CanvasDrawableCoords(canvas, textPtr->drawOrigin[0],
+ textPtr->drawOrigin[1], &drawableX, &drawableY);
if (textInfoPtr->selItemPtr == itemPtr) {
selFirstChar = textInfoPtr->selectFirst;
@@ -780,20 +867,30 @@ DisplayCanvText(
x = xFirst;
height = hFirst;
for (y = yFirst ; y <= yLast; y += height) {
+ int dx1, dy1, dx2, dy2;
+ double s = textPtr->sine, c = textPtr->cosine;
+ XPoint points[4];
+
if (y == yLast) {
width = xLast + wLast - x;
} else {
- width = textPtr->rightEdge - textPtr->leftEdge - x;
+ width = textPtr->actualWidth - x;
}
- Tk_CanvasDrawableCoords(canvas,
- (double) (textPtr->leftEdge + x
- - textInfoPtr->selBorderWidth),
- (double) (textPtr->header.y1 + y),
- &drawableX, &drawableY);
- Tk_Fill3DRectangle(Tk_CanvasTkwin(canvas), drawable,
- textInfoPtr->selBorder, drawableX, drawableY,
- width + 2 * textInfoPtr->selBorderWidth,
- height, textInfoPtr->selBorderWidth, TK_RELIEF_RAISED);
+ dx1 = x - textInfoPtr->selBorderWidth;
+ dy1 = y;
+ dx2 = width + 2 * textInfoPtr->selBorderWidth;
+ dy2 = height;
+ points[0].x = drawableX + dx1*c + dy1*s;
+ points[0].y = drawableY + dy1*c - dx1*s;
+ points[1].x = drawableX + (dx1+dx2)*c + dy1*s;
+ points[1].y = drawableY + dy1*c - (dx1+dx2)*s;
+ points[2].x = drawableX + (dx1+dx2)*c + (dy1+dy2)*s;
+ points[2].y = drawableY + (dy1+dy2)*c - (dx1+dx2)*s;
+ points[3].x = drawableX + dx1*c + (dy1+dy2)*s;
+ points[3].y = drawableY + (dy1+dy2)*c - dx1*s;
+ Tk_Fill3DPolygon(Tk_CanvasTkwin(canvas), drawable,
+ textInfoPtr->selBorder, points, 4,
+ textInfoPtr->selBorderWidth, TK_RELIEF_RAISED);
x = 0;
}
}
@@ -811,18 +908,28 @@ DisplayCanvText(
if ((textInfoPtr->focusItemPtr == itemPtr) && (textInfoPtr->gotFocus)) {
if (Tk_CharBbox(textPtr->textLayout, textPtr->insertPos,
&x, &y, NULL, &height)) {
- Tk_CanvasDrawableCoords(canvas,
- (double) (textPtr->leftEdge + x
- - (textInfoPtr->insertWidth / 2)),
- (double) (textPtr->header.y1 + y),
- &drawableX, &drawableY);
- Tk_SetCaretPos(Tk_CanvasTkwin(canvas), drawableX, drawableY,
+ int dx1, dy1, dx2, dy2;
+ double s = textPtr->sine, c = textPtr->cosine;
+ XPoint points[4];
+
+ dx1 = x - (textInfoPtr->insertWidth / 2);
+ dy1 = y;
+ dx2 = textInfoPtr->insertWidth;
+ dy2 = height;
+ points[0].x = drawableX + dx1*c + dy1*s;
+ points[0].y = drawableY + dy1*c - dx1*s;
+ points[1].x = drawableX + (dx1+dx2)*c + dy1*s;
+ points[1].y = drawableY + dy1*c - (dx1+dx2)*s;
+ points[2].x = drawableX + (dx1+dx2)*c + (dy1+dy2)*s;
+ points[2].y = drawableY + (dy1+dy2)*c - (dx1+dx2)*s;
+ points[3].x = drawableX + dx1*c + (dy1+dy2)*s;
+ points[3].y = drawableY + (dy1+dy2)*c - dx1*s;
+
+ Tk_SetCaretPos(Tk_CanvasTkwin(canvas), points[0].x, points[0].y,
height);
if (textInfoPtr->cursorOn) {
- Tk_Fill3DRectangle(Tk_CanvasTkwin(canvas), drawable,
- textInfoPtr->insertBorder,
- drawableX, drawableY,
- textInfoPtr->insertWidth, height,
+ Tk_Fill3DPolygon(Tk_CanvasTkwin(canvas), drawable,
+ textInfoPtr->insertBorder, points, 4,
textInfoPtr->insertBorderWidth, TK_RELIEF_RAISED);
} else if (textPtr->cursorOffGC != None) {
/*
@@ -832,10 +939,8 @@ DisplayCanvText(
* where both may be drawn in the same color.
*/
- XFillRectangle(display, drawable, textPtr->cursorOffGC,
- drawableX, drawableY,
- (unsigned) textInfoPtr->insertWidth,
- (unsigned) height);
+ XFillPolygon(display, drawable, textPtr->cursorOffGC,
+ points, 4, Convex, CoordModeOrigin);
}
}
}
@@ -850,23 +955,24 @@ DisplayCanvText(
* anti-aliasing colors would blend together.
*/
- Tk_CanvasDrawableCoords(canvas, (double) textPtr->leftEdge,
- (double) textPtr->header.y1, &drawableX, &drawableY);
-
if ((selFirstChar >= 0) && (textPtr->selTextGC != textPtr->gc)) {
- Tk_DrawTextLayout(display, drawable, textPtr->gc, textPtr->textLayout,
- drawableX, drawableY, 0, selFirstChar);
- Tk_DrawTextLayout(display, drawable, textPtr->selTextGC,
- textPtr->textLayout, drawableX, drawableY, selFirstChar,
- selLastChar + 1);
- Tk_DrawTextLayout(display, drawable, textPtr->gc, textPtr->textLayout,
- drawableX, drawableY, selLastChar + 1, -1);
+ TkDrawAngledTextLayout(display, drawable, textPtr->gc,
+ textPtr->textLayout, drawableX, drawableY, textPtr->angle,
+ 0, selFirstChar);
+ TkDrawAngledTextLayout(display, drawable, textPtr->selTextGC,
+ textPtr->textLayout, drawableX, drawableY, textPtr->angle,
+ selFirstChar, selLastChar + 1);
+ TkDrawAngledTextLayout(display, drawable, textPtr->gc,
+ textPtr->textLayout, drawableX, drawableY, textPtr->angle,
+ selLastChar + 1, -1);
} else {
- Tk_DrawTextLayout(display, drawable, textPtr->gc, textPtr->textLayout,
- drawableX, drawableY, 0, -1);
+ TkDrawAngledTextLayout(display, drawable, textPtr->gc,
+ textPtr->textLayout, drawableX, drawableY, textPtr->angle,
+ 0, -1);
}
- Tk_UnderlineTextLayout(display, drawable, textPtr->gc, textPtr->textLayout,
- drawableX, drawableY, textPtr->underline);
+ TkUnderlineAngledTextLayout(display, drawable, textPtr->gc,
+ textPtr->textLayout, drawableX, drawableY, textPtr->angle,
+ textPtr->underline);
if (stipple != None) {
XSetTSOrigin(display, textPtr->gc, 0, 0);
@@ -1076,15 +1182,17 @@ TextToPoint(
{
TextItem *textPtr;
Tk_State state = itemPtr->state;
- double value;
+ double value, px, py;
if (state == TK_STATE_NULL) {
state = Canvas(canvas)->canvas_state;
}
textPtr = (TextItem *) itemPtr;
+ px = pointPtr[0] - textPtr->drawOrigin[0];
+ py = pointPtr[1] - textPtr->drawOrigin[1];
value = (double) Tk_DistanceToTextLayout(textPtr->textLayout,
- (int) pointPtr[0] - textPtr->leftEdge,
- (int) pointPtr[1] - textPtr->header.y1);
+ (int) px*textPtr->cosine - py*textPtr->sine,
+ (int) py*textPtr->cosine + px*textPtr->sine);
if ((state == TK_STATE_HIDDEN) || (textPtr->color == NULL) ||
(textPtr->text == NULL) || (*textPtr->text == 0)) {
@@ -1128,11 +1236,12 @@ TextToArea(
}
textPtr = (TextItem *) itemPtr;
- return Tk_IntersectTextLayout(textPtr->textLayout,
- (int) (rectPtr[0] + 0.5) - textPtr->leftEdge,
- (int) (rectPtr[1] + 0.5) - textPtr->header.y1,
+ return TkIntersectAngledTextLayout(textPtr->textLayout,
+ (int) (rectPtr[0] + 0.5) - textPtr->drawOrigin[0],
+ (int) (rectPtr[1] + 0.5) - textPtr->drawOrigin[1],
(int) (rectPtr[2] - rectPtr[0] + 0.5),
- (int) (rectPtr[3] - rectPtr[1] + 0.5));
+ (int) (rectPtr[3] - rectPtr[1] + 0.5),
+ textPtr->angle);
}
/*
@@ -1261,7 +1370,7 @@ GetTextIndex(
*indexPtr = textInfoPtr->selectLast;
} else if (c == '@') {
int x, y;
- double tmp;
+ double tmp, c = textPtr->cosine, s = textPtr->sine;
char *end, *p;
p = string+1;
@@ -1276,9 +1385,9 @@ GetTextIndex(
goto badIndex;
}
y = (int) ((tmp < 0) ? tmp - 0.5 : tmp + 0.5);
- *indexPtr = Tk_PointToChar(textPtr->textLayout,
- x + canvasPtr->scrollX1 - textPtr->leftEdge,
- y + canvasPtr->scrollY1 - textPtr->header.y1);
+ x += canvasPtr->scrollX1 - textPtr->drawOrigin[0];
+ y += canvasPtr->scrollY1 - textPtr->drawOrigin[1];
+ *indexPtr = Tk_PointToChar(textPtr->textLayout, x*c-y*s, y*c+x*s);
} else if (Tcl_GetIntFromObj(NULL, obj, indexPtr) == TCL_OK) {
if (*indexPtr < 0) {
*indexPtr = 0;
@@ -1420,10 +1529,9 @@ TextToPostscript(
* being created. */
{
TextItem *textPtr = (TextItem *) itemPtr;
- int x, y;
+ double x, y;
Tk_FontMetrics fm;
const char *justify;
- char buffer[500];
XColor *color;
Pixmap stipple;
Tk_State state = itemPtr->state;
@@ -1437,17 +1545,17 @@ TextToPostscript(
textPtr->text == NULL || *textPtr->text == 0) {
return TCL_OK;
} else if (Canvas(canvas)->currentItemPtr == itemPtr) {
- if (textPtr->activeColor!=NULL) {
+ if (textPtr->activeColor != NULL) {
color = textPtr->activeColor;
}
- if (textPtr->activeStipple!=None) {
+ if (textPtr->activeStipple != None) {
stipple = textPtr->activeStipple;
}
- } else if (state==TK_STATE_DISABLED) {
- if (textPtr->disabledColor!=NULL) {
+ } else if (state == TK_STATE_DISABLED) {
+ if (textPtr->disabledColor != NULL) {
color = textPtr->disabledColor;
}
- if (textPtr->disabledStipple!=None) {
+ if (textPtr->disabledStipple != None) {
stipple = textPtr->disabledStipple;
}
}
@@ -1467,9 +1575,8 @@ TextToPostscript(
Tcl_AppendResult(interp, "} bind def\n", NULL);
}
- sprintf(buffer, "%.15g %.15g [\n", textPtr->x,
- Tk_CanvasPsY(canvas, textPtr->y));
- Tcl_AppendResult(interp, buffer, NULL);
+ Tcl_AppendPrintfToObj(Tcl_GetObjResult(interp), "%.15g %.15g %.15g [\n",
+ textPtr->angle, textPtr->x, Tk_CanvasPsY(canvas, textPtr->y));
Tk_TextLayoutToPostscript(interp, textPtr->textLayout);
@@ -1492,15 +1599,10 @@ TextToPostscript(
}
Tk_GetFontMetrics(textPtr->tkfont, &fm);
- sprintf(buffer, "] %d ", fm.linespace);
- Tcl_AppendResult(interp, buffer, NULL);
- Tcl_PrintDouble(NULL, x / -2.0, buffer);
- Tcl_AppendResult(interp, buffer, " ", NULL);
- Tcl_PrintDouble(NULL, y / 2.0, buffer);
- Tcl_AppendResult(interp, buffer, NULL);
- sprintf(buffer, " %s %s DrawText\n", justify,
+ Tcl_AppendPrintfToObj(Tcl_GetObjResult(interp),
+ "] %d %g %g %s %s DrawText\n",
+ fm.linespace, x / -2.0, y / 2.0, justify,
((stipple == None) ? "false" : "true"));
- Tcl_AppendResult(interp, buffer, NULL);
return TCL_OK;
}
diff --git a/generic/tkFont.c b/generic/tkFont.c
index a0fac74..c3b0e72 100644
--- a/generic/tkFont.c
+++ b/generic/tkFont.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkFont.c,v 1.48 2008/11/02 09:54:02 nijtmans Exp $
+ * RCS: @(#) $Id: tkFont.c,v 1.49 2008/11/22 18:08:51 dkf Exp $
*/
#include "tkInt.h"
@@ -888,7 +888,7 @@ RecomputeWidgets(
Tk_GetClassProc(winPtr->classProcsPtr, worldChangedProc);
if (proc != NULL) {
- (*proc)(winPtr->instanceData);
+ proc(winPtr->instanceData);
}
/*
@@ -1347,7 +1347,7 @@ SetFontFromAny(
Tcl_GetString(objPtr);
typePtr = objPtr->typePtr;
if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
- (*typePtr->freeIntRepProc)(objPtr);
+ typePtr->freeIntRepProc(objPtr);
}
objPtr->typePtr = &tkFontObjType;
objPtr->internalRep.twoPtrValue.ptr1 = NULL;
@@ -2310,6 +2310,69 @@ Tk_DrawTextLayout(
}
}
+void
+TkDrawAngledTextLayout(
+ Display *display, /* Display on which to draw. */
+ Drawable drawable, /* Window or pixmap in which to draw. */
+ GC gc, /* Graphics context to use for drawing text. */
+ Tk_TextLayout layout, /* Layout information, from a previous call to
+ * Tk_ComputeTextLayout(). */
+ int x, int y, /* Upper-left hand corner of rectangle in
+ * which to draw (pixels). */
+ double angle,
+ int firstChar, /* The index of the first character to draw
+ * from the given text item. 0 specfies the
+ * beginning. */
+ int lastChar) /* The index just after the last character to
+ * draw from the given text item. A number < 0
+ * means to draw all characters. */
+{
+ TextLayout *layoutPtr = (TextLayout *) layout;
+ int i, numDisplayChars, drawX;
+ const char *firstByte, *lastByte;
+ LayoutChunk *chunkPtr;
+ double sinA = sin(angle * PI/180.0), cosA = cos(angle * PI/180.0);
+
+ if (layoutPtr == NULL) {
+ return;
+ }
+
+ if (lastChar < 0) {
+ lastChar = 100000000;
+ }
+ chunkPtr = layoutPtr->chunks;
+ for (i = 0; i < layoutPtr->numChunks; i++) {
+ numDisplayChars = chunkPtr->numDisplayChars;
+ if ((numDisplayChars > 0) && (firstChar < numDisplayChars)) {
+ double dx, dy;
+
+ if (firstChar <= 0) {
+ drawX = 0;
+ firstChar = 0;
+ firstByte = chunkPtr->start;
+ } else {
+ firstByte = Tcl_UtfAtIndex(chunkPtr->start, firstChar);
+ Tk_MeasureChars(layoutPtr->tkfont, chunkPtr->start,
+ firstByte - chunkPtr->start, -1, 0, &drawX);
+ }
+ if (lastChar < numDisplayChars) {
+ numDisplayChars = lastChar;
+ }
+ lastByte = Tcl_UtfAtIndex(chunkPtr->start, numDisplayChars);
+ dx = cosA * (chunkPtr->x + drawX) + sinA * (chunkPtr->y);
+ dy = -sinA * (chunkPtr->x + drawX) + cosA * (chunkPtr->y);
+ TkpDrawAngledChars(display, drawable, gc, layoutPtr->tkfont,
+ firstByte, lastByte - firstByte, x+dx, y+dy, angle);
+ }
+ firstChar -= chunkPtr->numChars;
+ lastChar -= chunkPtr->numChars;
+ if (lastChar <= 0) {
+ break;
+ }
+ chunkPtr++;
+ }
+}
+
/*
*---------------------------------------------------------------------------
*
@@ -2358,6 +2421,68 @@ Tk_UnderlineTextLayout(
}
}
+void
+TkUnderlineAngledTextLayout(
+ Display *display, /* Display on which to draw. */
+ Drawable drawable, /* Window or pixmap in which to draw. */
+ GC gc, /* Graphics context to use for drawing text. */
+ Tk_TextLayout layout, /* Layout information, from a previous call to
+ * Tk_ComputeTextLayout(). */
+ int x, int y, /* Upper-left hand corner of rectangle in
+ * which to draw (pixels). */
+ double angle,
+ int underline) /* Index of the single character to underline,
+ * or -1 for no underline. */
+{
+ int xx, yy, width, height;
+
+ if (angle == 0.0) {
+ Tk_UnderlineTextLayout(display, drawable, gc, layout, x,y, underline);
+ return;
+ }
+
+ if ((Tk_CharBbox(layout, underline, &xx, &yy, &width, &height) != 0)
+ && (width != 0)) {
+ TextLayout *layoutPtr = (TextLayout *) layout;
+ TkFont *fontPtr = (TkFont *) layoutPtr->tkfont;
+ double sinA = sin(angle*PI/180), cosA = cos(angle*PI/180);
+ double dy = yy + fontPtr->fm.ascent + fontPtr->underlinePos;
+ XPoint points[5];
+
+ /*
+ * Note that we're careful to only round a double value once, which
+ * minimizes roundoff errors.
+ */
+
+ points[0].x = x + round(xx*cosA + dy*sinA);
+ points[0].y = y + round(dy*cosA - xx*sinA);
+ points[1].x = x + round(xx*cosA + dy*sinA + width*cosA);
+ points[1].y = y + round(dy*cosA - xx*sinA - width*sinA);
+ if (fontPtr->underlineHeight == 1) {
+ /*
+ * Thin underlines look better when rotated when drawn as a line
+ * rather than a rectangle; the rasterizer copes better.
+ */
+
+ XDrawLines(display, drawable, gc, points, 2, CoordModeOrigin);
+ } else {
+ points[2].x = x + round(xx*cosA + dy*sinA + width*cosA
+ - fontPtr->underlineHeight*sinA);
+ points[2].y = y + round(dy*cosA - xx*sinA - width*sinA
+ + fontPtr->underlineHeight*cosA);
+ points[3].x = x + round(xx*cosA + dy*sinA
+ - fontPtr->underlineHeight*sinA);
+ points[3].y = y + round(dy*cosA - xx*sinA
+ + fontPtr->underlineHeight*cosA);
+ points[4].x = points[0].x;
+ points[4].y = points[0].y;
+ XFillPolygon(display, drawable, gc, points, 5, Complex,
+ CoordModeOrigin);
+ XDrawLines(display, drawable, gc, points, 5, CoordModeOrigin);
+ }
+ }
+}
+
/*
*---------------------------------------------------------------------------
*
@@ -2806,6 +2931,263 @@ Tk_IntersectTextLayout(
/*
*---------------------------------------------------------------------------
*
+ * TkIntersectAngledTextLayout --
+ *
+ * Determines whether a text layout that has been turned by an angle
+ * about its top-left coordinae lies entirely inside, entirely outside,
+ * or overlaps a given rectangle. Non-displaying space characters that
+ * occur at the end of individual lines in the text layout are ignored
+ * for intersection calculations.
+ *
+ * Results:
+ * The return value is -1 if the text layout is entirely outside of the
+ * rectangle, 0 if it overlaps, and 1 if it is entirely inside of the
+ * rectangle.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static inline int
+PointInQuadrilateral(
+ double qx[],
+ double qy[],
+ double x,
+ double y)
+{
+ int i;
+
+ for (i=0 ; i<4 ; i++) {
+ double sideDX = qx[(i+1)%4] - qx[i];
+ double sideDY = qy[(i+1)%4] - qy[i];
+ double dx = x - qx[i];
+ double dy = y - qy[i];
+
+ if (sideDX*dy < sideDY*dx) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static inline int
+sign(
+ double value)
+{
+ if (value < 0.0) return -1;
+ if (value > 0.0) return 1;
+ return 0;
+}
+
+static inline int
+SidesIntersect(
+ double ax1, double ay1, double ax2, double ay2,
+ double bx1, double by1, double bx2, double by2)
+{
+#if 0
+/* http://www.freelunchdesign.com/cgi-bin/codwiki.pl?DiscussionTopics/CollideMeUpBaby */
+
+ double a1, b1, c1, a2, b2, c2, r1, r2, r3, r4, denom;
+
+ a1 = ay2 - ay1;
+ b1 = ax1 - ax2;
+ c1 = (ax2 * ay1) - (ax1 * ay2);
+ r3 = (a1 * bx1) + (b1 * by1) + c1;
+ r4 = (a1 * bx2) + (b1 * by2) + c1;
+ if ((r3 != 0.0) && (r4 != 0.0) && (r3*r4 > 0.0)) {
+ return 0;
+ }
+
+ a2 = by2 - by1;
+ b2 = bx1 - bx2;
+ c2 = (bx2 * by1) - (bx1 * by2);
+ r1 = (a2 * ax1) + (b2 * ay1) + c2;
+ r2 = (a2 * ax2) + (b2 * ay2) + c2;
+ if ((r1 != 0.0) && (r2 != 0.0) && (r1*r2 > 0.0)) {
+ return 0;
+ }
+
+ denom = (a1 * b2) - (a2 * b1);
+ return (denom != 0.0);
+#else
+ /*
+ * A more efficient version. Two line segments intersect if, when seen
+ * from the perspective of one line, the two endpoints of the other
+ * segment lie on opposite sides of the line, and vice versa. "Lie on
+ * opposite sides" is computed by taking the cross products and seeing if
+ * they are of opposite signs.
+ */
+
+ double dx, dy, dx1, dy1;
+
+ dx = ax2 - ax1;
+ dy = ay2 - ay1;
+ dx1 = bx1 - ax1;
+ dy1 = by1 - ay1;
+ if ((dx*dy1-dy*dx1 > 0.0) == (dx*(by2-ay1)-dy*(bx2-ax1) > 0.0)) {
+ return 0;
+ }
+ dx = bx2 - bx1;
+ dy = by2 - by1;
+ if ((dy*dx1-dx*dy1 > 0.0) == (dx*(ay2-by1)-dy*(ax2-bx1) > 0.0)) {
+ return 0;
+ }
+ return 1;
+#endif
+}
+
+int
+TkIntersectAngledTextLayout(
+ Tk_TextLayout layout, /* Layout information, from a previous call to
+ * Tk_ComputeTextLayout(). */
+ int x, int y, /* Upper-left hand corner, in pixels, of
+ * rectangular area to compare with text
+ * layout. Coordinates are with respect to the
+ * upper-left hand corner of the text layout
+ * itself. */
+ int width, int height, /* The width and height of the above
+ * rectangular area, in pixels. */
+ double angle)
+{
+ int i, x1, y1, x2, y2;
+ TextLayout *layoutPtr;
+ LayoutChunk *chunkPtr;
+ TkFont *fontPtr;
+ double c = cos(angle * PI/180.0), s = sin(angle * PI/180.0);
+ double rx[4], ry[4];
+
+ if (angle == 0.0) {
+ return Tk_IntersectTextLayout(layout, x, y, width, height);
+ }
+
+ /*
+ * Compute the coordinates of the rectangle, rotated into text layout
+ * space.
+ */
+
+ rx[0] = x*c - y*s;
+ ry[0] = y*c + x*s;
+ rx[1] = (x+width)*c - y*s;
+ ry[1] = y*c + (x+width)*s;
+ rx[2] = (x+width)*c - (y+height)*s;
+ ry[2] = (y+height)*c + (x+width)*s;
+ rx[3] = x*c - (y+height)*s;
+ ry[3] = (y+height)*c + x*s;
+
+ /*
+ * Want to know if all chunks are inside the rectangle, or if there is any
+ * overlap. First, we check to see if all chunks are inside; if and only
+ * if they are, we're in the "inside" case.
+ */
+
+ layoutPtr = (TextLayout *) layout;
+ chunkPtr = layoutPtr->chunks;
+ fontPtr = (TkFont *) layoutPtr->tkfont;
+
+ for (i=0 ; i<layoutPtr->numChunks ; i++,chunkPtr++) {
+ if (chunkPtr->start[0] == '\n') {
+ /*
+ * Newline characters are not counted when computing area
+ * intersection (but tab characters would still be considered).
+ */
+
+ continue;
+ }
+
+ x1 = chunkPtr->x;
+ y1 = chunkPtr->y - fontPtr->fm.ascent;
+ x2 = chunkPtr->x + chunkPtr->displayWidth;
+ y2 = chunkPtr->y + fontPtr->fm.descent;
+ if ( !PointInQuadrilateral(rx, ry, x1, y1) ||
+ !PointInQuadrilateral(rx, ry, x2, y1) ||
+ !PointInQuadrilateral(rx, ry, x2, y2) ||
+ !PointInQuadrilateral(rx, ry, x1, y2)) {
+ goto notInside;
+ }
+ }
+ return 1;
+
+ /*
+ * Next, check to see if all the points of the rectangle are inside a
+ * single chunk; if they are, we're in an "overlap" case.
+ */
+
+ notInside:
+ chunkPtr = layoutPtr->chunks;
+
+ for (i=0 ; i<layoutPtr->numChunks ; i++,chunkPtr++) {
+ double cx[4], cy[4];
+ if (chunkPtr->start[0] == '\n') {
+ /*
+ * Newline characters are not counted when computing area
+ * intersection (but tab characters would still be considered).
+ */
+
+ continue;
+ }
+
+ cx[0] = cx[3] = chunkPtr->x;
+ cy[0] = cy[1] = chunkPtr->y - fontPtr->fm.ascent;
+ cx[1] = cx[2] = chunkPtr->x + chunkPtr->displayWidth;
+ cy[2] = cy[3] = chunkPtr->y + fontPtr->fm.descent;
+ if ( !PointInQuadrilateral(cx, cy, rx[0], ry[0]) ||
+ !PointInQuadrilateral(cx, cy, rx[1], ry[1]) ||
+ !PointInQuadrilateral(cx, cy, rx[2], ry[2]) ||
+ !PointInQuadrilateral(cx, cy, rx[3], ry[3])) {
+ goto notReverseInside;
+ }
+ }
+ return 0;
+
+ /*
+ * If we're overlapping now, we must be partially in and out of at least
+ * one chunk. If that is the case, there must be one line segment of the
+ * rectangle that is touching or crossing a line segment of a chunk.
+ */
+
+ notReverseInside:
+ chunkPtr = layoutPtr->chunks;
+
+ for (i=0 ; i<layoutPtr->numChunks ; i++,chunkPtr++) {
+ int j;
+
+ if (chunkPtr->start[0] == '\n') {
+ /*
+ * Newline characters are not counted when computing area
+ * intersection (but tab characters would still be considered).
+ */
+
+ continue;
+ }
+
+ x1 = chunkPtr->x;
+ y1 = chunkPtr->y - fontPtr->fm.ascent;
+ x2 = chunkPtr->x + chunkPtr->displayWidth;
+ y2 = chunkPtr->y + fontPtr->fm.descent;
+
+ for (j=0 ; j<4 ; j++) {
+ int k = (j+1) % 4;
+ if ( SidesIntersect(rx[j],ry[j], rx[k],ry[k], x1,y1, x2,y1) ||
+ SidesIntersect(rx[j],ry[j], rx[k],ry[k], x2,y1, x2,y2) ||
+ SidesIntersect(rx[j],ry[j], rx[k],ry[k], x2,y2, x1,y2) ||
+ SidesIntersect(rx[j],ry[j], rx[k],ry[k], x1,y2, x1,y1)) {
+ return 0;
+ }
+ }
+ }
+
+ /*
+ * They must be wholly non-overlapping.
+ */
+
+ return -1;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
* Tk_TextLayoutToPostscript --
*
* Outputs the contents of a text layout in Postscript format. The set of
diff --git a/generic/tkInt.h b/generic/tkInt.h
index 10fff59..5fe85e1 100644
--- a/generic/tkInt.h
+++ b/generic/tkInt.h
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: $Id: tkInt.h,v 1.92 2008/11/09 21:53:39 nijtmans Exp $
+ * RCS: $Id: tkInt.h,v 1.93 2008/11/22 18:08:51 dkf Exp $
*/
#ifndef _TKINT
@@ -956,6 +956,19 @@ MODULE_SCOPE TkMainInfo *tkMainWindowList;
MODULE_SCOPE Tk_ImageType tkPhotoImageType;
MODULE_SCOPE Tcl_HashTable tkPredefBitmapTable;
+/*
+ * The definition of pi, at least from the perspective of double-precision
+ * floats.
+ */
+
+#ifndef PI
+#define PI 3.14159265358979323846
+#endif
+
+/*
+ * Exported internals.
+ */
+
#include "tkIntDecls.h"
#ifdef BUILD_tk
@@ -1214,6 +1227,19 @@ MODULE_SCOPE void TkpCreateBusy(Tk_FakeWin *winPtr, Tk_Window tkRef,
Window *parentPtr, Tk_Window tkParent,
TkBusy busy);
+MODULE_SCOPE void TkDrawAngledTextLayout(Display *display,
+ Drawable drawable, GC gc, Tk_TextLayout layout,
+ int x, int y, double angle, int firstChar,
+ int lastChar);
+MODULE_SCOPE void TkpDrawAngledChars(Display *display,Drawable drawable,
+ GC gc, Tk_Font tkfont, const char *source,
+ int numBytes, double x, double y, double angle);
+MODULE_SCOPE void TkUnderlineAngledTextLayout(Display *display,
+ Drawable drawable, GC gc, Tk_TextLayout layout,
+ int x, int y, double angle, int underline);
+MODULE_SCOPE int TkIntersectAngledTextLayout(Tk_TextLayout layout,
+ int x,int y, int width, int height, double angle);
+
/*
* Unsupported commands.
*/
diff --git a/library/prolog.ps b/library/prolog.ps
index 9c76878..a82c3d2 100644
--- a/library/prolog.ps
+++ b/library/prolog.ps
@@ -3,7 +3,7 @@
% This is a standard prolog for Postscript generated by Tk's canvas
% widget.
-% RCS: @(#) $Id: prolog.ps,v 1.3 1999/02/04 20:59:48 stanton Exp $
+% RCS: @(#) $Id: prolog.ps,v 1.4 2008/11/22 18:08:51 dkf Exp $
% The definitions below just define all of the variables used in
% any of the procedures here. This is needed for obscure reasons
@@ -189,11 +189,12 @@ systemdict /ISOLatin1Encoding known not {
} if
} bind def
-% x y strings spacing xoffset yoffset justify stipple DrawText --
+% angle x y strings spacing xoffset yoffset justify stipple DrawText --
% This procedure does all of the real work of drawing text. The
% color and font must already have been set by the caller, and the
% following arguments must be on the stack:
%
+% angle - Angle through which to rotate text, in degrees.
% x, y - Coordinates at which to draw text.
% strings - An array of strings, one for each line of the text item,
% in order from top to bottom.
@@ -235,11 +236,12 @@ systemdict /ISOLatin1Encoding known not {
exch pop exch sub /height exch def pop
newpath
- % Translate coordinates first so that the origin is at the upper-left
- % corner of the text's bounding box. Remember that x and y for
- % positioning are still on the stack.
+ % Translate and rotatecoordinates first so that the origin is at the
+ % upper-left corner of the text's bounding box. Remember that angle, x and
+ % y for positioning are still on the stack.
translate
+ rotate
lineLength xoffset mul
strings length 1 sub spacing mul height add yoffset mul translate
diff --git a/macosx/tkMacOSXFont.c b/macosx/tkMacOSXFont.c
index 921cf93..ca11b69 100644
--- a/macosx/tkMacOSXFont.c
+++ b/macosx/tkMacOSXFont.c
@@ -35,7 +35,7 @@
* that such fonts can not be used for controls, because controls
* definitely require a family id (this assertion needs testing).
*
- * RCS: @(#) $Id: tkMacOSXFont.c,v 1.40 2008/11/02 09:54:02 nijtmans Exp $
+ * RCS: @(#) $Id: tkMacOSXFont.c,v 1.41 2008/11/22 18:08:51 dkf Exp $
*/
#include "tkMacOSXPrivate.h"
@@ -262,7 +262,10 @@ static OSStatus GetThemeFontAndFamily(const ThemeFontID themeFontId,
static void InitSystemFonts(TkMainInfo *mainPtr);
static int CreateNamedSystemFont(Tcl_Interp *interp, Tk_Window tkwin,
const char* name, TkFontAttributes *faPtr);
-
+static void DrawCharsInContext(Display *display,
+ Drawable drawable, GC gc, Tk_Font tkfont,
+ const char *source, int numBytes, int rangeStart,
+ int rangeLength, int x, int y, double angle);
/*
*-------------------------------------------------------------------------
@@ -1135,8 +1138,31 @@ Tk_DrawChars(
int x, int y) /* Coordinates at which to place origin of the
* string when drawing. */
{
- TkpDrawCharsInContext(display, drawable, gc, tkfont, source, numBytes,
- 0, numBytes, x, y);
+ DrawCharsInContext(display, drawable, gc, tkfont, source, numBytes,
+ 0, numBytes, x, y, 0.0);
+}
+
+void
+TkpDrawAngledChars(
+ Display *display, /* Display on which to draw. */
+ Drawable drawable, /* Window or pixmap in which to draw. */
+ GC gc, /* Graphics context for drawing characters. */
+ Tk_Font tkfont, /* Font in which characters will be drawn;
+ * must be the same as font used in GC. */
+ const char *source, /* UTF-8 string to be displayed. Need not be
+ * '\0' terminated. All Tk meta-characters
+ * (tabs, control characters, and newlines)
+ * should be stripped out of the string that
+ * is passed to this function. If they are not
+ * stripped out, they will be displayed as
+ * regular printing characters. */
+ int numBytes, /* Number of bytes in string. */
+ double x, double y, /* Coordinates at which to place origin of
+ * string when drawing. */
+ double angle) /* What angle to put text at, in degrees. */
+{
+ DrawCharsInContext(display, drawable, gc, tkfont, source, numBytes,
+ 0, numBytes, x, y, angle);
}
/*
@@ -1180,6 +1206,32 @@ TkpDrawCharsInContext(
* whole (not just the range) string when
* drawing. */
{
+ DrawCharsInContext(display, drawable, gc, tkfont, source, numBytes,
+ rangeStart, rangeLength, x, y, 0.0);
+}
+
+static void
+DrawCharsInContext(
+ Display *display, /* Display on which to draw. */
+ Drawable drawable, /* Window or pixmap in which to draw. */
+ GC gc, /* Graphics context for drawing characters. */
+ Tk_Font tkfont, /* Font in which characters will be drawn; must
+ * be the same as font used in GC. */
+ const char * source, /* UTF-8 string to be displayed. Need not be
+ * '\0' terminated. All Tk meta-characters
+ * (tabs, control characters, and newlines)
+ * should be stripped out of the string that
+ * is passed to this function. If they are not
+ * stripped out, they will be displayed as
+ * regular printing characters. */
+ int numBytes, /* Number of bytes in string. */
+ int rangeStart, /* Index of first byte to draw. */
+ int rangeLength, /* Length of range to draw in bytes. */
+ int x, int y, /* Coordinates at which to place origin of the
+ * whole (not just the range) string when
+ * drawing. */
+ double angle)
+{
const MacFont * fontPtr = (const MacFont *) tkfont;
MacDrawable *macWin = (MacDrawable *) drawable;
Fixed fx, fy;
@@ -1242,6 +1294,16 @@ TkpDrawCharsInContext(
urstart = Tcl_NumUtfChars(source, rangeStart);
urlen = Tcl_NumUtfChars(source+rangeStart,rangeLength);
+ /*
+ * Rotate the coordinate system for Quarz drawing.
+ */
+
+ if (drawingContext.context && angle != 0.0) {
+ CGContextTranslateCTM(drawingContext.context, x, y);
+ CGContextRotateCTM(drawingContext.context, angle * PI/180.0);
+ CGContextTranslateCTM(drawingContext.context, -x, -y);
+ }
+
ChkErr(ATSUDrawText, fontPtr->atsuLayout, lineOffset+urstart, urlen, fx,
fy);
diff --git a/tests/canvText.test b/tests/canvText.test
index 96a362a..2ca02f0 100644
--- a/tests/canvText.test
+++ b/tests/canvText.test
@@ -6,7 +6,7 @@
# Copyright (c) 1998-1999 by Scriptics Corporation.
# All rights reserved.
#
-# RCS: @(#) $Id: canvText.test,v 1.21 2008/10/11 06:47:25 dkf Exp $
+# RCS: @(#) $Id: canvText.test,v 1.22 2008/11/22 18:08:51 dkf Exp $
package require tcltest 2.2
namespace import ::tcltest::*
@@ -27,7 +27,6 @@ test canvText-1.1 {configuration options: good value for "anchor"} -body {
test canvasText-1.2 {configuration options: bad value for "anchor"} -body {
.c itemconfigure test -anchor xyz
} -returnCodes error -result {bad anchor position "xyz": must be n, ne, e, se, s, sw, w, nw, or center}
-
test canvText-1.3 {configuration options: good value for "fill"} -body {
.c itemconfigure test -fill #ff0000
list [lindex [.c itemconfigure test -fill] 4] [.c itemcget test -fill]
@@ -39,7 +38,6 @@ test canvText-1.5 {configuration options: good value for "fill"} -body {
.c itemconfigure test -fill {}
list [lindex [.c itemconfigure test -fill] 4] [.c itemcget test -fill]
} -result {{} {}}
-
test canvText-1.6 {configuration options: good value for "font"} -body {
.c itemconfigure test -font {Times 40}
list [lindex [.c itemconfigure test -font] 4] [.c itemcget test -font]
@@ -47,7 +45,6 @@ test canvText-1.6 {configuration options: good value for "font"} -body {
test canvasText-1.7 {configuration options: bad value for "font"} -body {
.c itemconfigure test -font {}
} -returnCodes error -result {font "" doesn't exist}
-
test canvText-1.8 {configuration options: good value for "justify"} -body {
.c itemconfigure test -justify left
list [lindex [.c itemconfigure test -justify] 4] [.c itemcget test -justify]
@@ -55,7 +52,6 @@ test canvText-1.8 {configuration options: good value for "justify"} -body {
test canvasText-1.9 {configuration options: bad value for "justify"} -body {
.c itemconfigure test -justify xyz
} -returnCodes error -result {bad justification "xyz": must be left, right, or center}
-
test canvText-1.10 {configuration options: good value for "stipple"} -body {
.c itemconfigure test -stipple gray50
list [lindex [.c itemconfigure test -stipple] 4] [.c itemcget test -stipple]
@@ -63,7 +59,6 @@ test canvText-1.10 {configuration options: good value for "stipple"} -body {
test canvasText-1.11 {configuration options: bad value for "stipple"} -body {
.c itemconfigure test -stipple xyz
} -returnCodes error -result {bitmap "xyz" not defined}
-
test canvText-1.12 {configuration options: good value for "underline"} -body {
.c itemconfigure test -underline 0
list [lindex [.c itemconfigure test -underline] 4] [.c itemcget test -underline]
@@ -71,7 +66,6 @@ test canvText-1.12 {configuration options: good value for "underline"} -body {
test canvasText-1.13 {configuration options: bad value for "underline"} -body {
.c itemconfigure test -underline xyz
} -returnCodes error -result {expected integer but got "xyz"}
-
test canvText-1.14 {configuration options: good value for "width"} -body {
.c itemconfigure test -width 6
list [lindex [.c itemconfigure test -width] 4] [.c itemcget test -width]
@@ -79,11 +73,25 @@ test canvText-1.14 {configuration options: good value for "width"} -body {
test canvasText-1.15 {configuration options: bad value for "width"} -body {
.c itemconfigure test -width xyz
} -returnCodes error -result {bad screen distance "xyz"}
-
test canvText-1.16 {configuration options: good value for "tags"} -body {
.c itemconfigure test -tags {test a b c}
list [lindex [.c itemconfigure test -tags] 4] [.c itemcget test -tags]
} -result {{test a b c} {test a b c}}
+test canvasText-1.17 {configuration options: bad value for "angle"} -body {
+ .c itemconfigure test -angle xyz
+} -returnCodes error -result {expected floating-point number but got "xyz"}
+test canvasText-1.18 {configuration options: good value for "angle"} -body {
+ .c itemconfigure test -angle 32.5
+ list [lindex [.c itemconfigure test -angle] 4] [.c itemcget test -angle]
+} -result {32.5 32.5}
+test canvasText-1.19 {configuration options: bounding of "angle"} -body {
+ .c itemconfigure test -angle 390
+ set result [.c itemcget test -angle]
+ .c itemconfigure test -angle -30
+ lappend result [.c itemcget test -angle]
+ .c itemconfigure test -angle -360
+ lappend result [.c itemcget test -angle]
+} -result {30.0 330.0 0.0}
.c delete test
@@ -93,17 +101,17 @@ test canvText-2.1 {CreateText procedure: args} -body {
test canvText-2.2 {CreateText procedure: args} -body {
.c create text xyz 0
} -cleanup {
- .c delete all
+ .c delete all
} -returnCodes {error} -result {bad screen distance "xyz"}
test canvText-2.3 {CreateText procedure: args} -body {
.c create text 0 xyz
} -cleanup {
- .c delete all
+ .c delete all
} -returnCodes {error} -result {bad screen distance "xyz"}
test canvText-2.4 {CreateText procedure: args} -body {
.c create text 0 0 -xyz xyz
} -cleanup {
- .c delete all
+ .c delete all
} -returnCodes {error} -result {unknown option "-xyz"}
test canvText-2.5 {CreateText procedure} -body {
.c create text 0 0 -tags x
@@ -114,29 +122,29 @@ test canvText-2.5 {CreateText procedure} -body {
test canvText-3.1 {TextCoords procedure} -body {
- .c create text 20 20 -tag test
- .c coords test 0 0
- update
+ .c create text 20 20 -tag test
+ .c coords test 0 0
+ update
.c coords test
} -cleanup {
- .c delete test
+ .c delete test
} -result {0.0 0.0}
test canvText-3.2 {TextCoords procedure} -setup {
- .c create text 20 20 -tag test
+ .c create text 20 20 -tag test
} -body {
.c coords test xyz 0
} -cleanup {
- .c delete test
+ .c delete test
} -returnCodes {error} -result {bad screen distance "xyz"}
test canvText-3.3 {TextCoords procedure} -setup {
- .c create text 20 20 -tag test
+ .c create text 20 20 -tag test
} -body {
.c coords test 0 xyz
} -cleanup {
- .c delete test
+ .c delete test
} -returnCodes {error} -result {bad screen distance "xyz"}
test canvText-3.4 {TextCoords procedure} -setup {
- .c create text 20 20 -tag test
+ .c create text 20 20 -tag test
} -body {
.c coords test 10 10
set result {}
@@ -145,75 +153,73 @@ test canvText-3.4 {TextCoords procedure} -setup {
}
return $result
} -cleanup {
- .c delete test
+ .c delete test
} -result {10.0 10.0}
test canvText-3.5 {TextCoords procedure} -setup {
- .c create text 20 20 -tag test
+ .c create text 20 20 -tag test
} -body {
.c coords test 10
} -cleanup {
- .c delete test
+ .c delete test
} -returnCodes {error} -result {wrong # coordinates: expected 2, got 1}
test canvText-3.6 {TextCoords procedure} -setup {
- .c create text 20 20 -tag test
+ .c create text 20 20 -tag test
} -body {
.c coords test 10 10 10
} -cleanup {
- .c delete test
+ .c delete test
} -returnCodes {error} -result {wrong # coordinates: expected 0 or 2, got 3}
test canvText-4.1 {ConfigureText procedure} -setup {
- .c create text 20 20 -tag test
+ .c create text 20 20 -tag test
} -body {
.c itemconfig test -fill xyz
} -cleanup {
- .c delete test
+ .c delete test
} -returnCodes {error} -result {unknown color name "xyz"}
test canvText-4.2 {ConfigureText procedure} -setup {
- .c create text 20 20 -tag test
+ .c create text 20 20 -tag test
} -body {
.c itemconfig test -fill blue
.c itemcget test -fill
} -cleanup {
- .c delete test
+ .c delete test
} -result {blue}
test canvText-4.3 {ConfigureText procedure: construct font gcs} -setup {
- .c create text 20 20 -tag test
+ .c create text 20 20 -tag test
} -body {
.c itemconfig test -font "times 20" -fill black -stipple gray50
list [.c itemcget test -font] [.c itemcget test -fill] [.c itemcget test -stipple]
} -cleanup {
- .c delete test
+ .c delete test
} -result {{times 20} black gray50}
test canvText-4.4 {ConfigureText procedure: construct cursor gc} -setup {
- .c create text 20 20 -tag test
- focus .c
- .c focus test
+ .c create text 20 20 -tag test
+ focus .c
+ .c focus test
} -body {
.c itemconfig test -text "abcdefg"
.c select from test 2
.c select to test 4
.c icursor test 3
-
# Both black -> cursor becomes white.
.c config -insertbackground black
.c config -selectbackground black
.c itemconfig test -just left
update
-
# Both same color (and not black) -> cursor becomes black.
.c config -insertbackground red
.c config -selectbackground red
.c itemconfig test -just left
update
} -cleanup {
- .c delete test
+ .c delete test
} -result {}
test canvText-4.5 {ConfigureText procedure: adjust selection} -setup {
- .c create text 20 20 -tag test
- focus .c
- .c focus test
+ .c create text 20 20 -tag test
+ focus .c
+ .c focus test
set x {}
} -body {
.c itemconfig test -text "abcdefghi"
@@ -235,10 +241,10 @@ test canvText-4.5 {ConfigureText procedure: adjust selection} -setup {
.c dchars test 4 end
lappend x [selection get]
} -cleanup {
- .c delete test
+ .c delete test
} -result {cdefg 1 cdefg cd cdef cd}
test canvText-4.6 {ConfigureText procedure: adjust cursor} -setup {
- .c create text 20 20 -tag test
+ .c create text 20 20 -tag test
} -body {
.c itemconfig test -text "abcdefghi"
.c icursor test 6
@@ -250,154 +256,128 @@ test canvText-4.6 {ConfigureText procedure: adjust cursor} -setup {
test canvText-5.1 {ConfigureText procedure: adjust cursor} -body {
- .c create text 10 10 -tag x -fill blue -font "times 40" -stipple gray50 -text "xyz"
+ .c create text 10 10 -tag x -fill blue -font "times 40" -stipple gray50 \
+ -text "xyz"
.c delete x
} -result {}
-test canvText-6.1 {ComputeTextBbox procedure} -constraints {
- fonts
-} -setup {
- .c delete test
+test canvText-6.1 {ComputeTextBbox procedure} -constraints fonts -setup {
+ .c delete test
} -body {
- set font "-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*"
- set ay [font metrics $font -linespace]
- set ax [font measure $font 0]
-
- .c create text 0 0 -tag test
+ set font "-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*"
+ set ay [font metrics $font -linespace]
+ set ax [font measure $font 0]
+ .c create text 0 0 -tag test
.c itemconfig test -font $font -text 0
expr {[.c itemconfig test -anchor n; .c bbox test] \
- eq "[expr -$ax/2-1] 0 [expr $ax/2+1] $ay"}
+ eq "[expr -$ax/2-1] 0 [expr $ax/2+1] $ay"}
} -cleanup {
- .c delete test
+ .c delete test
} -result 1
-test canvText-6.2 {ComputeTextBbox procedure} -constraints {
- fonts
-} -setup {
- .c delete test
+test canvText-6.2 {ComputeTextBbox procedure} -constraints fonts -setup {
+ .c delete test
} -body {
- set font "-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*"
- set ay [font metrics $font -linespace]
- set ax [font measure $font 0]
-
- .c create text 0 0 -tag test
+ set font "-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*"
+ set ay [font metrics $font -linespace]
+ set ax [font measure $font 0]
+ .c create text 0 0 -tag test
.c itemconfig test -font $font -text 0
expr {[.c itemconfig test -anchor nw; .c bbox test] \
- eq "-1 0 [expr $ax+1] $ay"}
+ eq "-1 0 [expr $ax+1] $ay"}
} -cleanup {
- .c delete test
+ .c delete test
} -result 1
-test canvText-6.3 {ComputeTextBbox procedure} -constraints {
- fonts
-} -setup {
- .c delete test
+test canvText-6.3 {ComputeTextBbox procedure} -constraints fonts -setup {
+ .c delete test
} -body {
- set font "-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*"
- set ay [font metrics $font -linespace]
- set ax [font measure $font 0]
-
- .c create text 0 0 -tag test
+ set font "-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*"
+ set ay [font metrics $font -linespace]
+ set ax [font measure $font 0]
+ .c create text 0 0 -tag test
.c itemconfig test -font $font -text 0
expr {[.c itemconfig test -anchor w; .c bbox test] \
- eq "-1 [expr -$ay/2] [expr $ax+1] [expr $ay/2]"}
+ eq "-1 [expr -$ay/2] [expr $ax+1] [expr $ay/2]"}
} -cleanup {
- .c delete test
+ .c delete test
} -result 1
-test canvText-6.4 {ComputeTextBbox procedure} -constraints {
- fonts
-} -setup {
- .c delete test
+test canvText-6.4 {ComputeTextBbox procedure} -constraints fonts -setup {
+ .c delete test
} -body {
- set font "-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*"
- set ay [font metrics $font -linespace]
- set ax [font measure $font 0]
-
- .c create text 0 0 -tag test
+ set font "-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*"
+ set ay [font metrics $font -linespace]
+ set ax [font measure $font 0]
+ .c create text 0 0 -tag test
.c itemconfig test -font $font -text 0
expr {[.c itemconfig test -anchor sw; .c bbox test] \
- eq "-1 -$ay [expr $ax+1] 0"}
+ eq "-1 -$ay [expr $ax+1] 0"}
} -cleanup {
- .c delete test
+ .c delete test
} -result 1
-test canvText-6.5 {ComputeTextBbox procedure} -constraints {
- fonts
-} -setup {
- .c delete test
+test canvText-6.5 {ComputeTextBbox procedure} -constraints fonts -setup {
+ .c delete test
} -body {
- set font "-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*"
- set ay [font metrics $font -linespace]
- set ax [font measure $font 0]
-
- .c create text 0 0 -tag test
+ set font "-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*"
+ set ay [font metrics $font -linespace]
+ set ax [font measure $font 0]
+ .c create text 0 0 -tag test
.c itemconfig test -font $font -text 0
expr {[.c itemconfig test -anchor s; .c bbox test] \
- eq "[expr -$ax/2-1] -$ay [expr $ax/2+1] 0"}
+ eq "[expr -$ax/2-1] -$ay [expr $ax/2+1] 0"}
} -cleanup {
- .c delete test
+ .c delete test
} -result 1
-test canvText-6.6 {ComputeTextBbox procedure} -constraints {
- fonts
-} -setup {
- .c delete test
+test canvText-6.6 {ComputeTextBbox procedure} -constraints fonts -setup {
+ .c delete test
} -body {
- set font "-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*"
- set ay [font metrics $font -linespace]
- set ax [font measure $font 0]
-
- .c create text 0 0 -tag test
+ set font "-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*"
+ set ay [font metrics $font -linespace]
+ set ax [font measure $font 0]
+ .c create text 0 0 -tag test
.c itemconfig test -font $font -text 0
expr {[.c itemconfig test -anchor se; .c bbox test] \
- eq "[expr -$ax-1] -$ay 1 0"}
+ eq "[expr -$ax-1] -$ay 1 0"}
} -cleanup {
- .c delete test
+ .c delete test
} -result 1
-test canvText-6.7 {ComputeTextBbox procedure} -constraints {
- fonts
-} -setup {
- .c delete test
+test canvText-6.7 {ComputeTextBbox procedure} -constraints fonts -setup {
+ .c delete test
} -body {
- set font "-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*"
- set ay [font metrics $font -linespace]
- set ax [font measure $font 0]
-
- .c create text 0 0 -tag test
+ set font "-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*"
+ set ay [font metrics $font -linespace]
+ set ax [font measure $font 0]
+ .c create text 0 0 -tag test
.c itemconfig test -font $font -text 0
expr {[.c itemconfig test -anchor e; .c bbox test]\
- eq "[expr -$ax-1] [expr -$ay/2] 1 [expr $ay/2]"}
+ eq "[expr -$ax-1] [expr -$ay/2] 1 [expr $ay/2]"}
} -cleanup {
- .c delete test
+ .c delete test
} -result 1
-test canvText-6.8 {ComputeTextBbox procedure} -constraints {
- fonts
-} -setup {
- .c delete test
+test canvText-6.8 {ComputeTextBbox procedure} -constraints fonts -setup {
+ .c delete test
} -body {
- set font "-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*"
- set ay [font metrics $font -linespace]
- set ax [font measure $font 0]
-
- .c create text 0 0 -tag test
+ set font "-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*"
+ set ay [font metrics $font -linespace]
+ set ax [font measure $font 0]
+ .c create text 0 0 -tag test
.c itemconfig test -font $font -text 0
expr {[.c itemconfig test -anchor ne; .c bbox test] \
- eq "[expr -$ax-1] 0 1 $ay"}
+ eq "[expr -$ax-1] 0 1 $ay"}
} -cleanup {
- .c delete test
+ .c delete test
} -result 1
-test canvText-6.9 {ComputeTextBbox procedure} -constraints {
- fonts
-} -setup {
- .c delete test
+test canvText-6.9 {ComputeTextBbox procedure} -constraints fonts -setup {
+ .c delete test
} -body {
- set font "-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*"
- set ay [font metrics $font -linespace]
- set ax [font measure $font 0]
-
- .c create text 0 0 -tag test
+ set font "-adobe-times-medium-r-normal--*-200-*-*-*-*-*-*"
+ set ay [font metrics $font -linespace]
+ set ax [font measure $font 0]
+ .c create text 0 0 -tag test
.c itemconfig test -font $font -text 0
expr {[.c itemconfig test -anchor center; .c bbox test] \
- eq "[expr -$ax/2-1] [expr -$ay/2] [expr $ax/2+1] [expr $ay/2]"}
+ eq "[expr -$ax/2-1] [expr -$ay/2] [expr $ax/2+1] [expr $ay/2]"}
} -cleanup {
- .c delete test
+ .c delete test
} -result 1
@@ -409,100 +389,100 @@ focus .c
.c focus test
.c itemconfig test -text "abcd\nefghi\njklmnopq"
test canvText-7.1 {DisplayText procedure: stippling} -body {
- .c create text 20 20 -tag test
+ .c create text 20 20 -tag test
.c itemconfig test -stipple gray50
update
.c itemconfig test -stipple {}
update
} -cleanup {
- .c delete test
+ .c delete test
} -result {}
test canvText-7.2 {DisplayText procedure: draw selection} -setup {
- .c create text 20 20 -tag test
- focus .c
- .c focus test
+ .c create text 20 20 -tag test
+ focus .c
+ .c focus test
} -body {
- .c itemconfig test -text "abcd\nefghi\njklmnopq"
+ .c itemconfig test -text "abcd\nefghi\njklmnopq"
.c select from test 0
.c select to test end
update
selection get
} -cleanup {
- .c delete test
+ .c delete test
} -result "abcd\nefghi\njklmnopq"
test canvText-7.3 {DisplayText procedure: selection} -setup {
- .c create text 20 20 -tag test
- focus .c
- .c focus test
+ .c create text 20 20 -tag test
+ focus .c
+ .c focus test
} -body {
- .c itemconfig test -text "abcd\nefghi\njklmnopq"
+ .c itemconfig test -text "abcd\nefghi\njklmnopq"
.c select from test 0
.c select to test end
update
selection get
} -cleanup {
- .c delete test
+ .c delete test
} -result "abcd\nefghi\njklmnopq"
test canvText-7.4 {DisplayText procedure: one line selection} -setup {
- .c create text 20 20 -tag test
- focus .c
- .c focus test
+ .c create text 20 20 -tag test
+ focus .c
+ .c focus test
} -body {
- .c itemconfig test -text "abcd\nefghi\njklmnopq"
+ .c itemconfig test -text "abcd\nefghi\njklmnopq"
.c select from test 2
.c select to test 3
update
} -cleanup {
- .c delete test
+ .c delete test
} -result {}
test canvText-7.5 {DisplayText procedure: multi-line selection} -setup {
- .c create text 20 20 -tag test
- focus .c
- .c focus test
+ .c create text 20 20 -tag test
+ focus .c
+ .c focus test
} -body {
- .c itemconfig test -text "abcd\nefghi\njklmnopq"
+ .c itemconfig test -text "abcd\nefghi\njklmnopq"
.c select from test 2
.c select to test 12
update
} -cleanup {
- .c delete test
+ .c delete test
} -result {}
test canvText-7.6 {DisplayText procedure: draw cursor} -setup {
- .c create text 20 20 -tag test
- focus .c
- .c focus test
+ .c create text 20 20 -tag test
+ focus .c
+ .c focus test
} -body {
- .c itemconfig test -text "abcd\nefghi\njklmnopq"
+ .c itemconfig test -text "abcd\nefghi\njklmnopq"
.c icursor test 3
update
} -cleanup {
- .c delete test
+ .c delete test
} -result {}
test canvText-7.7 {DisplayText procedure: selected text different color} -setup {
- .c create text 20 20 -tag test
- .c itemconfig test -text "abcd\nefghi\njklmnopq"
- focus .c
- .c focus test
+ .c create text 20 20 -tag test
+ .c itemconfig test -text "abcd\nefghi\njklmnopq"
+ focus .c
+ .c focus test
} -body {
.c config -selectforeground blue
.c itemconfig test -anchor n
update
} -cleanup {
- .c delete test
+ .c delete test
} -result {}
test canvText-7.8 {DisplayText procedure: not selected} -setup {
- .c create text 20 20 -tag test
- .c itemconfig test -text "abcd\nefghi\njklmnopq"
- focus .c
- .c focus test
+ .c create text 20 20 -tag test
+ .c itemconfig test -text "abcd\nefghi\njklmnopq"
+ focus .c
+ .c focus test
} -body {
.c select clear
update
} -cleanup {
- .c delete test
+ .c delete test
} -result {}
test canvText-7.9 {DisplayText procedure: select end} -setup {
- destroy .t
+ destroy .t
} -body {
toplevel .t
wm geometry .t +0+0
@@ -516,26 +496,26 @@ test canvText-7.9 {DisplayText procedure: select end} -setup {
#catch {destroy .t}
update
} -cleanup {
- destroy .t
+ destroy .t
} -result {}
test canvText-8.1 {TextInsert procedure: 0 length insert} -setup {
- .c create text 20 20 -tag test
- .c itemconfig test -text "abcd\nefghi\njklmnopq"
- focus .c
- .c focus test
+ .c create text 20 20 -tag test
+ .c itemconfig test -text "abcd\nefghi\njklmnopq"
+ focus .c
+ .c focus test
} -body {
.c insert test end {}
} -cleanup {
- .c delete test
+ .c delete test
} -result {}
test canvText-8.2 {TextInsert procedure: before beginning/after end} -body {
# Can't test this because GetTextIndex filters out those numbers.
} -result {}
test canvText-8.3 {TextInsert procedure: inserting in a selected item} -setup {
- .c create text 20 20 -tag test
- focus .c
- .c focus test
+ .c create text 20 20 -tag test
+ focus .c
+ .c focus test
} -body {
.c itemconfig test -text "abcdefg"
.c select from test 2
@@ -544,9 +524,9 @@ test canvText-8.3 {TextInsert procedure: inserting in a selected item} -setup {
.c itemcget test -text
} -result {axyzbcdefg}
test canvText-8.4 {TextInsert procedure: inserting before selection} -setup {
- .c create text 20 20 -tag test
- focus .c
- .c focus test
+ .c create text 20 20 -tag test
+ focus .c
+ .c focus test
} -body {
.c itemconfig test -text "abcdefg"
.c select from test 2
@@ -555,9 +535,9 @@ test canvText-8.4 {TextInsert procedure: inserting before selection} -setup {
list [.c index test sel.first] [.c index test sel.last]
} -result {5 7}
test canvText-8.5 {TextInsert procedure: inserting in selection} -setup {
- .c create text 20 20 -tag test
- focus .c
- .c focus test
+ .c create text 20 20 -tag test
+ focus .c
+ .c focus test
} -body {
.c itemconfig test -text "abcdefg"
.c select from test 2
@@ -566,9 +546,9 @@ test canvText-8.5 {TextInsert procedure: inserting in selection} -setup {
list [.c index test sel.first] [.c index test sel.last]
} -result {2 7}
test canvText-8.6 {TextInsert procedure: inserting after selection} -setup {
- .c create text 20 20 -tag test
- focus .c
- .c focus test
+ .c create text 20 20 -tag test
+ focus .c
+ .c focus test
} -body {
.c itemconfig test -text "abcdefg"
.c select from test 2
@@ -577,9 +557,9 @@ test canvText-8.6 {TextInsert procedure: inserting after selection} -setup {
list [.c index test sel.first] [.c index test sel.last]
} -result {2 4}
test canvText-8.7 {TextInsert procedure: inserting in unselected item} -setup {
- .c create text 20 20 -tag test
- focus .c
- .c focus test
+ .c create text 20 20 -tag test
+ focus .c
+ .c focus test
} -body {
.c itemconfig test -text "abcdefg"
.c select clear
@@ -587,9 +567,9 @@ test canvText-8.7 {TextInsert procedure: inserting in unselected item} -setup {
.c itemcget test -text
} -result {abcdexyzfg}
test canvText-8.8 {TextInsert procedure: inserting before cursor} -setup {
- .c create text 20 20 -tag test
- focus .c
- .c focus test
+ .c create text 20 20 -tag test
+ focus .c
+ .c focus test
} -body {
.c itemconfig test -text "abcdefg"
.c icursor test 3
@@ -597,9 +577,9 @@ test canvText-8.8 {TextInsert procedure: inserting before cursor} -setup {
.c index test insert
} -result {6}
test canvText-8.9 {TextInsert procedure: inserting after cursor} -setup {
- .c create text 20 20 -tag test
- focus .c
- .c focus test
+ .c create text 20 20 -tag test
+ focus .c
+ .c focus test
} -body {
.c itemconfig test -text "abcdefg"
.c icursor test 3
@@ -712,7 +692,7 @@ test canvText-9.15 {TextInsert procedure: cursor doesn't move} -body {
test canvText-10.1 {TextToPoint procedure} -body {
- .c create text 0 0 -tag test
+ .c create text 0 0 -tag test
.c itemconfig test -text 0 -anchor center
.c index test @0,0
} -cleanup {
@@ -721,22 +701,22 @@ test canvText-10.1 {TextToPoint procedure} -body {
test canvText-11.1 {TextToArea procedure} -setup {
- .c create text 0 0 -tag test
- focus .c
- .c focus test
-} -body {
+ .c create text 0 0 -tag test
+ focus .c
+ .c focus test
+} -body {
.c itemconfig test -text 0 -anchor center
- set res1 [.c find overlapping 0 0 1 1]
- set res2 [.c find withtag test]
- expr {$res1 eq $res2}
+ set res1 [.c find overlapping 0 0 1 1]
+ set res2 [.c find withtag test]
+ expr {$res1 eq $res2}
} -cleanup {
- .c delete test
+ .c delete test
} -result 1
test canvText-11.2 {TextToArea procedure} -setup {
- .c create text 0 0 -tag test
- focus .c
- .c focus test
-} -body {
+ .c create text 0 0 -tag test
+ focus .c
+ .c focus test
+} -body {
.c itemconfig test -text 0 -anchor center
.c find overlapping 1000 1000 1001 1001
} -cleanup {
@@ -745,7 +725,7 @@ test canvText-11.2 {TextToArea procedure} -setup {
test canvText-12.1 {ScaleText procedure} -body {
- .c create text 100 100 -tag test
+ .c create text 100 100 -tag test
.c scale all 50 50 2 2
format {%.6g %.6g} {*}[.c coords test]
} -cleanup {
@@ -763,61 +743,60 @@ test canvText-13.1 {TranslateText procedure} -body {
test canvText-14.1 {GetTextIndex procedure} -setup {
- .c create text 0 0 -tag test
- focus .c
- .c focus test
-} -body {
- .c itemconfig test -text "abcdefghijklmno" -anchor nw
- .c select from test 5
- .c select to test 8
- .c icursor test 12
- .c coords test 0 0
-
+ .c create text 0 0 -tag test
+ focus .c
+ .c focus test
+} -body {
+ .c itemconfig test -text "abcdefghijklmno" -anchor nw
+ .c select from test 5
+ .c select to test 8
+ .c icursor test 12
+ .c coords test 0 0
list [.c index test end] [.c index test insert] \
[.c index test sel.first] [.c index test sel.last] \
[.c index test @0,0] \
[.c index test -1] [.c index test 10] [.c index test 100]
} -cleanup {
- .c delete test
+ .c delete test
} -result {15 12 5 8 0 0 10 15}
test canvText-14.2 {GetTextIndex procedure: select error} -setup {
- .c create text 0 0 -tag test
- focus .c
- .c focus test
-} -body {
+ .c create text 0 0 -tag test
+ focus .c
+ .c focus test
+} -body {
.c select clear
.c index test sel.first
} -cleanup {
- .c delete test
+ .c delete test
} -returnCodes {error} -result {selection isn't in item}
test canvText-14.3 {GetTextIndex procedure: select error} -setup {
- .c create text 0 0 -tag test
- focus .c
- .c focus test
-} -body {
+ .c create text 0 0 -tag test
+ focus .c
+ .c focus test
+} -body {
.c select clear
.c index test sel.last
} -cleanup {
- .c delete test
+ .c delete test
} -returnCodes {error} -result {selection isn't in item}
test canvText-14.4 {GetTextIndex procedure: select error} -setup {
- .c create text 0 0 -tag test
- focus .c
- .c focus test
-} -body {
+ .c create text 0 0 -tag test
+ focus .c
+ .c focus test
+} -body {
.c select clear
.c index test sel.
} -cleanup {
- .c delete test
+ .c delete test
} -returnCodes {error} -result {bad index "sel."}
test canvText-14.5 {GetTextIndex procedure: bad int or unknown index} -setup {
- .c create text 0 0 -tag test
- focus .c
- .c focus test
-} -body {
+ .c create text 0 0 -tag test
+ focus .c
+ .c focus test
+} -body {
.c index test xyz
} -cleanup {
- .c delete test
+ .c delete test
} -returnCodes {error} -result {bad index "xyz"}
test canvText-14.6 {select clear errors} -setup {
.c create text 0 0 -tag test
@@ -828,54 +807,51 @@ test canvText-14.6 {select clear errors} -setup {
} -returnCodes error -result "wrong \# args: should be \".c select clear\""
test canvText-15.1 {SetTextCursor procedure} -setup {
- .c create text 0 0 -tag test
- focus .c
- .c focus test
-} -body {
- .c itemconfig test -text "abcdefghijklmno" -anchor nw
+ .c create text 0 0 -tag test
+ focus .c
+ .c focus test
+} -body {
+ .c itemconfig test -text "abcdefghijklmno" -anchor nw
.c itemconfig -text "abcdefg"
.c icursor test 3
.c index test insert
} -cleanup {
- .c delete test
+ .c delete test
} -result {3}
-
test canvText-16.1 {GetSelText procedure} -setup {
- .c create text 0 0 -tag test
- focus .c
- .c focus test
-} -body {
+ .c create text 0 0 -tag test
+ focus .c
+ .c focus test
+} -body {
.c itemconfig test -text "abcdefghijklmno" -anchor nw
.c select from test 5
.c select to test 8
selection get
} -cleanup {
- .c delete test
+ .c delete test
} -result {fghi}
-
test canvText-17.1 {TextToPostscript procedure} -setup {
.c delete all
-} -body {
- set font {Courier 12 italic}
- set ax [font measure $font 0]
- set ay [font metrics $font -linespace]
-
- set result "/Courier-Oblique findfont [font actual $font -size] scalefont ISOEncode setfont
+ set result {/Courier-Oblique findfont [font actual $font -size] scalefont ISOEncode setfont
0.000 0.000 0.000 setrgbcolor AdjustColor
-100 200 \[
+0 100 200 \[
\[(000)\]
\[(000)\]
\[(00)\]
-] $ay -0.5 0.0 0 false DrawText
+\] $ay -0.5 0 0 false DrawText
grestore
restore showpage
%%Trailer
end
%%EOF
-"
+}
+} -body {
+ set font {Courier 12 italic}
+ set ax [font measure $font 0]
+ set ay [font metrics $font -linespace]
.c config -height 300 -highlightthickness 0 -bd 0
update
.c create text 100 100 -tags test
@@ -883,8 +859,8 @@ end
.c itemconfig test -anchor n -fill black
set x [.c postscript]
set x [string range $x [string first "/Courier-Oblique" $x] end]
- expr {$x eq $result}
-} -result 1
+ expr {$x eq [subst $result] ? "ok" : $x}
+} -result ok
test canvText-18.1 {bug fix 2525, find enclosed on text with newlines} -setup {
destroy .c
@@ -898,23 +874,19 @@ test canvText-18.1 {bug fix 2525, find enclosed on text with newlines} -setup {
update
.c find enclosed 99 99 [expr $x2 + 1] [expr $y2 + 1]
} -cleanup {
- destroy .c
+ destroy .c
} -result 1
-
test canvText-19.1 {patch 1006286, leading space caused wrap under Win32} -setup {
destroy .c
-} -body {
set c [canvas .c -bg black -width 964]
pack $c
$c delete all
- after 1000 "set done 1" ; vwait done
-
+ after 100 "set done 1"; vwait done
+} -body {
set f {Arial 28 bold}
-
set s1 { Yeah-ah-ah-ah-oh-oh-oh-oh-oh-oh-oh-oh-oh-oh-oh-oh-oh-oh-oh-oh-Yow}
set s2 { Yeah ah ah ah oh oh oh oh oh oh oh oh oh oh oh oh oh oh oh oh Yow}
-
$c create text 21 18 \
-font $f \
-text $s1 \
@@ -922,8 +894,7 @@ test canvText-19.1 {patch 1006286, leading space caused wrap under Win32} -setup
-width 922 \
-anchor nw \
-tags tbox1
- eval {$c create rect} [$c bbox tbox1] -outline red
-
+ $c create rect {*}[$c bbox tbox1] -outline red
$c create text 21 160 \
-font $f \
-text $s2 \
@@ -931,38 +902,50 @@ test canvText-19.1 {patch 1006286, leading space caused wrap under Win32} -setup
-width 922 \
-anchor nw \
-tags tbox2
- eval {$c create rect} [$c bbox tbox2] -outline red
-
- after 1000 "set done 1" ; vwait done
-
+ $c create rect {*}[$c bbox tbox2] -outline red
+ after 500 "set done 1" ; vwait done
set results [list]
-
$c select from tbox2 4
$c select to tbox2 8
lappend results [selection get]
-
$c select from tbox1 4
$c select to tbox1 8
lappend results [selection get]
-
array set metrics [font metrics $f]
set x [expr {21 + [font measure $f " "] \
+ ([font measure {Arial 28 bold} "Y"] / 2)}]
set y1 [expr {18 + ($metrics(-linespace) / 2)}]
set y2 [expr {160 + ($metrics(-linespace) / 2)}]
-
lappend results [$c index tbox1 @$x,$y1]
lappend results [$c index tbox2 @$x,$y2]
-
- return $results
} -cleanup {
- destroy .c
+ destroy .c
} -result {{Yeah } Yeah- 4 4}
+test canvText-20.1 {angled text bounding box} -setup {
+ destroy .c
+ canvas .c
+ proc transpose {bbox} {
+ lassign $bbox a b c d
+ list $b $a $d $c
+ }
+} -body {
+ .c create text 2 2 -tag t -anchor center -text 0 -font {Helvetica 24}
+ set bb0 [.c bbox t]
+ .c itemconf t -angle 90
+ set bb1 [.c bbox t]
+ .c itemconf t -angle 180
+ set bb2 [.c bbox t]
+ .c itemconf t -angle 270
+ set bb3 [.c bbox t]
+ list [expr {$bb0 eq $bb2 ? "ok" : "$bb0,$bb2"}] \
+ [expr {$bb1 eq $bb3 ? "ok" : "$bb1,$bb3"}] \
+ [expr {$bb0 eq [transpose $bb1] ? "ok" : "$bb0,$bb1"}] \
+} -cleanup {
+ destroy .c
+ rename transpose {}
+} -result {ok ok ok}
# cleanup
cleanupTests
return
-
-
-
diff --git a/unix/tkUnixFont.c b/unix/tkUnixFont.c
index 405b19c..b069cd9 100644
--- a/unix/tkUnixFont.c
+++ b/unix/tkUnixFont.c
@@ -9,7 +9,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkUnixFont.c,v 1.38 2008/11/05 22:20:59 nijtmans Exp $
+ * RCS: @(#) $Id: tkUnixFont.c,v 1.39 2008/11/22 18:08:51 dkf Exp $
*/
#include "tkUnixInt.h"
@@ -139,9 +139,9 @@ typedef struct UnixFont {
*/
typedef struct EncodingAlias {
- const char *realName; /* The real name of the encoding to load if
+ const char *realName; /* The real name of the encoding to load if
* the provided name matched the pattern. */
- const char *aliasPattern; /* Pattern for encoding name, of the form that
+ const char *aliasPattern; /* Pattern for encoding name, of the form that
* is acceptable to Tcl_StringMatch. */
} EncodingAlias;
@@ -3018,6 +3018,283 @@ GetEncodingAlias(
return name;
}
+static inline XImage *
+GetImageOfText(
+ Display *display, /* Display on which to draw. */
+ Drawable drawable, /* Window or pixmap in which to draw. */
+ Tk_Font tkfont, /* Font in which characters will be drawn. */
+ const char *source, /* UTF-8 string to be displayed. Need not be
+ * '\0' terminated. All Tk meta-characters
+ * (tabs, control characters, and newlines)
+ * should be stripped out of the string that
+ * is passed to this function. If they are not
+ * stripped out, they will be displayed as
+ * regular printing characters. */
+ int numBytes, /* Number of bytes in string. */
+ int *realWidthPtr, int *realHeightPtr)
+{
+ int width, height;
+ TkFont *fontPtr = (TkFont *) tkfont;
+ Pixmap bitmap;
+ GC bitmapGC;
+ XGCValues values;
+ XImage *image;
+
+ (void) Tk_MeasureChars(tkfont, source, numBytes, -1, 0, &width);
+ height = fontPtr->fm.ascent + fontPtr->fm.descent;
+
+ bitmap = Tk_GetPixmap(display, drawable, width, height, 1);
+ values.graphics_exposures = False;
+ values.foreground = BlackPixel(display, DefaultScreen(display));
+ bitmapGC = XCreateGC(display, bitmap, GCGraphicsExposures|GCForeground,
+ &values);
+ XFillRectangle(display, bitmap, bitmapGC, 0, 0, width, height);
+
+ values.font = Tk_FontId(tkfont);
+ values.foreground = WhitePixel(display, DefaultScreen(display));
+ values.background = BlackPixel(display, DefaultScreen(display));
+ XChangeGC(display, bitmapGC, GCFont|GCForeground|GCBackground, &values);
+ Tk_DrawChars(display, bitmap, bitmapGC, tkfont, source, numBytes, 0,
+ fontPtr->fm.ascent);
+ XFreeGC(display, bitmapGC);
+
+ image = XGetImage(display, bitmap, 0, 0, width, height, AllPlanes,
+ ZPixmap);
+ Tk_FreePixmap(display, bitmap);
+
+ *realWidthPtr = width;
+ *realHeightPtr = height;
+ return image;
+}
+
+static inline XImage *
+InitDestImage(
+ Display *display,
+ Drawable drawable,
+ int width,
+ int height,
+ Pixmap *bitmapPtr)
+{
+ Pixmap bitmap;
+ XImage *image;
+ GC bitmapGC;
+ XGCValues values;
+
+ bitmap = Tk_GetPixmap(display, drawable, width, height, 1);
+ values.graphics_exposures = False;
+ values.foreground = BlackPixel(display, DefaultScreen(display));
+ bitmapGC = XCreateGC(display, bitmap, GCGraphicsExposures|GCForeground,
+ &values);
+ XFillRectangle(display, bitmap, bitmapGC, 0, 0, width, height);
+ XFreeGC(display, bitmapGC);
+
+ image = XGetImage(display, bitmap, 0, 0, width, height, AllPlanes,
+ ZPixmap);
+ *bitmapPtr = bitmap;
+ return image;
+}
+
+void
+TkpDrawAngledChars(
+ Display *display, /* Display on which to draw. */
+ Drawable drawable, /* Window or pixmap in which to draw. */
+ GC gc, /* Graphics context for drawing characters. */
+ Tk_Font tkfont, /* Font in which characters will be drawn;
+ * must be the same as font used in GC. */
+ const char *source, /* UTF-8 string to be displayed. Need not be
+ * '\0' terminated. All Tk meta-characters
+ * (tabs, control characters, and newlines)
+ * should be stripped out of the string that
+ * is passed to this function. If they are not
+ * stripped out, they will be displayed as
+ * regular printing characters. */
+ int numBytes, /* Number of bytes in string. */
+ double x, double y,
+ double angle)
+{
+ if (angle == 0.0) {
+ Tk_DrawChars(display, drawable, gc, tkfont, source, numBytes, x, y);
+ } else {
+ double sinA = sin(angle * PI/180.0), cosA = cos(angle * PI/180.0);
+ int bufHeight, bufWidth, srcWidth, srcHeight, i, j, dx, dy;
+ Pixmap buf;
+ XImage *srcImage = GetImageOfText(display, drawable, tkfont, source,
+ numBytes, &srcWidth, &srcHeight);
+ XImage *dstImage;
+ enum {Q0=1,R1,Q1,R2,Q2,R3,Q3} quadrant;
+ GC bwgc, cpgc;
+ XGCValues values;
+ int ascent = ((TkFont *) tkfont)->fm.ascent;
+
+ /*
+ * First, work out what quadrant we are operating in. We also handle
+ * the rectilinear rotations as special cases. Conceptually, there's
+ * also R0 (angle == 0.0) but that has been already handled as a
+ * special case above.
+ *
+ * R1
+ * Q1 | Q0
+ * |
+ * R2 ----+---- R0
+ * |
+ * Q2 | Q3
+ * R3
+ */
+
+ if (angle < 90.0) {
+ quadrant = Q0;
+ } else if (angle == 90.0) {
+ quadrant = R1;
+ } else if (angle < 180.0) {
+ quadrant = Q1;
+ } else if (angle == 180.0) {
+ quadrant = R2;
+ } else if (angle < 270.0) {
+ quadrant = Q2;
+ } else if (angle == 270.0) {
+ quadrant = R3;
+ } else {
+ quadrant = Q3;
+ }
+
+ if (srcImage == NULL) {
+ return;
+ }
+ bufWidth = srcWidth*fabs(cosA) + srcHeight*fabs(sinA);
+ bufHeight = srcHeight*fabs(cosA) + srcWidth*fabs(sinA);
+ dstImage = InitDestImage(display, drawable, bufWidth,bufHeight, &buf);
+ if (dstImage == NULL) {
+ Tk_FreePixmap(display, buf);
+ XDestroyImage(srcImage);
+ return;
+ }
+
+ /*
+ * Do the rotation, setting or resetting pixels in the destination
+ * image dependent on whether the corresponding pixel (after rotation
+ * to source image space) is set.
+ */
+
+ for (i=0 ; i<srcWidth ; i++) {
+ for (j=0 ; j<srcHeight ; j++) {
+ switch (quadrant) {
+ case Q0:
+ dx = floor(i*cosA + j*sinA + 0.5);
+ dy = floor(j*cosA + (srcWidth - i)*sinA + 0.5);
+ break;
+ case R1:
+ dx = j;
+ dy = srcWidth - i;
+ break;
+ case Q1:
+ dx = floor((i - srcWidth)*cosA + j*sinA + 0.5);
+ dy = floor((srcWidth-i)*sinA + (j-srcHeight)*cosA + 0.5);
+ break;
+ case R2:
+ dx = srcWidth - i;
+ dy = srcHeight - j;
+ break;
+ case Q2:
+ dx = floor((i-srcWidth)*cosA + (j-srcHeight)*sinA + 0.5);
+ dy = floor((j - srcHeight)*cosA - i*sinA + 0.5);
+ break;
+ case R3:
+ dx = srcHeight - j;
+ dy = i;
+ break;
+ default:
+ dx = floor(i*cosA + (j - srcHeight)*sinA + 0.5);
+ dy = floor(j*cosA - i*sinA + 0.5);
+ }
+
+ if (dx < 0 || dy < 0 || dx >= bufWidth || dy >= bufHeight) {
+ continue;
+ }
+ XPutPixel(dstImage, dx, dy,
+ XGetPixel(dstImage,dx,dy) | XGetPixel(srcImage,i,j));
+ }
+ }
+ XDestroyImage(srcImage);
+
+ /*
+ * Schlep the data back to the Xserver.
+ */
+
+ values.function = GXcopy;
+ values.foreground = WhitePixel(display, DefaultScreen(display));
+ values.background = BlackPixel(display, DefaultScreen(display));
+ bwgc = XCreateGC(display, buf, GCFunction|GCForeground|GCBackground,
+ &values);
+ XPutImage(display, buf, bwgc, dstImage, 0,0, 0,0, bufWidth,bufHeight);
+ XFreeGC(display, bwgc);
+ XDestroyImage(dstImage);
+
+ /*
+ * Calculate where we want to draw the text.
+ */
+
+ switch (quadrant) {
+ case Q0:
+ dx = x;
+ dy = y - srcWidth*sinA;
+ break;
+ case R1:
+ dx = x;
+ dy = y - srcWidth;
+ break;
+ case Q1:
+ dx = x + srcWidth*cosA;
+ dy = y + srcHeight*cosA - srcWidth*sinA;
+ break;
+ case R2:
+ dx = x - srcWidth;
+ dy = y - srcHeight;
+ break;
+ case Q2:
+ dx = x + srcWidth*cosA + srcHeight*sinA;
+ dy = y + srcHeight*cosA;
+ break;
+ case R3:
+ dx = x - srcHeight;
+ dy = y;
+ break;
+ default:
+ dx = x + srcHeight*sinA;
+ dy = y;
+ }
+
+ /*
+ * Apply a correction to deal with the fact that we aren't told to
+ * draw from our top-left corner but rather from the left-end of our
+ * baseline.
+ */
+
+ dx -= ascent*sinA;
+ dy -= ascent*cosA;
+
+ /*
+ * Transfer the text to the screen. This is done by using it as a mask
+ * and then drawing through that mask with the original drawing color.
+ */
+
+ values.function = GXcopy;
+ values.fill_style = FillSolid;
+ values.clip_mask = buf;
+ values.clip_x_origin = dx;
+ values.clip_y_origin = dy;
+ cpgc = XCreateGC(display, drawable,
+ GCFunction|GCFillStyle|GCClipMask|GCClipXOrigin|GCClipYOrigin,
+ &values);
+ XCopyGC(display, gc, GCForeground, cpgc);
+ XFillRectangle(display, drawable, cpgc, dx, dy, bufWidth,
+ bufHeight);
+ XFreeGC(display, cpgc);
+
+ Tk_FreePixmap(display, buf);
+ return;
+ }
+}
+
/*
* Local Variables:
* mode: c
diff --git a/unix/tkUnixRFont.c b/unix/tkUnixRFont.c
index 0a6be20..00b8095 100644
--- a/unix/tkUnixRFont.c
+++ b/unix/tkUnixRFont.c
@@ -8,7 +8,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkUnixRFont.c,v 1.26 2008/11/05 22:20:59 nijtmans Exp $
+ * RCS: @(#) $Id: tkUnixRFont.c,v 1.27 2008/11/22 18:08:51 dkf Exp $
*/
#include "tkUnixInt.h"
@@ -18,8 +18,10 @@
typedef struct {
XftFont *ftFont;
+ XftFont *ft0Font;
FcPattern *source;
FcCharSet *charset;
+ double angle;
} UnixFtFace;
typedef struct {
@@ -62,13 +64,15 @@ TkpFontPkgInit(
static XftFont *
GetFont(
UnixFtFont *fontPtr,
- FcChar32 ucs4)
+ FcChar32 ucs4,
+ double angle)
{
int i;
if (ucs4) {
for (i = 0; i < fontPtr->nfaces; i++) {
FcCharSet *charset = fontPtr->faces[i].charset;
+
if (charset && FcCharSetHasChar(charset, ucs4)) {
break;
}
@@ -79,34 +83,52 @@ GetFont(
} else {
i = 0;
}
- if (!fontPtr->faces[i].ftFont) {
- FcPattern *pat = FcFontRenderPrepare(0,
- fontPtr->pattern, fontPtr->faces[i].source);
- XftFont *ftFont = XftFontOpenPattern(fontPtr->display, pat);
+ if ((angle == 0.0 && !fontPtr->faces[i].ft0Font) || (angle != 0.0 &&
+ (!fontPtr->faces[i].ftFont || fontPtr->faces[i].angle != angle))){
+ FcPattern *pat = FcFontRenderPrepare(0, fontPtr->pattern,
+ fontPtr->faces[i].source);
+ double s = sin(angle*PI/180.0), c = cos(angle*PI/180.0);
+ FcMatrix mat = {c, -s, s, c};
+ XftFont *ftFont;
+ if (angle != 0.0) {
+ FcPatternAddMatrix(pat, FC_MATRIX, &mat);
+ }
+ ftFont = XftFontOpenPattern(fontPtr->display, pat);
if (!ftFont) {
/*
- * The previous call to XftFontOpenPattern() should not fail,
- * but sometimes does anyway. Usual cause appears to be
- * a misconfigured fontconfig installation; see [Bug 1090382].
- * Try a fallback:
+ * The previous call to XftFontOpenPattern() should not fail, but
+ * sometimes does anyway. Usual cause appears to be a
+ * misconfigured fontconfig installation; see [Bug 1090382]. Try a
+ * fallback:
*/
+
ftFont = XftFontOpen(fontPtr->display, fontPtr->screen,
- FC_FAMILY, FcTypeString, "sans",
- FC_SIZE, FcTypeDouble, 12.0,
- NULL);
+ FC_FAMILY, FcTypeString, "sans",
+ FC_SIZE, FcTypeDouble, 12.0,
+ FC_MATRIX, FcTypeMatrix, &mat,
+ NULL);
}
if (!ftFont) {
/*
- * The previous call should definitely not fail.
- * Impossible to proceed at this point.
+ * The previous call should definitely not fail. Impossible to
+ * proceed at this point.
*/
+
Tcl_Panic("Cannot find a usable font.");
}
- fontPtr->faces[i].ftFont = ftFont;
+ if (angle == 0.0) {
+ fontPtr->faces[i].ft0Font = ftFont;
+ } else {
+ if (fontPtr->faces[i].ftFont) {
+ XftFontClose(fontPtr->display, fontPtr->faces[i].ftFont);
+ }
+ fontPtr->faces[i].ftFont = ftFont;
+ fontPtr->faces[i].angle = angle;
+ }
}
- return fontPtr->faces[i].ftFont;
+ return (angle==0.0? fontPtr->faces[i].ft0Font : fontPtr->faces[i].ftFont);
}
/*
@@ -126,10 +148,10 @@ GetTkFontAttributes(
int weight, slant, size, pxsize;
double ptsize;
- (void)XftPatternGetString(ftFont->pattern, XFT_FAMILY, 0, familyPtr);
+ (void) XftPatternGetString(ftFont->pattern, XFT_FAMILY, 0, familyPtr);
if (XftPatternGetDouble(ftFont->pattern, XFT_SIZE, 0,
&ptsize) == XftResultMatch) {
- size = (int)ptsize;
+ size = (int) ptsize;
} else if (XftPatternGetInteger(ftFont->pattern, XFT_PIXEL_SIZE, 0,
&pxsize) == XftResultMatch) {
size = -pxsize;
@@ -165,7 +187,8 @@ GetTkFontAttributes(
* Fill in TkFontMetrics from an XftFont.
*/
-static void GetTkFontMetrics(
+static void
+GetTkFontMetrics(
XftFont *ftFont,
TkFontMetrics *fmPtr)
{
@@ -222,7 +245,7 @@ InitFont(
set = FcFontSort(0, pattern, FcTrue, NULL, &result);
if (!set) {
FcPatternDestroy(pattern);
- ckfree((char *)fontPtr);
+ ckfree((char *) fontPtr);
return NULL;
}
@@ -237,6 +260,7 @@ InitFont(
for (i = 0; i < set->nfont; i++) {
fontPtr->faces[i].ftFont = 0;
+ fontPtr->faces[i].ft0Font = 0;
fontPtr->faces[i].source = set->fonts[i];
if (FcPatternGetCharSet(set->fonts[i], FC_CHARSET, 0,
&charset) == FcResultMatch) {
@@ -244,6 +268,7 @@ InitFont(
} else {
fontPtr->faces[i].charset = 0;
}
+ fontPtr->faces[i].angle = 0.0;
}
fontPtr->display = Tk_Display(tkwin);
@@ -258,7 +283,8 @@ InitFont(
/*
* Fill in platform-specific fields of TkFont.
*/
- ftFont = GetFont(fontPtr, 0);
+
+ ftFont = GetFont(fontPtr, 0, 0.0);
fontPtr->font.fid = XLoadFont(Tk_Display(tkwin), "fixed");
GetTkFontAttributes(ftFont, &fontPtr->font.fa);
GetTkFontMetrics(ftFont, &fontPtr->font.fm);
@@ -272,19 +298,22 @@ FinishedWithFont(
{
Display *display = fontPtr->display;
int i;
- Tk_ErrorHandler handler = Tk_CreateErrorHandler(display, -1, -1, -1, NULL,
- (ClientData) NULL);
+ Tk_ErrorHandler handler =
+ Tk_CreateErrorHandler(display, -1, -1, -1, NULL, NULL);
for (i = 0; i < fontPtr->nfaces; i++) {
if (fontPtr->faces[i].ftFont) {
XftFontClose(fontPtr->display, fontPtr->faces[i].ftFont);
}
+ if (fontPtr->faces[i].ft0Font) {
+ XftFontClose(fontPtr->display, fontPtr->faces[i].ft0Font);
+ }
if (fontPtr->faces[i].charset) {
FcCharSetDestroy(fontPtr->faces[i].charset);
}
}
if (fontPtr->faces) {
- ckfree((char *)fontPtr->faces);
+ ckfree((char *) fontPtr->faces);
}
if (fontPtr->pattern) {
FcPatternDestroy(fontPtr->pattern);
@@ -432,14 +461,15 @@ TkpGetFontFamilies(
resultPtr = Tcl_NewListObj(0, NULL);
list = XftListFonts(Tk_Display(tkwin), Tk_ScreenNumber(tkwin),
- (char*)0, /* pattern elements */
- XFT_FAMILY, (char*)0); /* fields */
+ (char *) 0, /* pattern elements */
+ XFT_FAMILY, (char*) 0); /* fields */
for (i = 0; i < list->nfont; i++) {
char *family, **familyPtr = &family;
+
if (XftPatternGetString(list->fonts[i], XFT_FAMILY, 0, familyPtr)
- == XftResultMatch)
- {
+ == XftResultMatch) {
Tcl_Obj *strPtr = Tcl_NewStringObj(family, -1);
+
Tcl_ListObjAppendElement(NULL, resultPtr, strPtr);
}
}
@@ -517,7 +547,7 @@ TkpGetFontAttrsForChar(
/* Structure describing the logical font */
FcChar32 ucs4 = (FcChar32) c;
/* UCS-4 character to map */
- XftFont *ftFont = GetFont(fontPtr, ucs4);
+ XftFont *ftFont = GetFont(fontPtr, ucs4, 0.0);
/* Actual font used to render the character */
GetTkFontAttributes(ftFont, faPtr);
@@ -566,7 +596,7 @@ Tk_MeasureChars(
Tcl_UniChar unichar;
clen = Tcl_UtfToUniChar(source, &unichar);
- c = (FcChar32)unichar;
+ c = (FcChar32) unichar;
if (clen <= 0) {
/*
@@ -592,7 +622,7 @@ Tk_MeasureChars(
#if DEBUG_FONTSEL
string[len++] = (char) c;
#endif /* DEBUG_FONTSEL */
- ftFont = GetFont(fontPtr, c);
+ ftFont = GetFont(fontPtr, c, 0.0);
XftTextExtents32(fontPtr->display, ftFont, &c, 1, &extents);
@@ -674,8 +704,8 @@ Tk_DrawChars(
DefaultVisual(display, fontPtr->screen),
DefaultColormap(display, fontPtr->screen));
} else {
- Tk_ErrorHandler handler = Tk_CreateErrorHandler(display, -1, -1, -1,
- NULL, (ClientData) NULL);
+ Tk_ErrorHandler handler =
+ Tk_CreateErrorHandler(display, -1, -1, -1, NULL, NULL);
XftDrawChange(fontPtr->ftDraw, drawable);
Tk_DeleteErrorHandler(handler);
@@ -707,7 +737,7 @@ Tk_DrawChars(
source += clen;
numBytes -= clen;
- ftFont = GetFont(fontPtr, c);
+ ftFont = GetFont(fontPtr, c, 0.0);
if (ftFont) {
specs[nspec].font = ftFont;
specs[nspec].glyph = XftCharIndex(fontPtr->display, ftFont, c);
@@ -729,3 +759,195 @@ Tk_DrawChars(
XftDrawGlyphFontSpec(fontPtr->ftDraw, &fontPtr->color, specs, nspec);
}
}
+
+void
+TkpDrawAngledChars(
+ Display *display, /* Display on which to draw. */
+ Drawable drawable, /* Window or pixmap in which to draw. */
+ GC gc, /* Graphics context for drawing characters. */
+ Tk_Font tkfont, /* Font in which characters will be drawn;
+ * must be the same as font used in GC. */
+ const char *source, /* UTF-8 string to be displayed. Need not be
+ * '\0' terminated. All Tk meta-characters
+ * (tabs, control characters, and newlines)
+ * should be stripped out of the string that
+ * is passed to this function. If they are not
+ * stripped out, they will be displayed as
+ * regular printing characters. */
+ int numBytes, /* Number of bytes in string. */
+ double x, double y, /* Coordinates at which to place origin of
+ * string when drawing. */
+ double angle) /* What angle to put text at, in degrees. */
+{
+ const int maxCoord = 0x7FFF;/* Xft coordinates are 16 bit values */
+ const int minCoord = -1000; /* Should be good enough... */
+ UnixFtFont *fontPtr = (UnixFtFont *) tkfont;
+ XGCValues values;
+ XColor xcolor;
+#ifdef XFT_HAS_FIXED_ROTATED_PLACEMENT
+ int clen, nglyph;
+ FT_UInt glyphs[NUM_SPEC];
+ XGlyphInfo metrics;
+ XftFont *currentFtFont;
+ int originX, originY;
+
+ if (fontPtr->ftDraw == 0) {
+#if DEBUG_FONTSEL
+ printf("Switch to drawable 0x%x\n", drawable);
+#endif /* DEBUG_FONTSEL */
+ fontPtr->ftDraw = XftDrawCreate(display, drawable,
+ DefaultVisual(display, fontPtr->screen),
+ DefaultColormap(display, fontPtr->screen));
+ } else {
+ Tk_ErrorHandler handler =
+ Tk_CreateErrorHandler(display, -1, -1, -1, NULL, NULL);
+
+ XftDrawChange(fontPtr->ftDraw, drawable);
+ Tk_DeleteErrorHandler(handler);
+ }
+
+ XGetGCValues(display, gc, GCForeground, &values);
+ if (values.foreground != fontPtr->color.pixel) {
+ xcolor.pixel = values.foreground;
+ XQueryColor(display, DefaultColormap(display, fontPtr->screen),
+ &xcolor);
+ fontPtr->color.color.red = xcolor.red;
+ fontPtr->color.color.green = xcolor.green;
+ fontPtr->color.color.blue = xcolor.blue;
+ fontPtr->color.color.alpha = 0xffff;
+ fontPtr->color.pixel = values.foreground;
+ }
+
+ nglyph = 0;
+ currentFtFont = NULL;
+ originX = originY = 0; /* lint */
+
+ while (numBytes > 0 && x <= maxCoord && x >= minCoord && y <= maxCoord
+ && y >= minCoord) {
+ XftFont *ftFont;
+ FcChar32 c;
+
+ clen = FcUtf8ToUcs4((FcChar8 *) source, &c, numBytes);
+ if (clen <= 0) {
+ /*
+ * This should not happen, but it can.
+ */
+
+ return;
+ }
+ source += clen;
+ numBytes -= clen;
+
+ ftFont = GetFont(fontPtr, c, angle);
+ if (!ftFont) {
+ continue;
+ }
+
+ if (ftFont != currentFtFont || nglyph == NUM_SPEC) {
+ if (nglyph) {
+ /*
+ * We pass multiple glyphs at once to enable the code to
+ * perform better rendering of sub-pixel inter-glyph spacing.
+ * If only the current Xft implementation could make use of
+ * this information... but we'll be ready when it does!
+ */
+
+ XftDrawGlyphs(fontPtr->ftDraw, &fontPtr->color, currentFtFont,
+ originX, originY, glyphs, nglyph);
+ }
+ originX = (int) floor(x + 0.5);
+ originY = (int) floor(y + 0.5);
+ if (nglyph) {
+ XftGlyphExtents(fontPtr->display, currentFtFont, glyphs,
+ nglyph, &metrics);
+ nglyph = 0;
+ x += metrics.xOff;
+ y += metrics.yOff;
+ }
+ currentFtFont = ftFont;
+ }
+ glyphs[nglyph++] = XftCharIndex(fontPtr->display, ftFont, c);
+ }
+ if (nglyph) {
+ XftDrawGlyphs(fontPtr->ftDraw, &fontPtr->color, currentFtFont,
+ originX, originY, glyphs, nglyph);
+ }
+#else /* !XFT_HAS_FIXED_ROTATED_PLACEMENT */
+ int clen, nspec;
+ XftGlyphFontSpec specs[NUM_SPEC];
+ XGlyphInfo metrics;
+ double sinA = sin(angle * PI/180.0), cosA = cos(angle * PI/180.0);
+
+ if (fontPtr->ftDraw == 0) {
+#if DEBUG_FONTSEL
+ printf("Switch to drawable 0x%x\n", drawable);
+#endif /* DEBUG_FONTSEL */
+ fontPtr->ftDraw = XftDrawCreate(display, drawable,
+ DefaultVisual(display, fontPtr->screen),
+ DefaultColormap(display, fontPtr->screen));
+ } else {
+ Tk_ErrorHandler handler =
+ Tk_CreateErrorHandler(display, -1, -1, -1, NULL, NULL);
+
+ XftDrawChange(fontPtr->ftDraw, drawable);
+ Tk_DeleteErrorHandler(handler);
+ }
+ XGetGCValues(display, gc, GCForeground, &values);
+ if (values.foreground != fontPtr->color.pixel) {
+ xcolor.pixel = values.foreground;
+ XQueryColor(display, DefaultColormap(display, fontPtr->screen),
+ &xcolor);
+ fontPtr->color.color.red = xcolor.red;
+ fontPtr->color.color.green = xcolor.green;
+ fontPtr->color.color.blue = xcolor.blue;
+ fontPtr->color.color.alpha = 0xffff;
+ fontPtr->color.pixel = values.foreground;
+ }
+ nspec = 0;
+ while (numBytes > 0 && x <= maxCoord && x >= minCoord
+ && y <= maxCoord && y >= minCoord) {
+ XftFont *ftFont, *ft0Font;
+ FcChar32 c;
+
+ clen = FcUtf8ToUcs4((FcChar8 *) source, &c, numBytes);
+ if (clen <= 0) {
+ /*
+ * This should not happen, but it can.
+ */
+
+ return;
+ }
+ source += clen;
+ numBytes -= clen;
+
+ ftFont = GetFont(fontPtr, c, angle);
+ ft0Font = GetFont(fontPtr, c, 0.0);
+ if (ftFont && ft0Font) {
+ specs[nspec].font = ftFont;
+ specs[nspec].glyph = XftCharIndex(fontPtr->display, ftFont, c);
+ specs[nspec].x = (int) floor(x + 0.5);
+ specs[nspec].y = (int) floor(y + 0.5);
+ XftGlyphExtents(fontPtr->display, ft0Font, &specs[nspec].glyph, 1,
+ &metrics);
+ x += metrics.xOff*cosA + metrics.yOff*sinA;
+ y += metrics.yOff*cosA - metrics.xOff*sinA;
+ nspec++;
+ if (nspec == NUM_SPEC) {
+ XftDrawGlyphFontSpec(fontPtr->ftDraw, &fontPtr->color,
+ specs, nspec);
+ nspec = 0;
+ }
+ }
+ }
+ if (nspec) {
+ XftDrawGlyphFontSpec(fontPtr->ftDraw, &fontPtr->color, specs, nspec);
+ }
+#endif /* XFT_HAS_FIXED_ROTATED_PLACEMENT */
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/win/tkWinFont.c b/win/tkWinFont.c
index 755dc04..264acc2 100644
--- a/win/tkWinFont.c
+++ b/win/tkWinFont.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkWinFont.c,v 1.43 2008/11/08 22:52:29 dkf Exp $
+ * RCS: @(#) $Id: tkWinFont.c,v 1.44 2008/11/22 18:08:51 dkf Exp $
*/
#include "tkWinInt.h"
@@ -52,7 +52,7 @@ typedef struct FontFamily {
int isSymbolFont; /* Non-zero if this is a symbol font. */
int isWideFont; /* 1 if this is a double-byte font, 0
* otherwise. */
- BOOL (WINAPI *textOutProc)(HDC, int, int, TCHAR *, int);
+ BOOL (WINAPI *textOutProc)(HDC hdc, int x, int y, TCHAR *str, int len);
/* The procedure to use to draw text after it
* has been converted from UTF-8 to the
* encoding of this font. */
@@ -96,10 +96,12 @@ typedef struct FontFamily {
typedef struct SubFont {
char **fontMap; /* Pointer to font map from the FontFamily,
* cached here to save a dereference. */
- HFONT hFont; /* The specific screen font that will be used
+ HFONT hFont0; /* The specific screen font that will be used
* when displaying/measuring chars belonging
* to the FontFamily. */
FontFamily *familyPtr; /* The FontFamily for this SubFont. */
+ HFONT hFontAngled;
+ double angle;
} SubFont;
/*
@@ -125,7 +127,6 @@ typedef struct WinFont {
* attributes. Usually points to
* staticSubFonts, but may point to malloced
* space if there are lots of SubFonts. */
-
HWND hwnd; /* Toplevel window of application that owns
* this font, used for getting HDC for
* offscreen measurements. */
@@ -206,10 +207,11 @@ static void FontMapLoadPage(SubFont *subFontPtr, int row);
static int FontMapLookup(SubFont *subFontPtr, int ch);
static void FreeFontFamily(FontFamily *familyPtr);
static HFONT GetScreenFont(const TkFontAttributes *faPtr,
- const char *faceName, int pixelSize);
+ const char *faceName, int pixelSize,
+ double angle);
static void InitFont(Tk_Window tkwin, HFONT hFont,
int overstrike, WinFont *tkFontPtr);
-static void InitSubFont(HDC hdc, HFONT hFont, int base,
+static inline void InitSubFont(HDC hdc, HFONT hFont, int base,
SubFont *subFontPtr);
static int CreateNamedSystemLogFont(Tcl_Interp *interp,
Tk_Window tkwin, const char* name,
@@ -220,12 +222,15 @@ static int LoadFontRanges(HDC hdc, HFONT hFont,
USHORT **startCount, USHORT **endCount,
int *symbolPtr);
static void MultiFontTextOut(HDC hdc, WinFont *fontPtr,
- const char *source, int numBytes, int x, int y);
+ const char *source, int numBytes, int x, int y,
+ double angle);
static void ReleaseFont(WinFont *fontPtr);
-static void ReleaseSubFont(SubFont *subFontPtr);
+static inline void ReleaseSubFont(SubFont *subFontPtr);
static int SeenName(const char *name, Tcl_DString *dsPtr);
-static void SwapLong(PULONG p);
-static void SwapShort(USHORT *p);
+static inline HFONT SelectFont(HDC hdc, WinFont *fontPtr,
+ SubFont *subFontPtr, double angle);
+static inline void SwapLong(PULONG p);
+static inline void SwapShort(USHORT *p);
static int CALLBACK WinFontCanUseProc(ENUMLOGFONT *lfPtr,
NEWTEXTMETRIC *tmPtr, int fontType,
LPARAM lParam);
@@ -320,13 +325,13 @@ TkpGetNativeFont(
/*
*---------------------------------------------------------------------------
+ *
* CreateNamedSystemFont --
*
* This function registers a Windows logical font description with the Tk
* named font mechanism.
*
- * Side effects
- *
+ * Side effects:
* A new named font is added to the Tk font registry.
*
*---------------------------------------------------------------------------
@@ -341,7 +346,7 @@ CreateNamedSystemLogFont(
{
HFONT hFont;
int r;
-
+
hFont = CreateFontIndirect(logFontPtr);
r = CreateNamedSystemFont(interp, tkwin, name, hFont);
DeleteObject((HGDIOBJ)hFont);
@@ -350,13 +355,13 @@ CreateNamedSystemLogFont(
/*
*---------------------------------------------------------------------------
- * CreateNamedSystemFont --
*
- * This function registers a Windows font with the Tk
- * named font mechanism.
+ * CreateNamedSystemFont --
*
- * Side effects
+ * This function registers a Windows font with the Tk named font
+ * mechanism.
*
+ * Side effects:
* A new named font is added to the Tk font registry.
*
*---------------------------------------------------------------------------
@@ -371,7 +376,7 @@ CreateNamedSystemFont(
{
WinFont winfont;
int r;
-
+
TkDeleteNamedFont(NULL, tkwin, name);
InitFont(tkwin, hFont, 0, &winfont);
r = TkCreateNamedFont(interp, tkwin, name, &winfont.font.fa);
@@ -381,10 +386,12 @@ CreateNamedSystemFont(
/*
*---------------------------------------------------------------------------
+ *
* TkWinSystemFonts --
*
* Create some platform specific named fonts that to give access to the
- * system fonts. These are all defined for the Windows desktop parameters.
+ * system fonts. These are all defined for the Windows desktop
+ * parameters.
*
*---------------------------------------------------------------------------
*/
@@ -445,7 +452,7 @@ TkWinSetupSystemFonts(
hFont = (HFONT) GetStockObject(ANSI_FIXED_FONT);
CreateNamedSystemFont(interp, tkwin, "TkFixedFont", hFont);
- /*
+ /*
* Setup the remaining standard Tk font names as named fonts.
*/
@@ -550,7 +557,7 @@ TkpGetFontFromAttributes(
ReleaseDC(hwnd, hdc);
hFont = GetScreenFont(faPtr, faceName,
- TkFontGetPixels(tkwin, faPtr->size));
+ TkFontGetPixels(tkwin, faPtr->size), 0.0);
if (tkFontPtr == NULL) {
fontPtr = (WinFont *) ckalloc(sizeof(WinFont));
} else {
@@ -728,7 +735,7 @@ TkpGetFontAttrsForChar(
Tk_Window tkwin, /* Window on the font's display */
Tk_Font tkfont, /* Font to query */
Tcl_UniChar c, /* Character of interest */
- TkFontAttributes* faPtr) /* Output: Font attributes */
+ TkFontAttributes *faPtr) /* Output: Font attributes */
{
WinFont *fontPtr = (WinFont *) tkfont;
/* Structure describing the logical font */
@@ -736,12 +743,12 @@ TkpGetFontAttrsForChar(
/* GDI device context */
SubFont *lastSubFontPtr = &fontPtr->subFontArray[0];
/* Pointer to subfont array in case
- * FindSubFontForChar needs to fix up
- * the memory allocation */
- SubFont *thisSubFontPtr = FindSubFontForChar(fontPtr, c,
- &lastSubFontPtr);
- /* Pointer to the subfont to use for
- * the given character */
+ * FindSubFontForChar needs to fix up the
+ * memory allocation */
+ SubFont *thisSubFontPtr =
+ FindSubFontForChar(fontPtr, c, &lastSubFontPtr);
+ /* Pointer to the subfont to use for the given
+ * character */
FontFamily *familyPtr = thisSubFontPtr->familyPtr;
HFONT oldfont; /* Saved font from the device context */
TEXTMETRIC tm; /* Font metrics of the selected subfont */
@@ -750,7 +757,7 @@ TkpGetFontAttrsForChar(
* Get the font attributes.
*/
- oldfont = SelectObject(hdc, thisSubFontPtr->hFont);
+ oldfont = SelectObject(hdc, thisSubFontPtr->hFont0);
GetTextMetrics(hdc, &tm);
SelectObject(hdc, oldfont);
ReleaseDC(fontPtr->hwnd, hdc);
@@ -828,7 +835,7 @@ Tk_MeasureChars(
hdc = GetDC(fontPtr->hwnd);
lastSubFontPtr = &fontPtr->subFontArray[0];
- oldFont = SelectObject(hdc, lastSubFontPtr->hFont);
+ oldFont = SelectObject(hdc, lastSubFontPtr->hFont0);
/*
* A three step process:
@@ -863,7 +870,7 @@ Tk_MeasureChars(
lastSubFontPtr = thisSubFontPtr;
start = p;
- SelectObject(hdc, lastSubFontPtr->hFont);
+ SelectObject(hdc, lastSubFontPtr->hFont0);
}
p = next;
}
@@ -1091,8 +1098,156 @@ Tk_DrawChars(
SetROP2(dc, tkpWinRopModes[gc->function]);
if ((gc->clip_mask != None) &&
- ((TkpClipMask*)gc->clip_mask)->type == TKP_CLIP_REGION) {
- SelectClipRgn(dc, (HRGN)((TkpClipMask*)gc->clip_mask)->value.region);
+ ((TkpClipMask *) gc->clip_mask)->type == TKP_CLIP_REGION) {
+ SelectClipRgn(dc, (HRGN)((TkpClipMask *)gc->clip_mask)->value.region);
+ }
+
+ if ((gc->fill_style == FillStippled
+ || gc->fill_style == FillOpaqueStippled)
+ && gc->stipple != None) {
+ TkWinDrawable *twdPtr = (TkWinDrawable *) gc->stipple;
+ HBRUSH oldBrush, stipple;
+ HBITMAP oldBitmap, bitmap;
+ HDC dcMem;
+ TEXTMETRIC tm;
+ SIZE size;
+
+ if (twdPtr->type != TWD_BITMAP) {
+ Tcl_Panic("unexpected drawable type in stipple");
+ }
+
+ /*
+ * Select stipple pattern into destination dc.
+ */
+
+ dcMem = CreateCompatibleDC(dc);
+
+ stipple = CreatePatternBrush(twdPtr->bitmap.handle);
+ SetBrushOrgEx(dc, gc->ts_x_origin, gc->ts_y_origin, NULL);
+ oldBrush = SelectObject(dc, stipple);
+
+ SetTextAlign(dcMem, TA_LEFT | TA_BASELINE);
+ SetTextColor(dcMem, gc->foreground);
+ SetBkMode(dcMem, TRANSPARENT);
+ SetBkColor(dcMem, RGB(0, 0, 0));
+
+ /*
+ * Compute the bounding box and create a compatible bitmap.
+ */
+
+ GetTextExtentPoint(dcMem, source, numBytes, &size);
+ GetTextMetrics(dcMem, &tm);
+ size.cx -= tm.tmOverhang;
+ bitmap = CreateCompatibleBitmap(dc, size.cx, size.cy);
+ oldBitmap = SelectObject(dcMem, bitmap);
+
+ /*
+ * The following code is tricky because fonts are rendered in multiple
+ * colors. First we draw onto a black background and copy the white
+ * bits. Then we draw onto a white background and copy the black bits.
+ * Both the foreground and background bits of the font are ANDed with
+ * the stipple pattern as they are copied.
+ */
+
+ PatBlt(dcMem, 0, 0, size.cx, size.cy, BLACKNESS);
+ MultiFontTextOut(dc, fontPtr, source, numBytes, x, y, 0.0);
+ BitBlt(dc, x, y - tm.tmAscent, size.cx, size.cy, dcMem,
+ 0, 0, 0xEA02E9);
+ PatBlt(dcMem, 0, 0, size.cx, size.cy, WHITENESS);
+ MultiFontTextOut(dc, fontPtr, source, numBytes, x, y, 0.0);
+ BitBlt(dc, x, y - tm.tmAscent, size.cx, size.cy, dcMem,
+ 0, 0, 0x8A0E06);
+
+ /*
+ * Destroy the temporary bitmap and restore the device context.
+ */
+
+ SelectObject(dcMem, oldBitmap);
+ DeleteObject(bitmap);
+ DeleteDC(dcMem);
+ SelectObject(dc, oldBrush);
+ DeleteObject(stipple);
+ } else if (gc->function == GXcopy) {
+ SetTextAlign(dc, TA_LEFT | TA_BASELINE);
+ SetTextColor(dc, gc->foreground);
+ SetBkMode(dc, TRANSPARENT);
+ MultiFontTextOut(dc, fontPtr, source, numBytes, x, y, 0.0);
+ } else {
+ HBITMAP oldBitmap, bitmap;
+ HDC dcMem;
+ TEXTMETRIC tm;
+ SIZE size;
+
+ dcMem = CreateCompatibleDC(dc);
+
+ SetTextAlign(dcMem, TA_LEFT | TA_BASELINE);
+ SetTextColor(dcMem, gc->foreground);
+ SetBkMode(dcMem, TRANSPARENT);
+ SetBkColor(dcMem, RGB(0, 0, 0));
+
+ /*
+ * Compute the bounding box and create a compatible bitmap.
+ */
+
+ GetTextExtentPoint(dcMem, source, numBytes, &size);
+ GetTextMetrics(dcMem, &tm);
+ size.cx -= tm.tmOverhang;
+ bitmap = CreateCompatibleBitmap(dc, size.cx, size.cy);
+ oldBitmap = SelectObject(dcMem, bitmap);
+
+ MultiFontTextOut(dcMem, fontPtr, source, numBytes, 0, tm.tmAscent,
+ 0.0);
+ BitBlt(dc, x, y - tm.tmAscent, size.cx, size.cy, dcMem,
+ 0, 0, (DWORD) tkpWinBltModes[gc->function]);
+
+ /*
+ * Destroy the temporary bitmap and restore the device context.
+ */
+
+ SelectObject(dcMem, oldBitmap);
+ DeleteObject(bitmap);
+ DeleteDC(dcMem);
+ }
+ TkWinReleaseDrawableDC(drawable, dc, &state);
+}
+
+void
+TkpDrawAngledChars(
+ Display *display, /* Display on which to draw. */
+ Drawable drawable, /* Window or pixmap in which to draw. */
+ GC gc, /* Graphics context for drawing characters. */
+ Tk_Font tkfont, /* Font in which characters will be drawn;
+ * must be the same as font used in GC. */
+ const char *source, /* UTF-8 string to be displayed. Need not be
+ * '\0' terminated. All Tk meta-characters
+ * (tabs, control characters, and newlines)
+ * should be stripped out of the string that
+ * is passed to this function. If they are not
+ * stripped out, they will be displayed as
+ * regular printing characters. */
+ int numBytes, /* Number of bytes in string. */
+ double x, double y, /* Coordinates at which to place origin of
+ * string when drawing. */
+ double angle)
+{
+ HDC dc;
+ WinFont *fontPtr;
+ TkWinDCState state;
+
+ fontPtr = (WinFont *) gc->font;
+ display->request++;
+
+ if (drawable == None) {
+ return;
+ }
+
+ dc = TkWinGetDrawableDC(display, drawable, &state);
+
+ SetROP2(dc, tkpWinRopModes[gc->function]);
+
+ if ((gc->clip_mask != None) &&
+ ((TkpClipMask *) gc->clip_mask)->type == TKP_CLIP_REGION) {
+ SelectClipRgn(dc, (HRGN)((TkpClipMask *)gc->clip_mask)->value.region);
}
if ((gc->fill_style == FillStippled
@@ -1143,11 +1298,11 @@ Tk_DrawChars(
*/
PatBlt(dcMem, 0, 0, size.cx, size.cy, BLACKNESS);
- MultiFontTextOut(dc, fontPtr, source, numBytes, x, y);
+ MultiFontTextOut(dc, fontPtr, source, numBytes, x, y, angle);
BitBlt(dc, x, y - tm.tmAscent, size.cx, size.cy, dcMem,
0, 0, 0xEA02E9);
PatBlt(dcMem, 0, 0, size.cx, size.cy, WHITENESS);
- MultiFontTextOut(dc, fontPtr, source, numBytes, x, y);
+ MultiFontTextOut(dc, fontPtr, source, numBytes, x, y, angle);
BitBlt(dc, x, y - tm.tmAscent, size.cx, size.cy, dcMem,
0, 0, 0x8A0E06);
@@ -1164,7 +1319,7 @@ Tk_DrawChars(
SetTextAlign(dc, TA_LEFT | TA_BASELINE);
SetTextColor(dc, gc->foreground);
SetBkMode(dc, TRANSPARENT);
- MultiFontTextOut(dc, fontPtr, source, numBytes, x, y);
+ MultiFontTextOut(dc, fontPtr, source, numBytes, x, y, angle);
} else {
HBITMAP oldBitmap, bitmap;
HDC dcMem;
@@ -1188,7 +1343,8 @@ Tk_DrawChars(
bitmap = CreateCompatibleBitmap(dc, size.cx, size.cy);
oldBitmap = SelectObject(dcMem, bitmap);
- MultiFontTextOut(dcMem, fontPtr, source, numBytes, 0, tm.tmAscent);
+ MultiFontTextOut(dcMem, fontPtr, source, numBytes, 0, tm.tmAscent,
+ angle);
BitBlt(dc, x, y - tm.tmAscent, size.cx, size.cy, dcMem,
0, 0, (DWORD) tkpWinBltModes[gc->function]);
@@ -1243,8 +1399,8 @@ TkpDrawCharsInContext(
* drawing. */
{
(void) numBytes; /*unused*/
- Tk_DrawChars(display, drawable, gc, tkfont,
- source + rangeStart, rangeLength, x, y);
+ Tk_DrawChars(display, drawable, gc, tkfont, source + rangeStart,
+ rangeLength, x, y);
}
/*
@@ -1274,8 +1430,9 @@ MultiFontTextOut(
* following string. */
const char *source, /* Potentially multilingual UTF-8 string. */
int numBytes, /* Length of string in bytes. */
- int x, int y) /* Coordinates at which to place origin of
+ int x, int y, /* Coordinates at which to place origin of
* string when drawing. */
+ double angle)
{
Tcl_UniChar ch;
SIZE size;
@@ -1287,7 +1444,7 @@ MultiFontTextOut(
TEXTMETRIC tm;
lastSubFontPtr = &fontPtr->subFontArray[0];
- oldFont = SelectObject(hdc, lastSubFontPtr->hFont);
+ oldFont = SelectFont(hdc, fontPtr, lastSubFontPtr, angle);
GetTextMetrics(hdc, &tm);
end = source + numBytes;
@@ -1311,7 +1468,7 @@ MultiFontTextOut(
}
lastSubFontPtr = thisSubFontPtr;
source = p;
- SelectObject(hdc, lastSubFontPtr->hFont);
+ SelectFont(hdc, fontPtr, lastSubFontPtr, angle);
GetTextMetrics(hdc, &tm);
}
p = next;
@@ -1327,6 +1484,31 @@ MultiFontTextOut(
}
SelectObject(hdc, oldFont);
}
+
+static inline HFONT
+SelectFont(
+ HDC hdc,
+ WinFont *fontPtr,
+ SubFont *subFontPtr,
+ double angle)
+{
+ if (angle == 0.0) {
+ return SelectObject(hdc, subFontPtr->hFont0);
+ } else if (angle == subFontPtr->angle) {
+ return SelectObject(hdc, subFontPtr->hFontAngled);
+ } else {
+ if (subFontPtr->hFontAngled) {
+ DeleteObject(subFontPtr->hFontAngled);
+ }
+ subFontPtr->hFontAngled = GetScreenFont(&fontPtr->font.fa,
+ subFontPtr->familyPtr->faceName, fontPtr->pixelSize, angle);
+ if (subFontPtr->hFontAngled == NULL) {
+ return SelectObject(hdc, subFontPtr->hFont0);
+ }
+ subFontPtr->angle = angle;
+ return SelectObject(hdc, subFontPtr->hFontAngled);
+ }
+}
/*
*---------------------------------------------------------------------------
@@ -1501,7 +1683,7 @@ ReleaseFont(
*-------------------------------------------------------------------------
*/
-static void
+static inline void
InitSubFont(
HDC hdc, /* HDC in which font can be selected. */
HFONT hFont, /* The screen font. */
@@ -1510,9 +1692,11 @@ InitSubFont(
SubFont *subFontPtr) /* Filled with SubFont constructed from above
* attributes. */
{
- subFontPtr->hFont = hFont;
+ subFontPtr->hFont0 = hFont;
subFontPtr->familyPtr = AllocFontFamily(hdc, hFont, base);
subFontPtr->fontMap = subFontPtr->familyPtr->fontMap;
+ subFontPtr->hFontAngled = NULL;
+ subFontPtr->angle = 0.0;
}
/*
@@ -1532,11 +1716,14 @@ InitSubFont(
*---------------------------------------------------------------------------
*/
-static void
+static inline void
ReleaseSubFont(
SubFont *subFontPtr) /* The SubFont to delete. */
{
- DeleteObject(subFontPtr->hFont);
+ DeleteObject(subFontPtr->hFont0);
+ if (subFontPtr->hFontAngled) {
+ DeleteObject(subFontPtr->hFontAngled);
+ }
FreeFontFamily(subFontPtr->familyPtr);
}
@@ -2047,7 +2234,8 @@ FontMapLoadPage(
if (endCount[j] >= i) {
if (startCount[j] <= i) {
bitOffset = i & (FONTMAP_BITSPERPAGE - 1);
- subFontPtr->fontMap[row][bitOffset >> 3] |= 1 << (bitOffset & 7);
+ subFontPtr->fontMap[row][bitOffset >> 3] |=
+ 1 << (bitOffset & 7);
}
break;
}
@@ -2236,7 +2424,8 @@ CanUseFallback(
* Load this font and see if it has the desired character.
*/
- hFont = GetScreenFont(&fontPtr->font.fa, faceName, fontPtr->pixelSize);
+ hFont = GetScreenFont(&fontPtr->font.fa, faceName, fontPtr->pixelSize,
+ 0.0);
InitSubFont(hdc, hFont, 0, &subFont);
if (((ch < 256) && (subFont.familyPtr->isSymbolFont))
|| (FontMapLookup(&subFont, ch) == 0)) {
@@ -2252,9 +2441,9 @@ CanUseFallback(
if (fontPtr->numSubFonts >= SUBFONT_SPACE) {
SubFont *newPtr;
- newPtr = (SubFont *) ckalloc(sizeof(SubFont)
- * (fontPtr->numSubFonts + 1));
- memcpy((char *) newPtr, fontPtr->subFontArray,
+ newPtr = (SubFont *)
+ ckalloc(sizeof(SubFont) * (fontPtr->numSubFonts + 1));
+ memcpy(newPtr, fontPtr->subFontArray,
fontPtr->numSubFonts * sizeof(SubFont));
if (fontPtr->subFontArray != fontPtr->staticSubFonts) {
ckfree((char *) fontPtr->subFontArray);
@@ -2296,8 +2485,10 @@ GetScreenFont(
/* Desired font attributes for new HFONT. */
const char *faceName, /* Overrides font family specified in font
* attributes. */
- int pixelSize) /* Overrides size specified in font
+ int pixelSize, /* Overrides size specified in font
* attributes. */
+ double angle) /* What is the desired orientation of the
+ * font. */
{
Tcl_DString ds;
HFONT hFont;
@@ -2306,8 +2497,8 @@ GetScreenFont(
memset(&lf, 0, sizeof(lf));
lf.lfHeight = -pixelSize;
lf.lfWidth = 0;
- lf.lfEscapement = 0;
- lf.lfOrientation = 0;
+ lf.lfEscapement = (int) floor(angle * 10 + 0.5);
+ lf.lfOrientation = (int) floor(angle * 10 + 0.5);
lf.lfWeight = (faPtr->weight == TK_FW_NORMAL) ? FW_NORMAL : FW_BOLD;
lf.lfItalic = faPtr->slant;
lf.lfUnderline = faPtr->underline;
@@ -2725,14 +2916,14 @@ LoadFontRanges(
*-------------------------------------------------------------------------
*/
-static void
+static inline void
SwapShort(
PUSHORT p)
{
*p = (SHORT)(HIBYTE(*p) + (LOBYTE(*p) << 8));
}
-static void
+static inline void
SwapLong(
PULONG p)
{