aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornyamatongwe <devnull@localhost>2011-09-09 16:59:38 +1000
committernyamatongwe <devnull@localhost>2011-09-09 16:59:38 +1000
commite00160f45844f28985e11540aa62a96a2fcb0146 (patch)
tree4f4c1f6692ed01d6f6c4f5361935a07328158131
parentec3e2ca261c8a98fd0786c151a737ad12ed637f4 (diff)
parent8ab9f0c333bb0c9ef944d91d940c516b65b0384e (diff)
downloadscintilla-mirror-e00160f45844f28985e11540aa62a96a2fcb0146.tar.gz
Merge with main repository.
-rw-r--r--cocoa/PlatCocoa.h24
-rw-r--r--cocoa/PlatCocoa.mm53
-rw-r--r--cocoa/QuartzTextStyleAttribute.h3
-rw-r--r--cocoa/ScintillaCocoa.mm4
-rw-r--r--cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj4
-rw-r--r--cocoa/ScintillaTest/AppController.mm2
-rw-r--r--doc/ScintillaDoc.html34
-rw-r--r--gtk/PlatGTK.cxx163
-rw-r--r--gtk/ScintillaGTK.cxx8
-rw-r--r--include/Platform.h88
-rw-r--r--include/Scintilla.h12
-rw-r--r--include/Scintilla.iface28
-rw-r--r--src/AutoComplete.cxx4
-rw-r--r--src/AutoComplete.h2
-rw-r--r--src/CallTip.cxx8
-rw-r--r--src/CallTip.h2
-rw-r--r--src/Editor.cxx106
-rw-r--r--src/Editor.h8
-rw-r--r--src/FontQuality.h3
-rw-r--r--src/PositionCache.cxx14
-rw-r--r--src/PositionCache.h10
-rw-r--r--src/ScintillaBase.cxx3
-rw-r--r--src/Style.cxx20
-rw-r--r--src/Style.h8
-rw-r--r--src/ViewStyle.cxx22
-rw-r--r--src/ViewStyle.h3
-rw-r--r--win32/PlatWin.cxx1214
-rw-r--r--win32/PlatWin.h13
-rw-r--r--win32/ScintillaWin.cxx180
29 files changed, 1594 insertions, 449 deletions
diff --git a/cocoa/PlatCocoa.h b/cocoa/PlatCocoa.h
index 0e3c5f2e2..7f6a59705 100644
--- a/cocoa/PlatCocoa.h
+++ b/cocoa/PlatCocoa.h
@@ -96,20 +96,20 @@ public:
void DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage);
void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back);
void Copy(PRectangle rc, Scintilla::Point from, Surface &surfaceSource);
- void DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore,
+ void DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore,
ColourAllocated back);
- void DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore,
+ void DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore,
ColourAllocated back);
- void DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore);
- void MeasureWidths(Font &font_, const char *s, int len, int *positions);
- int WidthText(Font &font_, const char *s, int len);
- int WidthChar(Font &font_, char ch);
- int Ascent(Font &font_);
- int Descent(Font &font_);
- int InternalLeading(Font &font_);
- int ExternalLeading(Font &font_);
- int Height(Font &font_);
- int AverageCharWidth(Font &font_);
+ void DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore);
+ void MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions);
+ XYPOSITION WidthText(Font &font_, const char *s, int len);
+ XYPOSITION WidthChar(Font &font_, char ch);
+ XYPOSITION Ascent(Font &font_);
+ XYPOSITION Descent(Font &font_);
+ XYPOSITION InternalLeading(Font &font_);
+ XYPOSITION ExternalLeading(Font &font_);
+ XYPOSITION Height(Font &font_);
+ XYPOSITION AverageCharWidth(Font &font_);
int SetPalette(Scintilla::Palette *pal, bool inBackGround);
void SetClip(PRectangle rc);
diff --git a/cocoa/PlatCocoa.mm b/cocoa/PlatCocoa.mm
index fd66f671f..ce112f853 100644
--- a/cocoa/PlatCocoa.mm
+++ b/cocoa/PlatCocoa.mm
@@ -156,8 +156,7 @@ static int FontCharacterSet(Font &f) {
/**
* Creates a CTFontRef with the given properties.
*/
-void Font::Create(const char *faceName, int characterSet, int size, bool bold, bool italic,
- int /* extraFontFlag */)
+void Font::Create(const FontParameters &fp)
{
Release();
@@ -165,9 +164,9 @@ void Font::Create(const char *faceName, int characterSet, int size, bool bold, b
fid = style;
// Create the font with attributes
- QuartzFont font(faceName, strlen(faceName), size, bold, italic);
+ QuartzFont font(fp.faceName, strlen(fp.faceName), fp.size, fp.weight, fp.italic);
CTFontRef fontRef = font.getFontID();
- style->setFontRef(fontRef, characterSet);
+ style->setFontRef(fontRef, fp.characterSet);
}
//--------------------------------------------------------------------------------------------------
@@ -507,6 +506,9 @@ void SurfaceImpl::FillRectangle(PRectangle rc, ColourAllocated back)
if (gc)
{
FillColour(back);
+ // Snap rectangle boundaries to nearest int
+ rc.left = lround(rc.left);
+ rc.right = lround(rc.right);
CGRect rect = PRectangleToCGRect(rc);
CGContextFillRect(gc, rect);
}
@@ -641,7 +643,10 @@ void Scintilla::SurfaceImpl::AlphaRectangle(PRectangle rc, int /*cornerSize*/, C
{
if ( gc ) {
ColourDesired colour( fill.AsLong() );
-
+
+ // Snap rectangle boundaries to nearest int
+ rc.left = lround(rc.left);
+ rc.right = lround(rc.right);
// Set the Fill color to match
CGContextSetRGBFillColor( gc, colour.GetRed() / 255.0, colour.GetGreen() / 255.0, colour.GetBlue() / 255.0, alphaFill / 255.0 );
CGRect rect = PRectangleToCGRect( rc );
@@ -836,7 +841,7 @@ void SurfaceImpl::Copy(PRectangle rc, Scintilla::Point from, Surface &surfaceSou
//--------------------------------------------------------------------------------------------------
-void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len,
+void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len,
ColourAllocated fore, ColourAllocated back)
{
FillRectangle(rc, back);
@@ -845,7 +850,7 @@ void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const ch
//--------------------------------------------------------------------------------------------------
-void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len,
+void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len,
ColourAllocated fore, ColourAllocated back)
{
CGContextSaveGState(gc);
@@ -913,7 +918,7 @@ CFStringEncoding EncodingFromCharacterSet(bool unicode, int characterSet)
}
}
-void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len,
+void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len,
ColourAllocated fore)
{
CFStringEncoding encoding = EncodingFromCharacterSet(unicodeMode, FontCharacterSet(font_));
@@ -943,7 +948,7 @@ static size_t utf8LengthFromLead(unsigned char uch) {
//--------------------------------------------------------------------------------------------------
-void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positions)
+void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions)
{
CFStringEncoding encoding = EncodingFromCharacterSet(unicodeMode, FontCharacterSet(font_));
textLayout->setText (reinterpret_cast<const UInt8*>(s), len, encoding, *reinterpret_cast<QuartzTextStyle*>(font_.GetID()));
@@ -962,7 +967,7 @@ void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positi
size_t codeUnits = (lenChar < 4) ? 1 : 2;
CGFloat xPosition = CTLineGetOffsetForStringIndex(mLine, ui+1, NULL);
for (unsigned int bytePos=0; (bytePos<lenChar) && (i<len); bytePos++) {
- positions[i++] = static_cast<int>(lround(xPosition));
+ positions[i++] = xPosition;
}
ui += codeUnits;
}
@@ -978,20 +983,20 @@ void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positi
size_t lenChar = Platform::IsDBCSLeadByte(codePage, s[i]) ? 2 : 1;
CGFloat xPosition = CTLineGetOffsetForStringIndex(mLine, ui+1, NULL);
for (unsigned int bytePos=0; (bytePos<lenChar) && (i<len); bytePos++) {
- positions[i++] = static_cast<int>(lround(xPosition));
+ positions[i++] = xPosition;
}
ui++;
}
} else { // Single byte encoding
for (int i=0;i<len;i++) {
CGFloat xPosition = CTLineGetOffsetForStringIndex(mLine, i+1, NULL);
- positions[i] = static_cast<int>(lround(xPosition));
+ positions[i] = xPosition;
}
}
}
-int SurfaceImpl::WidthText(Font &font_, const char *s, int len) {
+XYPOSITION SurfaceImpl::WidthText(Font &font_, const char *s, int len) {
if (font_.GetID())
{
CFStringEncoding encoding = EncodingFromCharacterSet(unicodeMode, FontCharacterSet(font_));
@@ -1002,7 +1007,7 @@ int SurfaceImpl::WidthText(Font &font_, const char *s, int len) {
return 1;
}
-int SurfaceImpl::WidthChar(Font &font_, char ch) {
+XYPOSITION SurfaceImpl::WidthChar(Font &font_, char ch) {
char str[2] = { ch, '\0' };
if (font_.GetID())
{
@@ -1019,7 +1024,7 @@ int SurfaceImpl::WidthChar(Font &font_, char ch) {
const char sizeString[] = "`~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890"
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
-int SurfaceImpl::Ascent(Font &font_) {
+XYPOSITION SurfaceImpl::Ascent(Font &font_) {
if (!font_.GetID())
return 1;
@@ -1028,7 +1033,7 @@ int SurfaceImpl::Ascent(Font &font_) {
}
-int SurfaceImpl::Descent(Font &font_) {
+XYPOSITION SurfaceImpl::Descent(Font &font_) {
if (!font_.GetID())
return 1;
@@ -1037,11 +1042,11 @@ int SurfaceImpl::Descent(Font &font_) {
}
-int SurfaceImpl::InternalLeading(Font &) {
+XYPOSITION SurfaceImpl::InternalLeading(Font &) {
return 0;
}
-int SurfaceImpl::ExternalLeading(Font &font_) {
+XYPOSITION SurfaceImpl::ExternalLeading(Font &font_) {
if (!font_.GetID())
return 1;
@@ -1050,13 +1055,13 @@ int SurfaceImpl::ExternalLeading(Font &font_) {
}
-int SurfaceImpl::Height(Font &font_) {
+XYPOSITION SurfaceImpl::Height(Font &font_) {
int ht = Ascent(font_) + Descent(font_);
return ht;
}
-int SurfaceImpl::AverageCharWidth(Font &font_) {
+XYPOSITION SurfaceImpl::AverageCharWidth(Font &font_) {
if (!font_.GetID())
return 1;
@@ -1089,7 +1094,7 @@ void SurfaceImpl::SetDBCSMode(int codePage_) {
codePage = codePage_;
}
-Surface *Surface::Allocate()
+Surface *Surface::Allocate(int)
{
return new SurfaceImpl();
}
@@ -1368,7 +1373,7 @@ static NSImage* ImageFromXPM(XPM* pxpm)
const int width = pxpm->GetWidth();
const int height = pxpm->GetHeight();
PRectangle rcxpm(0, 0, width, height);
- Surface* surfaceXPM = Surface::Allocate();
+ Surface* surfaceXPM = Surface::Allocate(SC_TECHNOLOGY_DEFAULT);
if (surfaceXPM)
{
surfaceXPM->InitPixMap(width, height, NULL, NULL);
@@ -1510,7 +1515,7 @@ public:
// ListBox methods
void SetFont(Font& font);
- void Create(Window& parent, int ctrlID, Scintilla::Point pt, int lineHeight_, bool unicodeMode_);
+ void Create(Window& parent, int ctrlID, Scintilla::Point pt, int lineHeight_, bool unicodeMode_, int technology_);
void SetAverageCharWidth(int width);
void SetVisibleRows(int rows);
int GetVisibleRows() const;
@@ -1595,7 +1600,7 @@ ListBox* ListBox::Allocate()
}
void ListBoxImpl::Create(Window& /*parent*/, int /*ctrlID*/, Scintilla::Point pt,
- int lineHeight_, bool unicodeMode_)
+ int lineHeight_, bool unicodeMode_, int)
{
lineHeight = lineHeight_;
unicodeMode = unicodeMode_;
diff --git a/cocoa/QuartzTextStyleAttribute.h b/cocoa/QuartzTextStyleAttribute.h
index 33c49281c..b9698645e 100644
--- a/cocoa/QuartzTextStyleAttribute.h
+++ b/cocoa/QuartzTextStyleAttribute.h
@@ -16,12 +16,13 @@ class QuartzFont
{
public:
/** Create a font style from a name. */
- QuartzFont( const char* name, size_t length, float size, bool bold, bool italic )
+ QuartzFont( const char* name, size_t length, float size, int weight, bool italic )
{
assert( name != NULL && length > 0 && name[length] == '\0' );
CFStringRef fontName = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingMacRoman);
assert(fontName != NULL);
+ bool bold = weight > SC_WEIGHT_NORMAL;
if (bold || italic)
{
diff --git a/cocoa/ScintillaCocoa.mm b/cocoa/ScintillaCocoa.mm
index 089568d66..7927652a7 100644
--- a/cocoa/ScintillaCocoa.mm
+++ b/cocoa/ScintillaCocoa.mm
@@ -702,7 +702,7 @@ void ScintillaCocoa::Paste(bool forceRectangular)
void ScintillaCocoa::CTPaint(void* gc, NSRect rc) {
#pragma unused(rc)
- Surface *surfaceWindow = Surface::Allocate();
+ Surface *surfaceWindow = Surface::Allocate(SC_TECHNOLOGY_DEFAULT);
if (surfaceWindow) {
surfaceWindow->Init(gc, wMain.GetID());
surfaceWindow->SetUnicodeMode(SC_CP_UTF8 == ct.codePage);
@@ -1251,7 +1251,7 @@ void ScintillaCocoa::SyncPaint(void* gc, PRectangle rc)
rcPaint = rc;
PRectangle rcText = GetTextRectangle();
paintingAllText = rcPaint.Contains(rcText);
- Surface *sw = Surface::Allocate();
+ Surface *sw = Surface::Allocate(SC_TECHNOLOGY_DEFAULT);
if (sw)
{
sw->Init(gc, wMain.GetID());
diff --git a/cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj b/cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj
index 7765983a8..5ec9eb93a 100644
--- a/cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj
+++ b/cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj
@@ -955,7 +955,7 @@
SCI_LEXER,
);
GCC_VERSION = com.apple.compilers.llvmgcc42;
- GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = NO;
GCC_WARN_UNKNOWN_PRAGMAS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_LABEL = YES;
@@ -984,7 +984,7 @@
SCI_LEXER,
);
GCC_VERSION = com.apple.compilers.llvmgcc42;
- GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = NO;
GCC_WARN_UNKNOWN_PRAGMAS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_LABEL = YES;
diff --git a/cocoa/ScintillaTest/AppController.mm b/cocoa/ScintillaTest/AppController.mm
index 24941ffe2..294704f02 100644
--- a/cocoa/ScintillaTest/AppController.mm
+++ b/cocoa/ScintillaTest/AppController.mm
@@ -116,7 +116,7 @@ const char user_keywords[] = // Definition of own keywords, not used by MySQL.
[mEditor setReferenceProperty: SCI_SETKEYWORDS parameter: 7 value: user_keywords];
// Colors and styles for various syntactic elements. First the default style.
- [mEditor setStringProperty: SCI_STYLESETFONT parameter: STYLE_DEFAULT value: @"Andale Mono"];
+ [mEditor setStringProperty: SCI_STYLESETFONT parameter: STYLE_DEFAULT value: @"Helvetica"];
// [mEditor setStringProperty: SCI_STYLESETFONT parameter: STYLE_DEFAULT value: @"Monospac821 BT"]; // Very pleasing programmer's font.
[mEditor setGeneralProperty: SCI_STYLESETSIZE parameter: STYLE_DEFAULT value: 14];
[mEditor setColorProperty: SCI_STYLESETFORE parameter: STYLE_DEFAULT value: [NSColor blackColor]];
diff --git a/doc/ScintillaDoc.html b/doc/ScintillaDoc.html
index c733db471..c0b0c7a6f 100644
--- a/doc/ScintillaDoc.html
+++ b/doc/ScintillaDoc.html
@@ -2392,9 +2392,15 @@ struct Sci_TextToFind {
<a class="message" href="#SCI_STYLESETSIZE">SCI_STYLESETSIZE(int styleNumber, int
sizeInPoints)</a><br />
<a class="message" href="#SCI_STYLEGETSIZE">SCI_STYLEGETSIZE(int styleNumber)</a><br />
+ <a class="message" href="#SCI_STYLESETSIZEFRACTIONAL">SCI_STYLESETSIZEFRACTIONAL(int styleNumber, int
+ sizeInHundredthPoints)</a><br />
+ <a class="message" href="#SCI_STYLEGETSIZEFRACTIONAL">SCI_STYLEGETSIZEFRACTIONAL(int styleNumber)</a><br />
<a class="message" href="#SCI_STYLESETBOLD">SCI_STYLESETBOLD(int styleNumber, bool
bold)</a><br />
<a class="message" href="#SCI_STYLEGETBOLD">SCI_STYLEGETBOLD(int styleNumber)</a><br />
+ <a class="message" href="#SCI_STYLESETWEIGHT">SCI_STYLESETWEIGHT(int styleNumber, int
+ weight)</a><br />
+ <a class="message" href="#SCI_STYLEGETWEIGHT">SCI_STYLEGETWEIGHT(int styleNumber)</a><br />
<a class="message" href="#SCI_STYLESETITALIC">SCI_STYLESETITALIC(int styleNumber, bool
italic)</a><br />
<a class="message" href="#SCI_STYLEGETITALIC">SCI_STYLEGETITALIC(int styleNumber)</a><br />
@@ -2443,8 +2449,12 @@ struct Sci_TextToFind {
<b id="SCI_STYLEGETFONT">SCI_STYLEGETFONT(int styleNumber, char *fontName)</b><br />
<b id="SCI_STYLESETSIZE">SCI_STYLESETSIZE(int styleNumber, int sizeInPoints)</b><br />
<b id="SCI_STYLEGETSIZE">SCI_STYLEGETSIZE(int styleNumber)</b><br />
+ <b id="SCI_STYLESETSIZEFRACTIONAL">SCI_STYLESETSIZEFRACTIONAL(int styleNumber, int sizeInHundredthPoints)</b><br />
+ <b id="SCI_STYLEGETSIZEFRACTIONAL">SCI_STYLEGETSIZEFRACTIONAL(int styleNumber)</b><br />
<b id="SCI_STYLESETBOLD">SCI_STYLESETBOLD(int styleNumber, bool bold)</b><br />
<b id="SCI_STYLEGETBOLD">SCI_STYLEGETBOLD(int styleNumber)</b><br />
+ <b id="SCI_STYLESETWEIGHT">SCI_STYLESETWEIGHT(int styleNumber, int weight)</b><br />
+ <b id="SCI_STYLEGETWEIGHT">SCI_STYLEGETWEIGHT(int styleNumber)</b><br />
<b id="SCI_STYLESETITALIC">SCI_STYLESETITALIC(int styleNumber, bool italic)</b><br />
<b id="SCI_STYLEGETITALIC">SCI_STYLEGETITALIC(int styleNumber)</b><br />
These messages (plus <a class="message"
@@ -2457,6 +2467,21 @@ struct Sci_TextToFind {
Pango antialiases text, works well with Unicode and is better supported in recent versions of GTK+
but GDK is faster.
Prepend a '!' character to the font name to use Pango.</p>
+ <p>Sizes can be set to a whole number of points with <code>SCI_STYLESETSIZE</code>
+ or to a fractional point size in hundredths of a point with <code>SCI_STYLESETSIZEFRACTIONAL</code>
+ by multiplying the size by 100 (<code>SC_FONT_SIZE_MULTIPLIER</code>).
+ For example, a text size of 9.4 points is set with <code>SCI_STYLESETSIZEFRACTIONAL(&lt;style&gt;, 940)</code>.
+ </p>
+ <p>The weight or boldness of a font can be set with <code>SCI_STYLESETBOLD</code>
+ or <code>SCI_STYLESETWEIGHT</code>. The weight is a number between 1 and 999 with 1 being very light
+ and 999 very heavy. While any value can be used, fonts often only support between 2 and 4 weights with three weights
+ being common enough to have symbolic names:
+ <code>SC_WEIGHT_NORMAL</code> (400),
+ <code>SC_WEIGHT_SEMIBOLD</code> (600), and
+ <code>SC_WEIGHT_BOLD</code> (700).
+ The <code>SCI_STYLESETBOLD</code> message takes a boolean argument with 0 choosing <code>SC_WEIGHT_NORMAL</code>
+ and 1 <code>SC_WEIGHT_BOLD</code>.
+ </p>
<p><b id="SCI_STYLESETUNDERLINE">SCI_STYLESETUNDERLINE(int styleNumber, bool
underline)</b><br />
@@ -2983,6 +3008,8 @@ struct Sci_TextToFind {
<a class="message" href="#SCI_GETBUFFEREDDRAW">SCI_GETBUFFEREDDRAW</a><br />
<a class="message" href="#SCI_SETTWOPHASEDRAW">SCI_SETTWOPHASEDRAW(bool twoPhase)</a><br />
<a class="message" href="#SCI_GETTWOPHASEDRAW">SCI_GETTWOPHASEDRAW</a><br />
+ <a class="message" href="#SCI_SETTECHNOLOGY">SCI_SETTECHNOLOGY(int technology)</a><br />
+ <a class="message" href="#SCI_GETTECHNOLOGY">SCI_GETTECHNOLOGY</a><br />
<a class="message" href="#SCI_SETFONTQUALITY">SCI_SETFONTQUALITY(int fontQuality)</a><br />
<a class="message" href="#SCI_GETFONTQUALITY">SCI_GETFONTQUALITY</a><br />
<a class="message" href="#SCI_SETCODEPAGE">SCI_SETCODEPAGE(int codePage)</a><br />
@@ -3046,6 +3073,13 @@ struct Sci_TextToFind {
transparent mode. Two phase drawing may flicker more than single phase
unless buffered drawing is on. The default is for drawing to be two phase.</p>
+ <p><b id="SCI_SETTECHNOLOGY">SCI_SETTECHNOLOGY(int technology)</b><br />
+ <b id="SCI_GETTECHNOLOGY">SCI_GETTECHNOLOGY</b><br />
+ The technology property allows choosing between different drawing APIs and options.
+ On most platforms, the only choice is <code>SC_TECHNOLOGY_DEFAULT</code> (0).
+ On Windows Vista or later, <code>SC_TECHNOLOGY_DIRECTWRITE</code> (1)
+ can be chosen to use the Direct2D and DirectWrite APIs for higher quality antialiased drawing.</p>
+
<p><b id="SCI_SETFONTQUALITY">SCI_SETFONTQUALITY(int fontQuality)</b><br />
<b id="SCI_GETFONTQUALITY">SCI_GETFONTQUALITY</b><br />
Manage font quality (antialiasing method). Currently, the following values are available on Windows:
diff --git a/gtk/PlatGTK.cxx b/gtk/PlatGTK.cxx
index 8fe55145a..ffb04d005 100644
--- a/gtk/PlatGTK.cxx
+++ b/gtk/PlatGTK.cxx
@@ -92,7 +92,7 @@ enum encodingType { singleByte, UTF8, dbcs};
struct LOGFONT {
int size;
- bool bold;
+ int weight;
bool italic;
int characterSet;
char faceName[300];
@@ -443,10 +443,10 @@ static void GenerateFontSpecStrings(const char *fontName, int characterSet,
#endif
-static void SetLogFont(LOGFONT &lf, const char *faceName, int characterSet, int size, bool bold, bool italic) {
+static void SetLogFont(LOGFONT &lf, const char *faceName, int characterSet, float size, int weight, bool italic) {
memset(&lf, 0, sizeof(lf));
lf.size = size;
- lf.bold = bold;
+ lf.weight = weight;
lf.italic = italic;
lf.characterSet = characterSet;
strncpy(lf.faceName, faceName, sizeof(lf.faceName) - 1);
@@ -457,13 +457,13 @@ static void SetLogFont(LOGFONT &lf, const char *faceName, int characterSet, int
* If one font is the same as another, its hash will be the same, but if the hash is the
* same then they may still be different.
*/
-static int HashFont(const char *faceName, int characterSet, int size, bool bold, bool italic) {
+static int HashFont(const FontParameters &fp) {
return
- size ^
- (characterSet << 10) ^
- (bold ? 0x10000000 : 0) ^
- (italic ? 0x20000000 : 0) ^
- faceName[0];
+ static_cast<int>(fp.size+0.5) ^
+ (fp.characterSet << 10) ^
+ ((fp.weight / 100) << 12) ^
+ (fp.italic ? 0x20000000 : 0) ^
+ fp.faceName[0];
}
class FontCached : Font {
@@ -471,35 +471,34 @@ class FontCached : Font {
int usage;
LOGFONT lf;
int hash;
- FontCached(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_);
+ FontCached(const FontParameters &fp);
~FontCached() {}
- bool SameAs(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_);
+ bool SameAs(const FontParameters &fp);
virtual void Release();
- static FontID CreateNewFont(const char *fontName, int characterSet,
- int size, bool bold, bool italic);
+ static FontID CreateNewFont(const FontParameters &fp);
static FontCached *first;
public:
- static FontID FindOrCreate(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_);
+ static FontID FindOrCreate(const FontParameters &fp);
static void ReleaseId(FontID fid_);
};
FontCached *FontCached::first = 0;
-FontCached::FontCached(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_) :
+FontCached::FontCached(const FontParameters &fp) :
next(0), usage(0), hash(0) {
- ::SetLogFont(lf, faceName_, characterSet_, size_, bold_, italic_);
- hash = HashFont(faceName_, characterSet_, size_, bold_, italic_);
- fid = CreateNewFont(faceName_, characterSet_, size_, bold_, italic_);
+ ::SetLogFont(lf, fp.faceName, fp.characterSet, fp.size, fp.weight, fp.italic);
+ hash = HashFont(fp);
+ fid = CreateNewFont(fp);
usage = 1;
}
-bool FontCached::SameAs(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_) {
+bool FontCached::SameAs(const FontParameters &fp) {
return
- lf.size == size_ &&
- lf.bold == bold_ &&
- lf.italic == italic_ &&
- lf.characterSet == characterSet_ &&
- 0 == strcmp(lf.faceName, faceName_);
+ lf.size == fp.size &&
+ lf.weight == fp.weight &&
+ lf.italic == fp.italic &&
+ lf.characterSet == fp.characterSet &&
+ 0 == strcmp(lf.faceName, fp.faceName);
}
void FontCached::Release() {
@@ -508,19 +507,19 @@ void FontCached::Release() {
fid = 0;
}
-FontID FontCached::FindOrCreate(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_) {
+FontID FontCached::FindOrCreate(const FontParameters &fp) {
FontID ret = 0;
FontMutexLock();
- int hashFind = HashFont(faceName_, characterSet_, size_, bold_, italic_);
+ int hashFind = HashFont(fp);
for (FontCached *cur = first; cur; cur = cur->next) {
if ((cur->hash == hashFind) &&
- cur->SameAs(faceName_, characterSet_, size_, bold_, italic_)) {
+ cur->SameAs(fp)) {
cur->usage++;
ret = cur->fid;
}
}
if (ret == 0) {
- FontCached *fc = new FontCached(faceName_, characterSet_, size_, bold_, italic_);
+ FontCached *fc = new FontCached(fp);
if (fc) {
fc->next = first;
first = fc;
@@ -560,16 +559,15 @@ static GdkFont *LoadFontOrSet(const char *fontspec, int characterSet) {
}
#endif
-FontID FontCached::CreateNewFont(const char *fontName, int characterSet,
- int size, bool bold, bool italic) {
- if (fontName[0] == '!') {
+FontID FontCached::CreateNewFont(const FontParameters &fp) {
+ if (fp.faceName[0] == '!') {
PangoFontDescription *pfd = pango_font_description_new();
if (pfd) {
- pango_font_description_set_family(pfd, fontName+1);
- pango_font_description_set_size(pfd, size * PANGO_SCALE);
- pango_font_description_set_weight(pfd, bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL);
- pango_font_description_set_style(pfd, italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL);
- return new FontHandle(pfd, characterSet);
+ pango_font_description_set_family(pfd, fp.faceName+1);
+ pango_font_description_set_size(pfd, pango_units_from_double(fp.size));
+ pango_font_description_set_weight(pfd, static_cast<PangoWeight>(fp.weight));
+ pango_font_description_set_style(pfd, fp.italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL);
+ return new FontHandle(pfd, fp.characterSet);
}
}
@@ -636,7 +634,7 @@ FontID FontCached::CreateNewFont(const char *fontName, int characterSet,
sizeof(fontspec) - 1,
spec,
foundary, faceName,
- bold ? "-bold" : "-medium",
+ (weight > 400) ? "-bold" : "-medium",
italic ? "-i" : "-r",
size * 10,
charset);
@@ -652,7 +650,7 @@ FontID FontCached::CreateNewFont(const char *fontName, int characterSet,
sizeof(fontspec) - 1,
",%s%s%s-o-*-*-*-%0d-*-*-*-*-%s",
foundary, faceName,
- bold ? "-bold" : "-medium",
+ (weight > 400) ? "-bold" : "-medium",
size * 10,
charset);
}
@@ -686,7 +684,7 @@ FontID FontCached::CreateNewFont(const char *fontName, int characterSet,
sizeof(fontspec) - 1,
"%s%s%s%s-*-*-*-%0d-*-*-*-*-%s",
foundary, faceName,
- bold ? "-bold" : "-medium",
+ (weight > 400) ? "-bold" : "-medium",
italic ? "-i" : "-r",
size * 10,
charset);
@@ -697,7 +695,7 @@ FontID FontCached::CreateNewFont(const char *fontName, int characterSet,
sizeof(fontspec) - 1,
"%s%s%s%s-*-*-*-%0d-*-*-*-*-%s",
foundary, faceName,
- bold ? "-bold" : "-medium",
+ (weight > 400) ? "-bold" : "-medium",
italic ? "-o" : "-r",
size * 10,
charset);
@@ -727,10 +725,9 @@ Font::Font() : fid(0) {}
Font::~Font() {}
-void Font::Create(const char *faceName, int characterSet, int size,
- bool bold, bool italic, int) {
+void Font::Create(const FontParameters &fp) {
Release();
- fid = FontCached::FindOrCreate(faceName, characterSet, size, bold, italic);
+ fid = FontCached::FindOrCreate(fp);
}
void Font::Release() {
@@ -790,19 +787,19 @@ public:
void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back);
void Copy(PRectangle rc, Point from, Surface &surfaceSource);
- void DrawTextBase(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore);
- void DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
- void DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
- void DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore);
- void MeasureWidths(Font &font_, const char *s, int len, int *positions);
- int WidthText(Font &font_, const char *s, int len);
- int WidthChar(Font &font_, char ch);
- int Ascent(Font &font_);
- int Descent(Font &font_);
- int InternalLeading(Font &font_);
- int ExternalLeading(Font &font_);
- int Height(Font &font_);
- int AverageCharWidth(Font &font_);
+ void DrawTextBase(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore);
+ void DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
+ void DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
+ void DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore);
+ void MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions);
+ XYPOSITION WidthText(Font &font_, const char *s, int len);
+ XYPOSITION WidthChar(Font &font_, char ch);
+ XYPOSITION Ascent(Font &font_);
+ XYPOSITION Descent(Font &font_);
+ XYPOSITION InternalLeading(Font &font_);
+ XYPOSITION ExternalLeading(Font &font_);
+ XYPOSITION Height(Font &font_);
+ XYPOSITION AverageCharWidth(Font &font_);
int SetPalette(Palette *pal, bool inBackGround);
void SetClip(PRectangle rc);
@@ -1579,7 +1576,7 @@ static size_t UTF8CharLength(const char *s) {
const int maxLengthTextRun = 10000;
-void SurfaceImpl::DrawTextBase(PRectangle rc, Font &font_, int ybase, const char *s, int len,
+void SurfaceImpl::DrawTextBase(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len,
ColourAllocated fore) {
PenColour(fore);
#ifdef USE_CAIRO
@@ -1587,7 +1584,7 @@ void SurfaceImpl::DrawTextBase(PRectangle rc, Font &font_, int ybase, const char
#else
if (gc && drawable) {
#endif
- int xText = rc.left;
+ XYPOSITION xText = rc.left;
if (PFont(font_)->pfd) {
char *utfForm = 0;
if (et == UTF8) {
@@ -1678,20 +1675,20 @@ void SurfaceImpl::DrawTextBase(PRectangle rc, Font &font_, int ybase, const char
}
}
-void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len,
+void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len,
ColourAllocated fore, ColourAllocated back) {
FillRectangle(rc, back);
DrawTextBase(rc, font_, ybase, s, len, fore);
}
// On GTK+, exactly same as DrawTextNoClip
-void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len,
+void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len,
ColourAllocated fore, ColourAllocated back) {
FillRectangle(rc, back);
DrawTextBase(rc, font_, ybase, s, len, fore);
}
-void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len,
+void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len,
ColourAllocated fore) {
// Avoid drawing spaces in transparent mode
for (int i=0;i<len;i++) {
@@ -1708,9 +1705,9 @@ class ClusterIterator {
int lenPositions;
public:
bool finished;
- int positionStart;
- int position;
- int distance;
+ XYPOSITION positionStart;
+ XYPOSITION position;
+ XYPOSITION distance;
int curIndex;
ClusterIterator(PangoLayout *layout, int len) : lenPositions(len), finished(false),
positionStart(0), position(0), distance(0), curIndex(0) {
@@ -1725,18 +1722,18 @@ public:
positionStart = position;
if (pango_layout_iter_next_cluster(iter)) {
pango_layout_iter_get_cluster_extents(iter, NULL, &pos);
- position = PANGO_PIXELS(pos.x);
+ position = pango_units_to_double(pos.x);
curIndex = pango_layout_iter_get_index(iter);
} else {
finished = true;
- position = PANGO_PIXELS(pos.x + pos.width);
+ position = pango_units_to_double(pos.x + pos.width);
curIndex = lenPositions;
}
distance = position - positionStart;
}
};
-void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positions) {
+void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions) {
if (font_.GetID()) {
const int lenPositions = len;
if (PFont(font_)->pfd) {
@@ -1892,7 +1889,7 @@ void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positi
}
}
-int SurfaceImpl::WidthText(Font &font_, const char *s, int len) {
+XYPOSITION SurfaceImpl::WidthText(Font &font_, const char *s, int len) {
if (font_.GetID()) {
if (PFont(font_)->pfd) {
char *utfForm = 0;
@@ -1921,7 +1918,7 @@ int SurfaceImpl::WidthText(Font &font_, const char *s, int len) {
#endif
pango_layout_line_get_extents(pangoLine, NULL, &pos);
delete []utfForm;
- return PANGO_PIXELS(pos.width);
+ return pango_units_to_double(pos.width);
}
#ifndef DISABLE_GDK_FONT
if (et == UTF8) {
@@ -1941,7 +1938,7 @@ int SurfaceImpl::WidthText(Font &font_, const char *s, int len) {
}
}
-int SurfaceImpl::WidthChar(Font &font_, char ch) {
+XYPOSITION SurfaceImpl::WidthChar(Font &font_, char ch) {
if (font_.GetID()) {
if (PFont(font_)->pfd) {
return WidthText(font_, &ch, 1);
@@ -1973,7 +1970,7 @@ const char sizeString[] = "`~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890"
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
#endif
-int SurfaceImpl::Ascent(Font &font_) {
+XYPOSITION SurfaceImpl::Ascent(Font &font_) {
if (!(font_.GetID()))
return 1;
#ifdef FAST_WAY
@@ -1983,7 +1980,7 @@ int SurfaceImpl::Ascent(Font &font_) {
PangoFontMetrics *metrics = pango_context_get_metrics(pcontext,
PFont(font_)->pfd, pango_context_get_language(pcontext));
PFont(font_)->ascent =
- PANGO_PIXELS(pango_font_metrics_get_ascent(metrics));
+ pango_units_to_double(pango_font_metrics_get_ascent(metrics));
pango_font_metrics_unref(metrics);
ascent = PFont(font_)->ascent;
}
@@ -2011,7 +2008,7 @@ int SurfaceImpl::Ascent(Font &font_) {
#endif
}
-int SurfaceImpl::Descent(Font &font_) {
+XYPOSITION SurfaceImpl::Descent(Font &font_) {
if (!(font_.GetID()))
return 1;
#ifdef FAST_WAY
@@ -2019,7 +2016,7 @@ int SurfaceImpl::Descent(Font &font_) {
if (PFont(font_)->pfd) {
PangoFontMetrics *metrics = pango_context_get_metrics(pcontext,
PFont(font_)->pfd, pango_context_get_language(pcontext));
- int descent = PANGO_PIXELS(pango_font_metrics_get_descent(metrics));
+ int descent = pango_units_to_double(pango_font_metrics_get_descent(metrics));
pango_font_metrics_unref(metrics);
return descent;
}
@@ -2042,19 +2039,19 @@ int SurfaceImpl::Descent(Font &font_) {
#endif
}
-int SurfaceImpl::InternalLeading(Font &) {
+XYPOSITION SurfaceImpl::InternalLeading(Font &) {
return 0;
}
-int SurfaceImpl::ExternalLeading(Font &) {
+XYPOSITION SurfaceImpl::ExternalLeading(Font &) {
return 0;
}
-int SurfaceImpl::Height(Font &font_) {
+XYPOSITION SurfaceImpl::Height(Font &font_) {
return Ascent(font_) + Descent(font_);
}
-int SurfaceImpl::AverageCharWidth(Font &font_) {
+XYPOSITION SurfaceImpl::AverageCharWidth(Font &font_) {
return WidthChar(font_, 'n');
}
@@ -2086,8 +2083,8 @@ void SurfaceImpl::SetDBCSMode(int codePage) {
et = dbcs;
}
-Surface *Surface::Allocate() {
- return new SurfaceImpl;
+Surface *Surface::Allocate(int) {
+ return new SurfaceImpl();
}
Window::~Window() {}
@@ -2307,7 +2304,7 @@ public:
}
}
virtual void SetFont(Font &font);
- virtual void Create(Window &parent, int ctrlID, Point location_, int lineHeight_, bool unicodeMode_);
+ virtual void Create(Window &parent, int ctrlID, Point location_, int lineHeight_, bool unicodeMode_, int technology_);
virtual void SetAverageCharWidth(int width);
virtual void SetVisibleRows(int rows);
virtual int GetVisibleRows() const;
@@ -2396,7 +2393,7 @@ static void StyleSet(GtkWidget *w, GtkStyle*, void*) {
#endif
}
-void ListBoxX::Create(Window &, int, Point, int, bool) {
+void ListBoxX::Create(Window &, int, Point, int, bool, int) {
wid = gtk_window_new(GTK_WINDOW_POPUP);
GtkWidget *frame = gtk_frame_new(NULL);
@@ -2838,7 +2835,7 @@ void Menu::Show(Point pt, Window &) {
pt.y = screenHeight - requisition.height;
}
gtk_menu_popup(widget, NULL, NULL, MenuPositionFunc,
- reinterpret_cast<void *>((pt.y << 16) | pt.x), 0,
+ reinterpret_cast<void *>((static_cast<int>(pt.y) << 16) | static_cast<int>(pt.x)), 0,
gtk_get_current_event_time());
}
diff --git a/gtk/ScintillaGTK.cxx b/gtk/ScintillaGTK.cxx
index 0932c6e3b..efb0e0cd5 100644
--- a/gtk/ScintillaGTK.cxx
+++ b/gtk/ScintillaGTK.cxx
@@ -584,7 +584,7 @@ void ScintillaGTK::UnMapThis() {
#else
GTK_WIDGET_UNSET_FLAGS(PWidget(wMain), GTK_MAPPED);
#endif
- DropGraphics();
+ DropGraphics(false);
gdk_window_hide(PWindow(wMain));
gtk_widget_unmap(PWidget(wText));
gtk_widget_unmap(PWidget(scrollbarh));
@@ -1112,7 +1112,7 @@ void ScintillaGTK::SyncPaint(PRectangle rc) {
PRectangle rcClient = GetClientRectangle();
paintingAllText = rcPaint.Contains(rcClient);
if (PWindow(wText)) {
- Surface *sw = Surface::Allocate();
+ Surface *sw = Surface::Allocate(SC_TECHNOLOGY_DEFAULT);
if (sw) {
#if GTK_CHECK_VERSION(3,0,0)
cairo_t *cr = gdk_cairo_create(PWindow(wText));
@@ -2473,7 +2473,7 @@ gboolean ScintillaGTK::DrawTextThis(cairo_t *cr) {
rcPaint.bottom = y2;
PRectangle rcClient = GetClientRectangle();
paintingAllText = rcPaint.Contains(rcClient);
- Surface *surfaceWindow = Surface::Allocate();
+ Surface *surfaceWindow = Surface::Allocate(SC_TECHNOLOGY_DEFAULT);
if (surfaceWindow) {
surfaceWindow->Init(cr, PWidget(wText));
Paint(surfaceWindow, rcPaint);
@@ -2831,7 +2831,7 @@ gboolean ScintillaGTK::PressCT(GtkWidget *widget, GdkEventButton *event, Scintil
gboolean ScintillaGTK::DrawCT(GtkWidget *widget, cairo_t *cr, CallTip *ctip) {
try {
- Surface *surfaceWindow = Surface::Allocate();
+ Surface *surfaceWindow = Surface::Allocate(SC_TECHNOLOGY_DEFAULT);
if (surfaceWindow) {
surfaceWindow->Init(cr, widget);
surfaceWindow->SetUnicodeMode(SC_CP_UTF8 == ctip->codePage);
diff --git a/include/Platform.h b/include/Platform.h
index b0f3de0dc..499e78e5d 100644
--- a/include/Platform.h
+++ b/include/Platform.h
@@ -59,6 +59,10 @@
namespace Scintilla {
#endif
+typedef float XYPOSITION;
+typedef double XYACCUMULATOR;
+//#define XYPOSITION int
+
// Underlying the implementation of the platform classes are platform specific types.
// Sometimes these need to be passed around by client code so they are defined here
@@ -76,10 +80,10 @@ typedef void *IdlerID;
*/
class Point {
public:
- int x;
- int y;
+ XYPOSITION x;
+ XYPOSITION y;
- explicit Point(int x_=0, int y_=0) : x(x_), y(y_) {
+ explicit Point(XYPOSITION x_=0, XYPOSITION y_=0) : x(x_), y(y_) {
}
// Other automatically defined methods (assignment, copy constructor, destructor) are fine
@@ -94,12 +98,12 @@ public:
*/
class PRectangle {
public:
- int left;
- int top;
- int right;
- int bottom;
+ XYPOSITION left;
+ XYPOSITION top;
+ XYPOSITION right;
+ XYPOSITION bottom;
- PRectangle(int left_=0, int top_=0, int right_=0, int bottom_ = 0) :
+ PRectangle(XYPOSITION left_=0, XYPOSITION top_=0, XYPOSITION right_=0, XYPOSITION bottom_ = 0) :
left(left_), top(top_), right(right_), bottom(bottom_) {
}
@@ -121,14 +125,14 @@ public:
return (right > other.left) && (left < other.right) &&
(bottom > other.top) && (top < other.bottom);
}
- void Move(int xDelta, int yDelta) {
+ void Move(XYPOSITION xDelta, XYPOSITION yDelta) {
left += xDelta;
top += yDelta;
right += xDelta;
bottom += yDelta;
}
- int Width() { return right - left; }
- int Height() { return bottom - top; }
+ XYPOSITION Width() { return right - left; }
+ XYPOSITION Height() { return bottom - top; }
bool Empty() {
return (Height() <= 0) || (Width() <= 0);
}
@@ -287,6 +291,37 @@ public:
/**
* Font management.
*/
+
+struct FontParameters {
+ const char *faceName;
+ float size;
+ int weight;
+ bool italic;
+ int extraFontFlag;
+ int technology;
+ int characterSet;
+
+ FontParameters(
+ const char *faceName_,
+ float size_=10,
+ int weight_=400,
+ bool italic_=false,
+ int extraFontFlag_=0,
+ int technology_=0,
+ int characterSet_=0) :
+
+ faceName(faceName_),
+ size(size_),
+ weight(weight_),
+ italic(italic_),
+ extraFontFlag(extraFontFlag_),
+ technology(technology_),
+ characterSet(characterSet_)
+ {
+ }
+
+};
+
class Font {
protected:
FontID fid;
@@ -300,8 +335,7 @@ public:
Font();
virtual ~Font();
- virtual void Create(const char *faceName, int characterSet, int size,
- bool bold, bool italic, int extraFontFlag=0);
+ virtual void Create(const FontParameters &fp);
virtual void Release();
FontID GetID() { return fid; }
@@ -325,7 +359,7 @@ private:
public:
Surface() {}
virtual ~Surface() {}
- static Surface *Allocate();
+ static Surface *Allocate(int technology);
virtual void Init(WindowID wid)=0;
virtual void Init(SurfaceID sid, WindowID wid)=0;
@@ -349,18 +383,18 @@ public:
virtual void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back)=0;
virtual void Copy(PRectangle rc, Point from, Surface &surfaceSource)=0;
- virtual void DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back)=0;
- virtual void DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back)=0;
- virtual void DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore)=0;
- virtual void MeasureWidths(Font &font_, const char *s, int len, int *positions)=0;
- virtual int WidthText(Font &font_, const char *s, int len)=0;
- virtual int WidthChar(Font &font_, char ch)=0;
- virtual int Ascent(Font &font_)=0;
- virtual int Descent(Font &font_)=0;
- virtual int InternalLeading(Font &font_)=0;
- virtual int ExternalLeading(Font &font_)=0;
- virtual int Height(Font &font_)=0;
- virtual int AverageCharWidth(Font &font_)=0;
+ virtual void DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back)=0;
+ virtual void DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back)=0;
+ virtual void DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore)=0;
+ virtual void MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions)=0;
+ virtual XYPOSITION WidthText(Font &font_, const char *s, int len)=0;
+ virtual XYPOSITION WidthChar(Font &font_, char ch)=0;
+ virtual XYPOSITION Ascent(Font &font_)=0;
+ virtual XYPOSITION Descent(Font &font_)=0;
+ virtual XYPOSITION InternalLeading(Font &font_)=0;
+ virtual XYPOSITION ExternalLeading(Font &font_)=0;
+ virtual XYPOSITION Height(Font &font_)=0;
+ virtual XYPOSITION AverageCharWidth(Font &font_)=0;
virtual int SetPalette(Palette *pal, bool inBackGround)=0;
virtual void SetClip(PRectangle rc)=0;
@@ -439,7 +473,7 @@ public:
static ListBox *Allocate();
virtual void SetFont(Font &font)=0;
- virtual void Create(Window &parent, int ctrlID, Point location, int lineHeight_, bool unicodeMode_)=0;
+ virtual void Create(Window &parent, int ctrlID, Point location, int lineHeight_, bool unicodeMode_, int technology_)=0;
virtual void SetAverageCharWidth(int width)=0;
virtual void SetVisibleRows(int rows)=0;
virtual int GetVisibleRows() const=0;
diff --git a/include/Scintilla.h b/include/Scintilla.h
index 34e4f793d..c8ffba04e 100644
--- a/include/Scintilla.h
+++ b/include/Scintilla.h
@@ -221,6 +221,14 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_STYLEGETCHANGEABLE 2492
#define SCI_STYLEGETHOTSPOT 2493
#define SCI_STYLESETCASE 2060
+#define SC_FONT_SIZE_MULTIPLIER 100
+#define SCI_STYLESETSIZEFRACTIONAL 2061
+#define SCI_STYLEGETSIZEFRACTIONAL 2062
+#define SC_WEIGHT_NORMAL 400
+#define SC_WEIGHT_SEMIBOLD 600
+#define SC_WEIGHT_BOLD 700
+#define SCI_STYLESETWEIGHT 2063
+#define SCI_STYLEGETWEIGHT 2064
#define SCI_STYLESETCHARACTERSET 2066
#define SCI_STYLESETHOTSPOT 2409
#define SCI_SETSELFORE 2067
@@ -819,6 +827,10 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_REGISTERRGBAIMAGE 2627
#define SCI_SCROLLTOSTART 2628
#define SCI_SCROLLTOEND 2629
+#define SC_TECHNOLOGY_DEFAULT 0
+#define SC_TECHNOLOGY_DIRECTWRITE 1
+#define SCI_SETTECHNOLOGY 2630
+#define SCI_GETTECHNOLOGY 2631
#define SCI_STARTRECORD 3001
#define SCI_STOPRECORD 3002
#define SCI_SETLEXER 4001
diff --git a/include/Scintilla.iface b/include/Scintilla.iface
index 9530f4292..23da6d5b5 100644
--- a/include/Scintilla.iface
+++ b/include/Scintilla.iface
@@ -482,6 +482,25 @@ get bool StyleGetHotSpot=2493(int style,)
# Set a style to be mixed case, or to force upper or lower case.
set void StyleSetCase=2060(int style, int caseForce)
+val SC_FONT_SIZE_MULTIPLIER=100
+
+# Set the size of characters of a style. Size is in points multiplied by 100.
+set void StyleSetSizeFractional=2061(int style, int caseForce)
+
+# Get the size of characters of a style in points multiplied by 100
+get int StyleGetSizeFractional=2062(int style,)
+
+enu FontWeight=SC_WEIGHT_
+val SC_WEIGHT_NORMAL=400
+val SC_WEIGHT_SEMIBOLD=600
+val SC_WEIGHT_BOLD=700
+
+# Set the weight of characters of a style.
+set void StyleSetWeight=2063(int style, int weight)
+
+# Get the weight of characters of a style.
+get int StyleGetWeight=2064(int style,)
+
# Set the character set of the font in a style.
set void StyleSetCharacterSet=2066(int style, int characterSet)
@@ -2175,6 +2194,15 @@ fun void ScrollToStart=2628(,)
# Scroll to end of document.
fun void ScrollToEnd=2629(,)
+val SC_TECHNOLOGY_DEFAULT=0
+val SC_TECHNOLOGY_DIRECTWRITE=1
+
+# Set the technolgy used.
+set void SetTechnology=2630(int technology,)
+
+# Get the tech.
+get int GetTechnology=2631(,)
+
# Start notifying the container of all key presses and commands.
fun void StartRecord=3001(,)
diff --git a/src/AutoComplete.cxx b/src/AutoComplete.cxx
index f6a291fe9..2752ef0c9 100644
--- a/src/AutoComplete.cxx
+++ b/src/AutoComplete.cxx
@@ -50,11 +50,11 @@ bool AutoComplete::Active() const {
void AutoComplete::Start(Window &parent, int ctrlID,
int position, Point location, int startLen_,
- int lineHeight, bool unicodeMode) {
+ int lineHeight, bool unicodeMode, int technology) {
if (active) {
Cancel();
}
- lb->Create(parent, ctrlID, location, lineHeight, unicodeMode);
+ lb->Create(parent, ctrlID, location, lineHeight, unicodeMode, technology);
lb->Clear();
active = true;
startLen = startLen_;
diff --git a/src/AutoComplete.h b/src/AutoComplete.h
index f48cb0551..aefab120a 100644
--- a/src/AutoComplete.h
+++ b/src/AutoComplete.h
@@ -40,7 +40,7 @@ public:
/// Display the auto completion list positioned to be near a character position
void Start(Window &parent, int ctrlID, int position, Point location,
- int startLen_, int lineHeight, bool unicodeMode);
+ int startLen_, int lineHeight, bool unicodeMode, int technology);
/// The stop chars are characters which, when typed, cause the auto completion list to disappear
void SetStopChars(const char *stopChars_);
diff --git a/src/CallTip.cxx b/src/CallTip.cxx
index cdc30fcbc..0e1e80cc1 100644
--- a/src/CallTip.cxx
+++ b/src/CallTip.cxx
@@ -255,14 +255,15 @@ void CallTip::MouseClick(Point pt) {
PRectangle CallTip::CallTipStart(int pos, Point pt, const char *defn,
const char *faceName, int size,
- int codePage_, int characterSet, Window &wParent) {
+ int codePage_, int characterSet,
+ int technology, Window &wParent) {
clickPlace = 0;
delete []val;
val = 0;
val = new char[strlen(defn) + 1];
strcpy(val, defn);
codePage = codePage_;
- Surface *surfaceMeasure = Surface::Allocate();
+ Surface *surfaceMeasure = Surface::Allocate(technology);
if (!surfaceMeasure)
return PRectangle();
surfaceMeasure->Init(wParent.GetID());
@@ -273,7 +274,8 @@ PRectangle CallTip::CallTipStart(int pos, Point pt, const char *defn,
inCallTipMode = true;
posStartCallTip = pos;
int deviceHeight = surfaceMeasure->DeviceHeightFont(size);
- font.Create(faceName, characterSet, deviceHeight, false, false);
+ FontParameters fp(faceName, deviceHeight / SC_FONT_SIZE_MULTIPLIER, SC_WEIGHT_NORMAL, false, 0, technology, characterSet);
+ font.Create(fp);
// Look for multiple lines in the text
// Only support \n here - simply means container must avoid \r!
int numLines = 1;
diff --git a/src/CallTip.h b/src/CallTip.h
index a9ba82eb8..e437f3309 100644
--- a/src/CallTip.h
+++ b/src/CallTip.h
@@ -62,7 +62,7 @@ public:
/// Setup the calltip and return a rectangle of the area required.
PRectangle CallTipStart(int pos, Point pt, const char *defn,
const char *faceName, int size, int codePage_,
- int characterSet, Window &wParent);
+ int characterSet, int technology, Window &wParent);
void CallTipCancel();
diff --git a/src/Editor.cxx b/src/Editor.cxx
index 347f27318..1257ac4b0 100644
--- a/src/Editor.cxx
+++ b/src/Editor.cxx
@@ -102,7 +102,8 @@ Editor::Editor() {
ctrlID = 0;
stylesValid = false;
-
+ technology = SC_TECHNOLOGY_DEFAULT;
+
printMagnification = 0;
printColourMode = SC_PRINT_NORMAL;
printWrapState = eWrapWord;
@@ -168,11 +169,11 @@ Editor::Editor() {
additionalCaretsVisible = true;
virtualSpaceOptions = SCVS_NONE;
- pixmapLine = Surface::Allocate();
- pixmapSelMargin = Surface::Allocate();
- pixmapSelPattern = Surface::Allocate();
- pixmapIndentGuide = Surface::Allocate();
- pixmapIndentGuideHighlight = Surface::Allocate();
+ pixmapLine = 0;
+ pixmapSelMargin = 0;
+ pixmapSelPattern = 0;
+ pixmapIndentGuide = 0;
+ pixmapIndentGuideHighlight = 0;
targetStart = 0;
targetEnd = 0;
@@ -226,12 +227,7 @@ Editor::~Editor() {
pdoc->RemoveWatcher(this, 0);
pdoc->Release();
pdoc = 0;
- DropGraphics();
- delete pixmapLine;
- delete pixmapSelMargin;
- delete pixmapSelPattern;
- delete pixmapIndentGuide;
- delete pixmapIndentGuideHighlight;
+ DropGraphics(true);
}
void Editor::Finalise() {
@@ -239,17 +235,50 @@ void Editor::Finalise() {
CancelModes();
}
-void Editor::DropGraphics() {
- pixmapLine->Release();
- pixmapSelMargin->Release();
- pixmapSelPattern->Release();
- pixmapIndentGuide->Release();
- pixmapIndentGuideHighlight->Release();
+void Editor::DropGraphics(bool freeObjects) {
+ if (freeObjects) {
+ delete pixmapLine;
+ pixmapLine = 0;
+ delete pixmapSelMargin;
+ pixmapSelMargin = 0;
+ delete pixmapSelPattern;
+ pixmapSelPattern = 0;
+ delete pixmapIndentGuide;
+ pixmapIndentGuide = 0;
+ delete pixmapIndentGuideHighlight;
+ pixmapIndentGuideHighlight = 0;
+ } else {
+ if (pixmapLine)
+ pixmapLine->Release();
+ if (pixmapSelMargin)
+ pixmapSelMargin->Release();
+ if (pixmapSelPattern)
+ pixmapSelPattern->Release();
+ if (pixmapIndentGuide)
+ pixmapIndentGuide->Release();
+ if (pixmapIndentGuideHighlight)
+ pixmapIndentGuideHighlight->Release();
+ }
+}
+
+void Editor::AllocateGraphics() {
+ if (!pixmapLine)
+ pixmapLine = Surface::Allocate(technology);
+ if (!pixmapSelMargin)
+ pixmapSelMargin = Surface::Allocate(technology);
+ if (!pixmapSelPattern)
+ pixmapSelPattern = Surface::Allocate(technology);
+ if (!pixmapIndentGuide)
+ pixmapIndentGuide = Surface::Allocate(technology);
+ if (!pixmapIndentGuideHighlight)
+ pixmapIndentGuideHighlight = Surface::Allocate(technology);
}
void Editor::InvalidateStyleData() {
stylesValid = false;
- DropGraphics();
+ vs.technology = technology;
+ DropGraphics(false);
+ AllocateGraphics();
palette.Release();
llc.Invalidate(LineLayout::llInvalid);
posCache.Clear();
@@ -2216,7 +2245,7 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou
// Layout the line, determining the position of each character,
// with an extra element at the end for the end of the line.
int startseg = 0; // Start of the current segment, in char. number
- int startsegx = 0; // Start of the current segment, in pixels
+ XYACCUMULATOR startsegx = 0; // Start of the current segment, in pixels
ll->positions[0] = 0;
unsigned int tabWidth = vstyle.spaceWidth * pdoc->tabInChars;
bool lastSegItalics = false;
@@ -2237,7 +2266,7 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou
if (vstyle.styles[ll->styles[charInLine]].visible) {
if (isControl) {
if (ll->chars[charInLine] == '\t') {
- ll->positions[charInLine + 1] = ((((startsegx + 2) /
+ ll->positions[charInLine + 1] = ((((static_cast<int>(startsegx) + 2) /
tabWidth) + 1) * tabWidth) - startsegx;
} else if (controlCharSymbol < 32) {
if (ctrlCharWidth[ll->chars[charInLine]] == 0) {
@@ -2902,8 +2931,10 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis
// draw strings that are completely past the right side of the window.
if ((rcSegment.left <= rcLine.right) && (rcSegment.right >= rcLine.left)) {
// Clip to line rectangle, since may have a huge position which will not work with some platforms
- rcSegment.left = Platform::Maximum(rcSegment.left, rcLine.left);
- rcSegment.right = Platform::Minimum(rcSegment.right, rcLine.right);
+ if (rcSegment.left < rcLine.left)
+ rcSegment.left = rcLine.left;
+ if (rcSegment.right > rcLine.right)
+ rcSegment.right = rcLine.right;
int styleMain = ll->styles[i];
const int inSelection = hideSelection ? 0 : sel.CharacterInSelection(iDoc);
@@ -3379,7 +3410,7 @@ void Editor::DrawCarets(Surface *surface, ViewStyle &vsDraw, int lineDoc, int xS
const int spaceWidth = static_cast<int>(vsDraw.styles[ll->EndLineStyle()].spaceWidth);
const int virtualOffset = posCaret.VirtualSpace() * spaceWidth;
if (ll->InLine(offset, subLine) && offset <= ll->numCharsBeforeEOL) {
- int xposCaret = ll->positions[offset] + virtualOffset - ll->positions[ll->LineStart(subLine)];
+ XYPOSITION xposCaret = ll->positions[offset] + virtualOffset - ll->positions[ll->LineStart(subLine)];
if (ll->wrapIndent != 0) {
int lineStart = ll->LineStart(subLine);
if (lineStart != 0) // Wrapped
@@ -3924,7 +3955,7 @@ void Editor::SetScrollBars() {
}
void Editor::ChangeSize() {
- DropGraphics();
+ DropGraphics(false);
SetScrollBars();
if (wrapState != eWrapNone) {
PRectangle rcTextArea = GetClientRectangle();
@@ -6979,7 +7010,10 @@ void Editor::StyleSetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam
vs.styles[wParam].back.desired = ColourDesired(lParam);
break;
case SCI_STYLESETBOLD:
- vs.styles[wParam].bold = lParam != 0;
+ vs.styles[wParam].weight = lParam != 0 ? SC_WEIGHT_BOLD : SC_WEIGHT_NORMAL;
+ break;
+ case SCI_STYLESETWEIGHT:
+ vs.styles[wParam].weight = lParam;
break;
case SCI_STYLESETITALIC:
vs.styles[wParam].italic = lParam != 0;
@@ -6988,6 +7022,9 @@ void Editor::StyleSetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam
vs.styles[wParam].eolFilled = lParam != 0;
break;
case SCI_STYLESETSIZE:
+ vs.styles[wParam].size = lParam * SC_FONT_SIZE_MULTIPLIER;
+ break;
+ case SCI_STYLESETSIZEFRACTIONAL:
vs.styles[wParam].size = lParam;
break;
case SCI_STYLESETFONT:
@@ -7025,12 +7062,16 @@ sptr_t Editor::StyleGetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lPar
case SCI_STYLEGETBACK:
return vs.styles[wParam].back.desired.AsLong();
case SCI_STYLEGETBOLD:
- return vs.styles[wParam].bold ? 1 : 0;
+ return vs.styles[wParam].weight > SC_WEIGHT_NORMAL;
+ case SCI_STYLEGETWEIGHT:
+ return vs.styles[wParam].weight;
case SCI_STYLEGETITALIC:
return vs.styles[wParam].italic ? 1 : 0;
case SCI_STYLEGETEOLFILLED:
return vs.styles[wParam].eolFilled ? 1 : 0;
case SCI_STYLEGETSIZE:
+ return vs.styles[wParam].size / SC_FONT_SIZE_MULTIPLIER;
+ case SCI_STYLEGETSIZEFRACTIONAL:
return vs.styles[wParam].size;
case SCI_STYLEGETFONT:
if (!vs.styles[wParam].fontName)
@@ -8148,9 +8189,11 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
case SCI_STYLESETFORE:
case SCI_STYLESETBACK:
case SCI_STYLESETBOLD:
+ case SCI_STYLESETWEIGHT:
case SCI_STYLESETITALIC:
case SCI_STYLESETEOLFILLED:
case SCI_STYLESETSIZE:
+ case SCI_STYLESETSIZEFRACTIONAL:
case SCI_STYLESETFONT:
case SCI_STYLESETUNDERLINE:
case SCI_STYLESETCASE:
@@ -8164,9 +8207,11 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
case SCI_STYLEGETFORE:
case SCI_STYLEGETBACK:
case SCI_STYLEGETBOLD:
+ case SCI_STYLEGETWEIGHT:
case SCI_STYLEGETITALIC:
case SCI_STYLEGETEOLFILLED:
case SCI_STYLEGETSIZE:
+ case SCI_STYLEGETSIZEFRACTIONAL:
case SCI_STYLEGETFONT:
case SCI_STYLEGETUNDERLINE:
case SCI_STYLEGETCASE:
@@ -9202,6 +9247,13 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
case SCI_GETIDENTIFIER:
return GetCtrlID();
+ case SCI_SETTECHNOLOGY:
+ // No action by default
+ break;
+
+ case SCI_GETTECHNOLOGY:
+ return technology;
+
default:
return DefWndProc(iMessage, wParam, lParam);
}
diff --git a/src/Editor.h b/src/Editor.h
index f1a500b74..7a30fdf3f 100644
--- a/src/Editor.h
+++ b/src/Editor.h
@@ -131,6 +131,7 @@ protected: // ScintillaBase subclass needs access to much of Editor
* When a style attribute is changed, this cache is flushed. */
bool stylesValid;
ViewStyle vs;
+ int technology;
Point sizeRGBAImage;
Palette palette;
@@ -279,7 +280,8 @@ protected: // ScintillaBase subclass needs access to much of Editor
void InvalidateStyleRedraw();
virtual void RefreshColourPalette(Palette &pal, bool want);
void RefreshStyleData();
- void DropGraphics();
+ void DropGraphics(bool freeObjects);
+ void AllocateGraphics();
virtual PRectangle GetClientRectangle();
PRectangle GetTextRectangle();
@@ -574,7 +576,7 @@ private:
public:
AutoSurface(Editor *ed) : surf(0) {
if (ed->wMain.GetID()) {
- surf = Surface::Allocate();
+ surf = Surface::Allocate(ed->technology);
if (surf) {
surf->Init(ed->wMain.GetID());
surf->SetUnicodeMode(SC_CP_UTF8 == ed->CodePage());
@@ -584,7 +586,7 @@ public:
}
AutoSurface(SurfaceID sid, Editor *ed) : surf(0) {
if (ed->wMain.GetID()) {
- surf = Surface::Allocate();
+ surf = Surface::Allocate(ed->technology);
if (surf) {
surf->Init(sid, ed->wMain.GetID());
surf->SetUnicodeMode(SC_CP_UTF8 == ed->CodePage());
diff --git a/src/FontQuality.h b/src/FontQuality.h
index 2c8d548a8..45600c35e 100644
--- a/src/FontQuality.h
+++ b/src/FontQuality.h
@@ -10,3 +10,6 @@
#define SC_EFF_QUALITY_NON_ANTIALIASED 1
#define SC_EFF_QUALITY_ANTIALIASED 2
#define SC_EFF_QUALITY_LCD_OPTIMIZED 3
+
+#define SCWIN_TECH_GDI 0
+#define SCWIN_TECH_DIRECTWRITE 1
diff --git a/src/PositionCache.cxx b/src/PositionCache.cxx
index 2105c292f..614e6b8bf 100644
--- a/src/PositionCache.cxx
+++ b/src/PositionCache.cxx
@@ -86,7 +86,7 @@ void LineLayout::Resize(int maxLineLength_) {
indicators = new char[maxLineLength_ + 1];
// Extra position allocated as sometimes the Windows
// GetTextExtentExPoint API writes an extra element.
- positions = new int[maxLineLength_ + 1 + 1];
+ positions = new XYPOSITION[maxLineLength_ + 1 + 1];
maxLineLength = maxLineLength_;
}
}
@@ -503,15 +503,15 @@ PositionCacheEntry::PositionCacheEntry() :
}
void PositionCacheEntry::Set(unsigned int styleNumber_, const char *s_,
- unsigned int len_, int *positions_, unsigned int clock_) {
+ unsigned int len_, XYPOSITION *positions_, unsigned int clock_) {
Clear();
styleNumber = styleNumber_;
len = len_;
clock = clock_;
if (s_ && positions_) {
- positions = new short[len + (len + 1) / 2];
+ positions = new XYPOSITION[len + (len + 1) / 2];
for (unsigned int i=0; i<len; i++) {
- positions[i] = static_cast<short>(positions_[i]);
+ positions[i] = static_cast<XYPOSITION>(positions_[i]);
}
memcpy(reinterpret_cast<char *>(positions + len), s_, len);
}
@@ -530,7 +530,7 @@ void PositionCacheEntry::Clear() {
}
bool PositionCacheEntry::Retrieve(unsigned int styleNumber_, const char *s_,
- unsigned int len_, int *positions_) const {
+ unsigned int len_, XYPOSITION *positions_) const {
if ((styleNumber == styleNumber_) && (len == len_) &&
(memcmp(reinterpret_cast<char *>(positions + len), s_, len)== 0)) {
for (unsigned int i=0; i<len; i++) {
@@ -595,7 +595,7 @@ void PositionCache::SetSize(size_t size_) {
}
void PositionCache::MeasureWidths(Surface *surface, ViewStyle &vstyle, unsigned int styleNumber,
- const char *s, unsigned int len, int *positions, Document *pdoc) {
+ const char *s, unsigned int len, XYPOSITION *positions, Document *pdoc) {
allClear = false;
int probe = -1;
@@ -621,7 +621,7 @@ void PositionCache::MeasureWidths(Surface *surface, ViewStyle &vstyle, unsigned
if (len > BreakFinder::lengthStartSubdivision) {
// Break up into segments
unsigned int startSegment = 0;
- int xStartSegment = 0;
+ XYPOSITION xStartSegment = 0;
while (startSegment < len) {
unsigned int lenSegment = pdoc->SafeSegment(s + startSegment, len - startSegment, BreakFinder::lengthEachSubdivision);
surface->MeasureWidths(vstyle.styles[styleNumber].font, s + startSegment, lenSegment, positions + startSegment);
diff --git a/src/PositionCache.h b/src/PositionCache.h
index c6076ea20..280446627 100644
--- a/src/PositionCache.h
+++ b/src/PositionCache.h
@@ -41,7 +41,7 @@ public:
unsigned char *styles;
int styleBitsSet;
char *indicators;
- int *positions;
+ XYPOSITION *positions;
char bracePreviousStyles[2];
// Hotspot support
@@ -103,13 +103,13 @@ class PositionCacheEntry {
unsigned int styleNumber:8;
unsigned int len:8;
unsigned int clock:16;
- short *positions;
+ XYPOSITION *positions;
public:
PositionCacheEntry();
~PositionCacheEntry();
- void Set(unsigned int styleNumber_, const char *s_, unsigned int len_, int *positions_, unsigned int clock);
+ void Set(unsigned int styleNumber_, const char *s_, unsigned int len_, XYPOSITION *positions_, unsigned int clock);
void Clear();
- bool Retrieve(unsigned int styleNumber_, const char *s_, unsigned int len_, int *positions_) const;
+ bool Retrieve(unsigned int styleNumber_, const char *s_, unsigned int len_, XYPOSITION *positions_) const;
static int Hash(unsigned int styleNumber_, const char *s, unsigned int len);
bool NewerThan(const PositionCacheEntry &other) const;
void ResetClock();
@@ -155,7 +155,7 @@ public:
void SetSize(size_t size_);
size_t GetSize() const { return size; }
void MeasureWidths(Surface *surface, ViewStyle &vstyle, unsigned int styleNumber,
- const char *s, unsigned int len, int *positions, Document *pdoc);
+ const char *s, unsigned int len, XYPOSITION *positions, Document *pdoc);
};
inline bool IsSpaceOrTab(int ch) {
diff --git a/src/ScintillaBase.cxx b/src/ScintillaBase.cxx
index da6b03e0d..247f34c4e 100644
--- a/src/ScintillaBase.cxx
+++ b/src/ScintillaBase.cxx
@@ -222,7 +222,7 @@ void ScintillaBase::AutoCompleteStart(int lenEntered, const char *list) {
}
}
ac.Start(wMain, idAutoComplete, sel.MainCaret(), PointMainCaret(),
- lenEntered, vs.lineHeight, IsUnicodeMode());
+ lenEntered, vs.lineHeight, IsUnicodeMode(), technology);
PRectangle rcClient = GetClientRectangle();
Point pt = LocationFromPosition(sel.MainCaret() - lenEntered);
@@ -419,6 +419,7 @@ void ScintillaBase::CallTipShow(Point pt, const char *defn) {
vs.styles[ctStyle].sizeZoomed,
CodePage(),
vs.styles[ctStyle].characterSet,
+ vs.technology,
wMain);
// If the call-tip window would be out of the client
// space, adjust so it displays above the text.
diff --git a/src/Style.cxx b/src/Style.cxx
index fc250f0bc..0a38cd6a5 100644
--- a/src/Style.cxx
+++ b/src/Style.cxx
@@ -33,7 +33,7 @@ void FontAlias::ClearFont() {
}
bool FontSpecification::EqualTo(const FontSpecification &other) const {
- return bold == other.bold &&
+ return weight == other.weight &&
italic == other.italic &&
size == other.size &&
characterSet == other.characterSet &&
@@ -56,18 +56,18 @@ void FontMeasurements::Clear() {
Style::Style() : FontSpecification() {
Clear(ColourDesired(0, 0, 0), ColourDesired(0xff, 0xff, 0xff),
- Platform::DefaultFontSize(), 0, SC_CHARSET_DEFAULT,
- false, false, false, false, caseMixed, true, true, false);
+ Platform::DefaultFontSize() * SC_FONT_SIZE_MULTIPLIER, 0, SC_CHARSET_DEFAULT,
+ SC_WEIGHT_NORMAL, false, false, false, caseMixed, true, true, false);
}
Style::Style(const Style &source) : FontSpecification(), FontMeasurements() {
Clear(ColourDesired(0, 0, 0), ColourDesired(0xff, 0xff, 0xff),
0, 0, 0,
- false, false, false, false, caseMixed, true, true, false);
+ SC_WEIGHT_NORMAL, false, false, false, caseMixed, true, true, false);
fore.desired = source.fore.desired;
back.desired = source.back.desired;
characterSet = source.characterSet;
- bold = source.bold;
+ weight = source.weight;
italic = source.italic;
size = source.size;
eolFilled = source.eolFilled;
@@ -86,11 +86,11 @@ Style &Style::operator=(const Style &source) {
return * this;
Clear(ColourDesired(0, 0, 0), ColourDesired(0xff, 0xff, 0xff),
0, 0, SC_CHARSET_DEFAULT,
- false, false, false, false, caseMixed, true, true, false);
+ SC_WEIGHT_NORMAL, false, false, false, caseMixed, true, true, false);
fore.desired = source.fore.desired;
back.desired = source.back.desired;
characterSet = source.characterSet;
- bold = source.bold;
+ weight = source.weight;
italic = source.italic;
size = source.size;
eolFilled = source.eolFilled;
@@ -103,13 +103,13 @@ Style &Style::operator=(const Style &source) {
void Style::Clear(ColourDesired fore_, ColourDesired back_, int size_,
const char *fontName_, int characterSet_,
- bool bold_, bool italic_, bool eolFilled_,
+ int weight_, bool italic_, bool eolFilled_,
bool underline_, ecaseForced caseForce_,
bool visible_, bool changeable_, bool hotspot_) {
fore.desired = fore_;
back.desired = back_;
characterSet = characterSet_;
- bold = bold_;
+ weight = weight_;
italic = italic_;
size = size_;
fontName = fontName_;
@@ -130,7 +130,7 @@ void Style::ClearTo(const Style &source) {
source.size,
source.fontName,
source.characterSet,
- source.bold,
+ source.weight,
source.italic,
source.eolFilled,
source.underline,
diff --git a/src/Style.h b/src/Style.h
index 29122b0a4..0e706d322 100644
--- a/src/Style.h
+++ b/src/Style.h
@@ -14,16 +14,16 @@ namespace Scintilla {
struct FontSpecification {
const char *fontName;
- bool bold;
+ int weight;
bool italic;
int size;
int characterSet;
int extraFontFlag;
FontSpecification() :
fontName(0),
- bold(false),
+ weight(SC_WEIGHT_NORMAL),
italic(false),
- size(10),
+ size(10 * SC_FONT_SIZE_MULTIPLIER),
characterSet(0),
extraFontFlag(0) {
}
@@ -77,7 +77,7 @@ public:
void Clear(ColourDesired fore_, ColourDesired back_,
int size_,
const char *fontName_, int characterSet_,
- bool bold_, bool italic_, bool eolFilled_,
+ int weight_, bool italic_, bool eolFilled_,
bool underline_, ecaseForced caseForce_,
bool visible_, bool changeable_, bool hotspot_);
void ClearTo(const Style &source);
diff --git a/src/ViewStyle.cxx b/src/ViewStyle.cxx
index 9ba69b1ce..08164f648 100644
--- a/src/ViewStyle.cxx
+++ b/src/ViewStyle.cxx
@@ -86,14 +86,15 @@ FontRealised::~FontRealised() {
frNext = 0;
}
-void FontRealised::Realise(Surface &surface, int zoomLevel) {
+void FontRealised::Realise(Surface &surface, int zoomLevel, int technology) {
PLATFORM_ASSERT(fontName);
- sizeZoomed = size + zoomLevel;
- if (sizeZoomed <= 2) // Hangs if sizeZoomed <= 1
- sizeZoomed = 2;
+ sizeZoomed = size + zoomLevel * SC_FONT_SIZE_MULTIPLIER;
+ if (sizeZoomed <= 2 * SC_FONT_SIZE_MULTIPLIER) // Hangs if sizeZoomed <= 1
+ sizeZoomed = 2 * SC_FONT_SIZE_MULTIPLIER;
- int deviceHeight = surface.DeviceHeightFont(sizeZoomed);
- font.Create(fontName, characterSet, deviceHeight, bold, italic, extraFontFlag);
+ float deviceHeight = surface.DeviceHeightFont(sizeZoomed);
+ FontParameters fp(fontName, deviceHeight / SC_FONT_SIZE_MULTIPLIER, weight, italic, extraFontFlag, technology, characterSet);
+ font.Create(fp);
ascent = surface.Ascent(font);
descent = surface.Descent(font);
@@ -102,7 +103,7 @@ void FontRealised::Realise(Surface &surface, int zoomLevel) {
aveCharWidth = surface.AverageCharWidth(font);
spaceWidth = surface.WidthChar(font, ' ');
if (frNext) {
- frNext->Realise(surface, zoomLevel);
+ frNext->Realise(surface, zoomLevel, technology);
}
}
@@ -239,6 +240,7 @@ void ViewStyle::Init(size_t stylesSize_) {
indicators[2].under = false;
indicators[2].fore = ColourDesired(0xff, 0, 0);
+ technology = SC_TECHNOLOGY_DEFAULT;
lineHeight = 1;
maxAscent = 1;
maxDescent = 1;
@@ -388,7 +390,7 @@ void ViewStyle::Refresh(Surface &surface) {
CreateFont(styles[j]);
}
- frFirst->Realise(surface, zoomLevel);
+ frFirst->Realise(surface, zoomLevel, technology);
for (unsigned int k=0; k<stylesSize; k++) {
FontRealised *fr = frFirst->Find(styles[k]);
@@ -457,9 +459,9 @@ void ViewStyle::EnsureStyle(size_t index) {
void ViewStyle::ResetDefaultStyle() {
styles[STYLE_DEFAULT].Clear(ColourDesired(0,0,0),
ColourDesired(0xff,0xff,0xff),
- Platform::DefaultFontSize(), fontNames.Save(Platform::DefaultFont()),
+ Platform::DefaultFontSize() * SC_FONT_SIZE_MULTIPLIER, fontNames.Save(Platform::DefaultFont()),
SC_CHARSET_DEFAULT,
- false, false, false, false, Style::caseMixed, true, true, false);
+ SC_WEIGHT_NORMAL, false, false, false, Style::caseMixed, true, true, false);
}
void ViewStyle::ClearStyles() {
diff --git a/src/ViewStyle.h b/src/ViewStyle.h
index b038a9b54..b15b9163c 100644
--- a/src/ViewStyle.h
+++ b/src/ViewStyle.h
@@ -48,7 +48,7 @@ public:
FontRealised *frNext;
FontRealised(const FontSpecification &fs);
virtual ~FontRealised();
- void Realise(Surface &surface, int zoomLevel);
+ void Realise(Surface &surface, int zoomLevel, int technology);
FontRealised *Find(const FontSpecification &fs);
void FindMaxAscentDescent(unsigned int &maxAscent, unsigned int &maxDescent);
};
@@ -67,6 +67,7 @@ public:
Style *styles;
LineMarker markers[MARKER_MAX + 1];
Indicator indicators[INDIC_MAX + 1];
+ int technology;
int lineHeight;
unsigned int maxAscent;
unsigned int maxDescent;
diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx
index 0ccc8aa13..00e0bf576 100644
--- a/win32/PlatWin.cxx
+++ b/win32/PlatWin.cxx
@@ -26,6 +26,8 @@
#include <commctrl.h>
#include <richedit.h>
#include <windowsx.h>
+#include <d2d1.h>
+#include <dwrite.h>
#include "Platform.h"
#include "UniConversion.h"
@@ -195,6 +197,88 @@ void Palette::Allocate(Window &) {
}
}
+IDWriteFactory *pIDWriteFactory = 0;
+ID2D1Factory *pD2DFactory = 0;
+
+bool LoadD2D() {
+ static bool triedLoadingD2D = false;
+ static HMODULE hDLLD2D = 0;
+ static HMODULE hDLLDWrite = 0;
+ if (!triedLoadingD2D) {
+ typedef HRESULT (WINAPI *D2D1CFSig)(D2D1_FACTORY_TYPE factoryType, REFIID riid,
+ CONST D2D1_FACTORY_OPTIONS *pFactoryOptions, IUnknown **factory);
+ typedef HRESULT (WINAPI *DWriteCFSig)(DWRITE_FACTORY_TYPE factoryType, REFIID iid,
+ IUnknown **factory);
+
+ hDLLD2D = ::LoadLibrary(TEXT("D2D1.DLL"));
+ if (hDLLD2D) {
+ D2D1CFSig fnD2DCF = (D2D1CFSig)::GetProcAddress(hDLLD2D, "D2D1CreateFactory");
+ if (fnD2DCF) {
+ // A single threaded factory as Scintilla always draw on the GUI thread
+ fnD2DCF(D2D1_FACTORY_TYPE_SINGLE_THREADED,
+ __uuidof(ID2D1Factory),
+ 0,
+ reinterpret_cast<IUnknown**>(&pD2DFactory));
+ }
+ }
+ hDLLDWrite = ::LoadLibrary(TEXT("DWRITE.DLL"));
+ if (hDLLDWrite) {
+ DWriteCFSig fnDWCF = (DWriteCFSig)::GetProcAddress(hDLLDWrite, "DWriteCreateFactory");
+ if (fnDWCF) {
+ fnDWCF(DWRITE_FACTORY_TYPE_SHARED,
+ __uuidof(IDWriteFactory),
+ reinterpret_cast<IUnknown**>(&pIDWriteFactory));
+ }
+ }
+ }
+ triedLoadingD2D = true;
+ return pIDWriteFactory && pD2DFactory;
+}
+
+struct FormatAndMetrics {
+ int technology;
+ HFONT hfont;
+ IDWriteTextFormat *pTextFormat;
+ int extraFontFlag;
+ FLOAT yAscent;
+ FLOAT yDescent;
+ FormatAndMetrics(HFONT hfont_, int extraFontFlag_) :
+ technology(SCWIN_TECH_GDI), hfont(hfont_), pTextFormat(0), extraFontFlag(extraFontFlag_), yAscent(2), yDescent(1) {
+ }
+ FormatAndMetrics(IDWriteTextFormat *pTextFormat_, int extraFontFlag_, FLOAT yAscent_, FLOAT yDescent_) :
+ technology(SCWIN_TECH_DIRECTWRITE), hfont(0), pTextFormat(pTextFormat_), extraFontFlag(extraFontFlag_), yAscent(yAscent_), yDescent(yDescent_) {
+ }
+ ~FormatAndMetrics() {
+ if (hfont)
+ ::DeleteObject(hfont);
+ if (pTextFormat)
+ pTextFormat->Release();
+ pTextFormat = 0;
+ extraFontFlag = 0;
+ yAscent = 2;
+ yDescent = 1;
+ }
+ HFONT HFont();
+};
+
+HFONT FormatAndMetrics::HFont() {
+ if (technology == SCWIN_TECH_GDI) {
+ return hfont;
+ } else {
+ LOGFONTW lf;
+ memset(&lf, 0, sizeof(lf));
+
+ HRESULT hr = pTextFormat->GetFontFamilyName(lf.lfFaceName, LF_FACESIZE);
+ if (SUCCEEDED(hr)) {
+ lf.lfWeight = pTextFormat->GetFontWeight();
+ lf.lfItalic = pTextFormat->GetFontStyle() == DWRITE_FONT_STYLE_ITALIC;
+ lf.lfHeight = -static_cast<int>(pTextFormat->GetFontSize());
+ return ::CreateFontIndirectW(&lf);
+ }
+ }
+ return 0;
+}
+
#ifndef CLEARTYPE_QUALITY
#define CLEARTYPE_QUALITY 5
#endif
@@ -216,11 +300,28 @@ static BYTE Win32MapFontQuality(int extraFontFlag) {
}
}
-static void SetLogFont(LOGFONTA &lf, const char *faceName, int characterSet, int size, bool bold, bool italic, int extraFontFlag) {
+static D2D1_TEXT_ANTIALIAS_MODE DWriteMapFontQuality(int extraFontFlag) {
+ switch (extraFontFlag & SC_EFF_QUALITY_MASK) {
+
+ case SC_EFF_QUALITY_NON_ANTIALIASED:
+ return D2D1_TEXT_ANTIALIAS_MODE_ALIASED;
+
+ case SC_EFF_QUALITY_ANTIALIASED:
+ return D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
+
+ case SC_EFF_QUALITY_LCD_OPTIMIZED:
+ return D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
+
+ default:
+ return D2D1_TEXT_ANTIALIAS_MODE_DEFAULT;
+ }
+}
+
+static void SetLogFont(LOGFONTA &lf, const char *faceName, int characterSet, float size, int weight, bool italic, int extraFontFlag) {
memset(&lf, 0, sizeof(lf));
// The negative is to allow for leading
- lf.lfHeight = -(abs(size));
- lf.lfWeight = bold ? FW_BOLD : FW_NORMAL;
+ lf.lfHeight = -(abs(static_cast<int>(size + 0.5)));
+ lf.lfWeight = weight;
lf.lfItalic = static_cast<BYTE>(italic ? 1 : 0);
lf.lfCharSet = static_cast<BYTE>(characterSet);
lf.lfQuality = Win32MapFontQuality(extraFontFlag);
@@ -232,71 +333,111 @@ static void SetLogFont(LOGFONTA &lf, const char *faceName, int characterSet, int
* If one font is the same as another, its hash will be the same, but if the hash is the
* same then they may still be different.
*/
-static int HashFont(const char *faceName, int characterSet, int size, bool bold, bool italic, int extraFontFlag) {
+static int HashFont(const FontParameters &fp) {
return
- size ^
- (characterSet << 10) ^
- ((extraFontFlag & SC_EFF_QUALITY_MASK) << 9) ^
- (bold ? 0x10000000 : 0) ^
- (italic ? 0x20000000 : 0) ^
- faceName[0];
+ static_cast<int>(fp.size) ^
+ (fp.characterSet << 10) ^
+ ((fp.extraFontFlag & SC_EFF_QUALITY_MASK) << 9) ^
+ ((fp.weight/100) << 12) ^
+ (fp.italic ? 0x20000000 : 0) ^
+ (fp.technology << 15) ^
+ fp.faceName[0];
}
class FontCached : Font {
FontCached *next;
int usage;
+ float size;
LOGFONTA lf;
+ int technology;
int hash;
- FontCached(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_, int extraFontFlag_);
+ FontCached(const FontParameters &fp);
~FontCached() {}
- bool SameAs(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_, int extraFontFlag_);
+ bool SameAs(const FontParameters &fp);
virtual void Release();
static FontCached *first;
public:
- static FontID FindOrCreate(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_, int extraFontFlag_);
+ static FontID FindOrCreate(const FontParameters &fp);
static void ReleaseId(FontID fid_);
};
FontCached *FontCached::first = 0;
-FontCached::FontCached(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_, int extraFontFlag_) :
- next(0), usage(0), hash(0) {
- SetLogFont(lf, faceName_, characterSet_, size_, bold_, italic_, extraFontFlag_);
- hash = HashFont(faceName_, characterSet_, size_, bold_, italic_, extraFontFlag_);
- fid = ::CreateFontIndirectA(&lf);
+FontCached::FontCached(const FontParameters &fp) :
+ next(0), usage(0), size(1.0), hash(0) {
+ SetLogFont(lf, fp.faceName, fp.characterSet, fp.size, fp.weight, fp.italic, fp.extraFontFlag);
+ technology = fp.technology;
+ hash = HashFont(fp);
+ fid = 0;
+ if (technology == SCWIN_TECH_GDI) {
+ HFONT hfont = ::CreateFontIndirectA(&lf);
+ fid = reinterpret_cast<void *>(new FormatAndMetrics(hfont, fp.extraFontFlag));
+ } else {
+ IDWriteTextFormat *pTextFormat;
+ const int faceSize = 200;
+ WCHAR wszFace[faceSize];
+ UTF16FromUTF8(fp.faceName, strlen(fp.faceName)+1, wszFace, faceSize);
+ FLOAT fHeight = fp.size;
+ DWRITE_FONT_STYLE style = fp.italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL;
+ HRESULT hr = pIDWriteFactory->CreateTextFormat(wszFace, NULL,
+ static_cast<DWRITE_FONT_WEIGHT>(fp.weight),
+ style,
+ DWRITE_FONT_STRETCH_NORMAL, fHeight, L"en-us", &pTextFormat);
+ if (SUCCEEDED(hr)) {
+ pTextFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP);
+
+ const int maxLines = 2;
+ DWRITE_LINE_METRICS lineMetrics[maxLines];
+ UINT32 lineCount = 0;
+ FLOAT yAscent = 1.0f;
+ FLOAT yDescent = 1.0f;
+ IDWriteTextLayout *pTextLayout = 0;
+ hr = pIDWriteFactory->CreateTextLayout(L"X", 1, pTextFormat,
+ 100.0f, 100.0f, &pTextLayout);
+ if (SUCCEEDED(hr)) {
+ hr = pTextLayout->GetLineMetrics(lineMetrics, maxLines, &lineCount);
+ if (SUCCEEDED(hr)) {
+ yAscent = lineMetrics[0].baseline;
+ yDescent = lineMetrics[0].height - lineMetrics[0].baseline;
+ }
+ pTextLayout->Release();
+ }
+ fid = reinterpret_cast<void *>(new FormatAndMetrics(pTextFormat, fp.extraFontFlag, yAscent, yDescent));
+ }
+ }
usage = 1;
}
-bool FontCached::SameAs(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_, int extraFontFlag_) {
+bool FontCached::SameAs(const FontParameters &fp) {
return
- (lf.lfHeight == -(abs(size_))) &&
- (lf.lfWeight == (bold_ ? FW_BOLD : FW_NORMAL)) &&
- (lf.lfItalic == static_cast<BYTE>(italic_ ? 1 : 0)) &&
- (lf.lfCharSet == characterSet_) &&
- (lf.lfQuality == Win32MapFontQuality(extraFontFlag_)) &&
- 0 == strcmp(lf.lfFaceName,faceName_);
+ (size == fp.size) &&
+ (lf.lfWeight == fp.weight) &&
+ (lf.lfItalic == static_cast<BYTE>(fp.italic ? 1 : 0)) &&
+ (lf.lfCharSet == fp.characterSet) &&
+ (lf.lfQuality == Win32MapFontQuality(fp.extraFontFlag)) &&
+ (technology == fp.technology) &&
+ 0 == strcmp(lf.lfFaceName,fp.faceName);
}
void FontCached::Release() {
- if (fid)
- ::DeleteObject(fid);
+ delete reinterpret_cast<FormatAndMetrics *>(fid);
fid = 0;
}
-FontID FontCached::FindOrCreate(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_, int extraFontFlag_) {
+FontID FontCached::FindOrCreate(const FontParameters &fp) {
FontID ret = 0;
::EnterCriticalSection(&crPlatformLock);
- int hashFind = HashFont(faceName_, characterSet_, size_, bold_, italic_, extraFontFlag_);
+ int hashFind = HashFont(fp);
for (FontCached *cur=first; cur; cur=cur->next) {
if ((cur->hash == hashFind) &&
- cur->SameAs(faceName_, characterSet_, size_, bold_, italic_, extraFontFlag_)) {
+ cur->SameAs(fp)) {
cur->usage++;
ret = cur->fid;
}
}
if (ret == 0) {
- FontCached *fc = new FontCached(faceName_, characterSet_, size_, bold_, italic_, extraFontFlag_);
+ FontCached *fc = new FontCached(fp);
if (fc) {
fc->next = first;
first = fc;
@@ -335,35 +476,62 @@ Font::~Font() {
#define FONTS_CACHED
-void Font::Create(const char *faceName, int characterSet, int size,
- bool bold, bool italic, int extraFontFlag) {
+void Font::Create(const FontParameters &fp) {
Release();
-#ifndef FONTS_CACHED
- LOGFONT lf;
- SetLogFont(lf, faceName, characterSet, size, bold, italic, extraFontFlag);
- fid = ::CreateFontIndirect(&lf);
-#else
- if (faceName)
- fid = FontCached::FindOrCreate(faceName, characterSet, size, bold, italic, extraFontFlag);
-#endif
+ if (fp.faceName)
+ fid = FontCached::FindOrCreate(fp);
}
void Font::Release() {
-#ifndef FONTS_CACHED
- if (fid)
- ::DeleteObject(fid);
-#else
if (fid)
FontCached::ReleaseId(fid);
-#endif
fid = 0;
}
+// Buffer to hold strings and string position arrays without always allocating on heap.
+// May sometimes have string too long to allocate on stack. So use a fixed stack-allocated buffer
+// when less than safe size otherwise allocate on heap and free automatically.
+template<typename T, int lengthStandard>
+class VarBuffer {
+ T bufferStandard[lengthStandard];
+public:
+ T *buffer;
+ VarBuffer(size_t length) : buffer(0) {
+ if (length > lengthStandard) {
+ buffer = new T[length];
+ } else {
+ buffer = bufferStandard;
+ }
+ }
+ ~VarBuffer() {
+ if (buffer != bufferStandard) {
+ delete []buffer;
+ buffer = 0;
+ }
+ }
+};
+
+const int stackBufferLength = 10000;
+class TextWide : public VarBuffer<wchar_t, stackBufferLength> {
+public:
+ int tlen;
+ TextWide(const char *s, int len, bool unicodeMode, int codePage=0) :
+ VarBuffer<wchar_t, stackBufferLength>(len) {
+ if (unicodeMode) {
+ tlen = UTF16FromUTF8(s, len, buffer, len);
+ } else {
+ // Support Asian string display in 9x English
+ tlen = ::MultiByteToWideChar(codePage, 0, s, len, buffer, len);
+ }
+ }
+};
+typedef VarBuffer<XYPOSITION, stackBufferLength> TextPositions;
+
#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif
-class SurfaceImpl : public Surface {
+class SurfaceGDI : public Surface {
bool unicodeMode;
HDC hdc;
bool hdcOwned;
@@ -386,12 +554,12 @@ class SurfaceImpl : public Surface {
void BrushColor(ColourAllocated back);
void SetFont(Font &font_);
- // Private so SurfaceImpl objects can not be copied
- SurfaceImpl(const SurfaceImpl &);
- SurfaceImpl &operator=(const SurfaceImpl &);
+ // Private so SurfaceGDI objects can not be copied
+ SurfaceGDI(const SurfaceGDI &);
+ SurfaceGDI &operator=(const SurfaceGDI &);
public:
- SurfaceImpl();
- virtual ~SurfaceImpl();
+ SurfaceGDI();
+ virtual ~SurfaceGDI();
void Init(WindowID wid);
void Init(SurfaceID sid, WindowID wid);
@@ -415,19 +583,19 @@ public:
void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back);
void Copy(PRectangle rc, Point from, Surface &surfaceSource);
- void DrawTextCommon(PRectangle rc, Font &font_, int ybase, const char *s, int len, UINT fuOptions);
- void DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
- void DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
- void DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore);
- void MeasureWidths(Font &font_, const char *s, int len, int *positions);
- int WidthText(Font &font_, const char *s, int len);
- int WidthChar(Font &font_, char ch);
- int Ascent(Font &font_);
- int Descent(Font &font_);
- int InternalLeading(Font &font_);
- int ExternalLeading(Font &font_);
- int Height(Font &font_);
- int AverageCharWidth(Font &font_);
+ void DrawTextCommon(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, UINT fuOptions);
+ void DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
+ void DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
+ void DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore);
+ void MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions);
+ XYPOSITION WidthText(Font &font_, const char *s, int len);
+ XYPOSITION WidthChar(Font &font_, char ch);
+ XYPOSITION Ascent(Font &font_);
+ XYPOSITION Descent(Font &font_);
+ XYPOSITION InternalLeading(Font &font_);
+ XYPOSITION ExternalLeading(Font &font_);
+ XYPOSITION Height(Font &font_);
+ XYPOSITION AverageCharWidth(Font &font_);
int SetPalette(Palette *pal, bool inBackGround);
void SetClip(PRectangle rc);
@@ -441,7 +609,7 @@ public:
} //namespace Scintilla
#endif
-SurfaceImpl::SurfaceImpl() :
+SurfaceGDI::SurfaceGDI() :
unicodeMode(false),
hdc(0), hdcOwned(false),
pen(0), penOld(0),
@@ -459,11 +627,11 @@ SurfaceImpl::SurfaceImpl() :
win9xACPSame = false;
}
-SurfaceImpl::~SurfaceImpl() {
+SurfaceGDI::~SurfaceGDI() {
Release();
}
-void SurfaceImpl::Release() {
+void SurfaceGDI::Release() {
if (penOld) {
::SelectObject(reinterpret_cast<HDC>(hdc), penOld);
::DeleteObject(pen);
@@ -501,33 +669,33 @@ void SurfaceImpl::Release() {
}
}
-bool SurfaceImpl::Initialised() {
+bool SurfaceGDI::Initialised() {
return hdc != 0;
}
-void SurfaceImpl::Init(WindowID) {
+void SurfaceGDI::Init(WindowID) {
Release();
hdc = ::CreateCompatibleDC(NULL);
hdcOwned = true;
::SetTextAlign(reinterpret_cast<HDC>(hdc), TA_BASELINE);
}
-void SurfaceImpl::Init(SurfaceID sid, WindowID) {
+void SurfaceGDI::Init(SurfaceID sid, WindowID) {
Release();
hdc = reinterpret_cast<HDC>(sid);
::SetTextAlign(reinterpret_cast<HDC>(hdc), TA_BASELINE);
}
-void SurfaceImpl::InitPixMap(int width, int height, Surface *surface_, WindowID) {
+void SurfaceGDI::InitPixMap(int width, int height, Surface *surface_, WindowID) {
Release();
- hdc = ::CreateCompatibleDC(static_cast<SurfaceImpl *>(surface_)->hdc);
+ hdc = ::CreateCompatibleDC(static_cast<SurfaceGDI *>(surface_)->hdc);
hdcOwned = true;
- bitmap = ::CreateCompatibleBitmap(static_cast<SurfaceImpl *>(surface_)->hdc, width, height);
+ bitmap = ::CreateCompatibleBitmap(static_cast<SurfaceGDI *>(surface_)->hdc, width, height);
bitmapOld = static_cast<HBITMAP>(::SelectObject(hdc, bitmap));
::SetTextAlign(reinterpret_cast<HDC>(hdc), TA_BASELINE);
}
-void SurfaceImpl::PenColour(ColourAllocated fore) {
+void SurfaceGDI::PenColour(ColourAllocated fore) {
if (pen) {
::SelectObject(hdc, penOld);
::DeleteObject(pen);
@@ -538,7 +706,7 @@ void SurfaceImpl::PenColour(ColourAllocated fore) {
penOld = static_cast<HPEN>(::SelectObject(reinterpret_cast<HDC>(hdc), pen));
}
-void SurfaceImpl::BrushColor(ColourAllocated back) {
+void SurfaceGDI::BrushColor(ColourAllocated back) {
if (brush) {
::SelectObject(hdc, brushOld);
::DeleteObject(brush);
@@ -551,46 +719,48 @@ void SurfaceImpl::BrushColor(ColourAllocated back) {
brushOld = static_cast<HBRUSH>(::SelectObject(hdc, brush));
}
-void SurfaceImpl::SetFont(Font &font_) {
+void SurfaceGDI::SetFont(Font &font_) {
if (font_.GetID() != font) {
+ FormatAndMetrics *pfm = reinterpret_cast<FormatAndMetrics *>(font_.GetID());
+ PLATFORM_ASSERT(pfm->technology == SCWIN_TECH_GDI);
if (fontOld) {
- ::SelectObject(hdc, font_.GetID());
+ ::SelectObject(hdc, pfm->hfont);
} else {
- fontOld = static_cast<HFONT>(::SelectObject(hdc, font_.GetID()));
+ fontOld = static_cast<HFONT>(::SelectObject(hdc, pfm->hfont));
}
- font = reinterpret_cast<HFONT>(font_.GetID());
+ font = reinterpret_cast<HFONT>(pfm->hfont);
}
}
-int SurfaceImpl::LogPixelsY() {
+int SurfaceGDI::LogPixelsY() {
return ::GetDeviceCaps(hdc, LOGPIXELSY);
}
-int SurfaceImpl::DeviceHeightFont(int points) {
+int SurfaceGDI::DeviceHeightFont(int points) {
return ::MulDiv(points, LogPixelsY(), 72);
}
-void SurfaceImpl::MoveTo(int x_, int y_) {
+void SurfaceGDI::MoveTo(int x_, int y_) {
::MoveToEx(hdc, x_, y_, 0);
}
-void SurfaceImpl::LineTo(int x_, int y_) {
+void SurfaceGDI::LineTo(int x_, int y_) {
::LineTo(hdc, x_, y_);
}
-void SurfaceImpl::Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back) {
+void SurfaceGDI::Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back) {
PenColour(fore);
BrushColor(back);
::Polygon(hdc, reinterpret_cast<POINT *>(pts), npts);
}
-void SurfaceImpl::RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
+void SurfaceGDI::RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
PenColour(fore);
BrushColor(back);
::Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom);
}
-void SurfaceImpl::FillRectangle(PRectangle rc, ColourAllocated back) {
+void SurfaceGDI::FillRectangle(PRectangle rc, ColourAllocated back) {
// Using ExtTextOut rather than a FillRect ensures that no dithering occurs.
// There is no need to allocate a brush either.
RECT rcw = RectFromPRectangle(rc);
@@ -598,10 +768,10 @@ void SurfaceImpl::FillRectangle(PRectangle rc, ColourAllocated back) {
::ExtTextOut(hdc, rc.left, rc.top, ETO_OPAQUE, &rcw, TEXT(""), 0, NULL);
}
-void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) {
+void SurfaceGDI::FillRectangle(PRectangle rc, Surface &surfacePattern) {
HBRUSH br;
- if (static_cast<SurfaceImpl &>(surfacePattern).bitmap)
- br = ::CreatePatternBrush(static_cast<SurfaceImpl &>(surfacePattern).bitmap);
+ if (static_cast<SurfaceGDI &>(surfacePattern).bitmap)
+ br = ::CreatePatternBrush(static_cast<SurfaceGDI &>(surfacePattern).bitmap);
else // Something is wrong so display in red
br = ::CreateSolidBrush(RGB(0xff, 0, 0));
RECT rcw = RectFromPRectangle(rc);
@@ -609,7 +779,7 @@ void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) {
::DeleteObject(br);
}
-void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
+void SurfaceGDI::RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
PenColour(fore);
BrushColor(back);
::RoundRect(hdc,
@@ -645,7 +815,7 @@ static DWORD dwordFromBGRA(byte b, byte g, byte r, byte a) {
return converter.val;
}
-void SurfaceImpl::AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill,
+void SurfaceGDI::AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill,
ColourAllocated outline, int alphaOutline, int /* flags*/ ) {
if (AlphaBlendFn && rc.Width() > 0) {
HDC hMemDC = ::CreateCompatibleDC(reinterpret_cast<HDC>(hdc));
@@ -704,7 +874,7 @@ void SurfaceImpl::AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated
}
}
-void SurfaceImpl::DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) {
+void SurfaceGDI::DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) {
if (AlphaBlendFn && rc.Width() > 0) {
HDC hMemDC = ::CreateCompatibleDC(reinterpret_cast<HDC>(hdc));
if (rc.Width() > width)
@@ -743,58 +913,21 @@ void SurfaceImpl::DrawRGBAImage(PRectangle rc, int width, int height, const unsi
}
}
-void SurfaceImpl::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
+void SurfaceGDI::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
PenColour(fore);
BrushColor(back);
::Ellipse(hdc, rc.left, rc.top, rc.right, rc.bottom);
}
-void SurfaceImpl::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
+void SurfaceGDI::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
::BitBlt(hdc,
rc.left, rc.top, rc.Width(), rc.Height(),
- static_cast<SurfaceImpl &>(surfaceSource).hdc, from.x, from.y, SRCCOPY);
+ static_cast<SurfaceGDI &>(surfaceSource).hdc, from.x, from.y, SRCCOPY);
}
-// Buffer to hold strings and string position arrays without always allocating on heap.
-// May sometimes have string too long to allocate on stack. So use a fixed stack-allocated buffer
-// when less than safe size otherwise allocate on heap and free automatically.
-template<typename T, int lengthStandard>
-class VarBuffer {
- T bufferStandard[lengthStandard];
-public:
- T *buffer;
- VarBuffer(size_t length) : buffer(0) {
- if (length > lengthStandard) {
- buffer = new T[length];
- } else {
- buffer = bufferStandard;
- }
- }
- ~VarBuffer() {
- if (buffer != bufferStandard) {
- delete []buffer;
- buffer = 0;
- }
- }
-};
+typedef VarBuffer<int, stackBufferLength> TextPositionsI;
-const int stackBufferLength = 10000;
-class TextWide : public VarBuffer<wchar_t, stackBufferLength> {
-public:
- int tlen;
- TextWide(const char *s, int len, bool unicodeMode, int codePage=0) :
- VarBuffer<wchar_t, stackBufferLength>(len) {
- if (unicodeMode) {
- tlen = UTF16FromUTF8(s, len, buffer, len);
- } else {
- // Support Asian string display in 9x English
- tlen = ::MultiByteToWideChar(codePage, 0, s, len, buffer, len);
- }
- }
-};
-typedef VarBuffer<int, stackBufferLength> TextPositions;
-
-void SurfaceImpl::DrawTextCommon(PRectangle rc, Font &font_, int ybase, const char *s, int len, UINT fuOptions) {
+void SurfaceGDI::DrawTextCommon(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, UINT fuOptions) {
SetFont(font_);
RECT rcw = RectFromPRectangle(rc);
SIZE sz={0,0};
@@ -838,21 +971,21 @@ void SurfaceImpl::DrawTextCommon(PRectangle rc, Font &font_, int ybase, const ch
}
}
-void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len,
+void SurfaceGDI::DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len,
ColourAllocated fore, ColourAllocated back) {
::SetTextColor(hdc, fore.AsLong());
::SetBkColor(hdc, back.AsLong());
DrawTextCommon(rc, font_, ybase, s, len, ETO_OPAQUE);
}
-void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len,
+void SurfaceGDI::DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len,
ColourAllocated fore, ColourAllocated back) {
::SetTextColor(hdc, fore.AsLong());
::SetBkColor(hdc, back.AsLong());
DrawTextCommon(rc, font_, ybase, s, len, ETO_OPAQUE | ETO_CLIPPED);
}
-void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len,
+void SurfaceGDI::DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len,
ColourAllocated fore) {
// Avoid drawing spaces in transparent mode
for (int i=0;i<len;i++) {
@@ -866,7 +999,7 @@ void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, int ybase, con
}
}
-int SurfaceImpl::WidthText(Font &font_, const char *s, int len) {
+XYPOSITION SurfaceGDI::WidthText(Font &font_, const char *s, int len) {
SetFont(font_);
SIZE sz={0,0};
if ((!unicodeMode) && (IsNT() || (codePage==0) || win9xACPSame)) {
@@ -878,13 +1011,13 @@ int SurfaceImpl::WidthText(Font &font_, const char *s, int len) {
return sz.cx;
}
-void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positions) {
+void SurfaceGDI::MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions) {
SetFont(font_);
SIZE sz={0,0};
int fit = 0;
if (unicodeMode) {
const TextWide tbuf(s, len, unicodeMode, codePage);
- TextPositions poses(tbuf.tlen);
+ TextPositionsI poses(tbuf.tlen);
fit = tbuf.tlen;
if (!::GetTextExtentExPointW(hdc, tbuf.buffer, tbuf.tlen, maxWidthMeasure, &fit, poses.buffer, &sz)) {
// Likely to have failed because on Windows 9x where function not available
@@ -928,19 +1061,19 @@ void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positi
int startOffset = 0;
while (len > 0) {
int lenBlock = Platform::Minimum(len, maxLenText);
- if (!::GetTextExtentExPointA(hdc, s, lenBlock, maxWidthMeasure, &fit, positions, &sz)) {
+ TextPositionsI poses(len);
+ if (!::GetTextExtentExPointA(hdc, s, lenBlock, maxWidthMeasure, &fit, poses.buffer, &sz)) {
// Eeek - a NULL DC or other foolishness could cause this.
return;
} else if (fit < lenBlock) {
// For some reason, such as an incomplete DBCS character
// Not all the positions are filled in so make them equal to end.
- for (int i=fit;i<lenBlock;i++)
- positions[i] = positions[fit-1];
- } else if (startOffset > 0) {
- for (int i=0;i<lenBlock;i++)
- positions[i] += startOffset;
+ for (int i = fit;i<lenBlock;i++)
+ poses.buffer[i] = poses.buffer[fit-1];
}
- startOffset = positions[lenBlock-1];
+ for (int i=0;i<lenBlock;i++)
+ positions[i] = poses.buffer[i] + startOffset;
+ startOffset = poses.buffer[lenBlock-1];
len -= lenBlock;
positions += lenBlock;
s += lenBlock;
@@ -948,7 +1081,7 @@ void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positi
} else {
// Support Asian string display in 9x English
const TextWide tbuf(s, len, unicodeMode, codePage);
- TextPositions poses(tbuf.tlen);
+ TextPositionsI poses(tbuf.tlen);
for (int widthSS=0; widthSS<tbuf.tlen; widthSS++) {
::GetTextExtentPoint32W(hdc, tbuf.buffer, widthSS+1, &sz);
poses.buffer[widthSS] = sz.cx;
@@ -970,56 +1103,56 @@ void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positi
}
}
-int SurfaceImpl::WidthChar(Font &font_, char ch) {
+XYPOSITION SurfaceGDI::WidthChar(Font &font_, char ch) {
SetFont(font_);
SIZE sz;
::GetTextExtentPoint32A(hdc, &ch, 1, &sz);
return sz.cx;
}
-int SurfaceImpl::Ascent(Font &font_) {
+XYPOSITION SurfaceGDI::Ascent(Font &font_) {
SetFont(font_);
TEXTMETRIC tm;
::GetTextMetrics(hdc, &tm);
return tm.tmAscent;
}
-int SurfaceImpl::Descent(Font &font_) {
+XYPOSITION SurfaceGDI::Descent(Font &font_) {
SetFont(font_);
TEXTMETRIC tm;
::GetTextMetrics(hdc, &tm);
return tm.tmDescent;
}
-int SurfaceImpl::InternalLeading(Font &font_) {
+XYPOSITION SurfaceGDI::InternalLeading(Font &font_) {
SetFont(font_);
TEXTMETRIC tm;
::GetTextMetrics(hdc, &tm);
return tm.tmInternalLeading;
}
-int SurfaceImpl::ExternalLeading(Font &font_) {
+XYPOSITION SurfaceGDI::ExternalLeading(Font &font_) {
SetFont(font_);
TEXTMETRIC tm;
::GetTextMetrics(hdc, &tm);
return tm.tmExternalLeading;
}
-int SurfaceImpl::Height(Font &font_) {
+XYPOSITION SurfaceGDI::Height(Font &font_) {
SetFont(font_);
TEXTMETRIC tm;
::GetTextMetrics(hdc, &tm);
return tm.tmHeight;
}
-int SurfaceImpl::AverageCharWidth(Font &font_) {
+XYPOSITION SurfaceGDI::AverageCharWidth(Font &font_) {
SetFont(font_);
TEXTMETRIC tm;
::GetTextMetrics(hdc, &tm);
return tm.tmAveCharWidth;
}
-int SurfaceImpl::SetPalette(Palette *pal, bool inBackGround) {
+int SurfaceGDI::SetPalette(Palette *pal, bool inBackGround) {
if (paletteOld) {
::SelectPalette(hdc, paletteOld, TRUE);
}
@@ -1033,28 +1166,705 @@ int SurfaceImpl::SetPalette(Palette *pal, bool inBackGround) {
return changes;
}
-void SurfaceImpl::SetClip(PRectangle rc) {
+void SurfaceGDI::SetClip(PRectangle rc) {
::IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom);
}
-void SurfaceImpl::FlushCachedState() {
+void SurfaceGDI::FlushCachedState() {
pen = 0;
brush = 0;
font = 0;
}
-void SurfaceImpl::SetUnicodeMode(bool unicodeMode_) {
+void SurfaceGDI::SetUnicodeMode(bool unicodeMode_) {
unicodeMode=unicodeMode_;
}
-void SurfaceImpl::SetDBCSMode(int codePage_) {
+void SurfaceGDI::SetDBCSMode(int codePage_) {
// No action on window as automatically handled by system.
codePage = codePage_;
win9xACPSame = !IsNT() && ((unsigned int)codePage == ::GetACP());
}
-Surface *Surface::Allocate() {
- return new SurfaceImpl;
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+class SurfaceD2D : public Surface {
+ bool unicodeMode;
+ int x, y;
+
+ int codePage;
+
+ ID2D1RenderTarget *pRenderTarget;
+ bool ownRenderTarget;
+ int clipsActive;
+
+ IDWriteTextFormat *pTextFormat;
+ FLOAT yAscent;
+ FLOAT yDescent;
+
+ ID2D1SolidColorBrush *pBrush;
+
+ int logPixelsY;
+ float dpiScaleX;
+ float dpiScaleY;
+
+ void SetFont(Font &font_);
+
+ // Private so SurfaceD2D objects can not be copied
+ SurfaceD2D(const SurfaceD2D &);
+ SurfaceD2D &operator=(const SurfaceD2D &);
+public:
+ SurfaceD2D();
+ virtual ~SurfaceD2D();
+
+ void SetScale();
+ void Init(WindowID wid);
+ void Init(SurfaceID sid, WindowID wid);
+ void InitPixMap(int width, int height, Surface *surface_, WindowID wid);
+
+ void Release();
+ bool Initialised();
+
+ HRESULT FlushDrawing();
+
+ void PenColour(ColourAllocated fore);
+ void D2DPenColour(ColourAllocated fore, int alpha=255);
+ int LogPixelsY();
+ int DeviceHeightFont(int points);
+ void MoveTo(int x_, int y_);
+ void LineTo(int x_, int y_);
+ void Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back);
+ void RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back);
+ void FillRectangle(PRectangle rc, ColourAllocated back);
+ void FillRectangle(PRectangle rc, Surface &surfacePattern);
+ void RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back);
+ void AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill,
+ ColourAllocated outline, int alphaOutline, int flags);
+ void DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage);
+ void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back);
+ void Copy(PRectangle rc, Point from, Surface &surfaceSource);
+
+ void DrawTextCommon(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, UINT fuOptions);
+ void DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
+ void DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
+ void DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourAllocated fore);
+ void MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions);
+ XYPOSITION WidthText(Font &font_, const char *s, int len);
+ XYPOSITION WidthChar(Font &font_, char ch);
+ XYPOSITION Ascent(Font &font_);
+ XYPOSITION Descent(Font &font_);
+ XYPOSITION InternalLeading(Font &font_);
+ XYPOSITION ExternalLeading(Font &font_);
+ XYPOSITION Height(Font &font_);
+ XYPOSITION AverageCharWidth(Font &font_);
+
+ int SetPalette(Palette *pal, bool inBackGround);
+ void SetClip(PRectangle rc);
+ void FlushCachedState();
+
+ void SetUnicodeMode(bool unicodeMode_);
+ void SetDBCSMode(int codePage_);
+};
+
+#ifdef SCI_NAMESPACE
+} //namespace Scintilla
+#endif
+
+SurfaceD2D::SurfaceD2D() :
+ unicodeMode(false),
+ x(0), y(0) {
+
+ codePage = 0;
+
+ pRenderTarget = NULL;
+ ownRenderTarget = false;
+ clipsActive = 0;
+
+ // From selected font
+ pTextFormat = NULL;
+ yAscent = 2;
+ yDescent = 1;
+
+ pBrush = NULL;
+
+ logPixelsY = 72;
+ dpiScaleX = 1.0;
+ dpiScaleY = 1.0;
+}
+
+SurfaceD2D::~SurfaceD2D() {
+ Release();
+}
+
+void SurfaceD2D::Release() {
+ if (pBrush) {
+ pBrush->Release();
+ pBrush = 0;
+ }
+ if (pRenderTarget) {
+ while (clipsActive) {
+ pRenderTarget->PopAxisAlignedClip();
+ clipsActive--;
+ }
+ if (ownRenderTarget) {
+ pRenderTarget->Release();
+ }
+ pRenderTarget = 0;
+ }
+}
+
+void SurfaceD2D::SetScale() {
+ HDC hdcMeasure = ::CreateCompatibleDC(NULL);
+ logPixelsY = ::GetDeviceCaps(hdcMeasure, LOGPIXELSY);
+ dpiScaleX = ::GetDeviceCaps(hdcMeasure, LOGPIXELSX) / 96.0f;
+ dpiScaleY = logPixelsY / 96.0f;
+ ::DeleteDC(hdcMeasure);
+}
+
+bool SurfaceD2D::Initialised() {
+ return pRenderTarget != 0;
+}
+
+HRESULT SurfaceD2D::FlushDrawing() {
+ return pRenderTarget->Flush();
+}
+
+void SurfaceD2D::Init(WindowID /* wid */) {
+ Release();
+ SetScale();
+}
+
+void SurfaceD2D::Init(SurfaceID sid, WindowID) {
+ Release();
+ SetScale();
+ pRenderTarget = reinterpret_cast<ID2D1HwndRenderTarget *>(sid);
+}
+
+void SurfaceD2D::InitPixMap(int width, int height, Surface *surface_, WindowID) {
+ Release();
+ SetScale();
+ SurfaceD2D *psurfOther = static_cast<SurfaceD2D *>(surface_);
+ ID2D1BitmapRenderTarget *pCompatibleRenderTarget = NULL;
+ HRESULT hr = psurfOther->pRenderTarget->CreateCompatibleRenderTarget(
+ D2D1::SizeF(width, height), &pCompatibleRenderTarget);
+ if (SUCCEEDED(hr)) {
+ pRenderTarget = pCompatibleRenderTarget;
+ pRenderTarget->BeginDraw();
+ ownRenderTarget = true;
+ }
+}
+
+void SurfaceD2D::PenColour(ColourAllocated fore) {
+ D2DPenColour(fore);
+}
+
+void SurfaceD2D::D2DPenColour(ColourAllocated fore, int alpha) {
+ if (pRenderTarget) {
+ D2D_COLOR_F col;
+ col.r = (fore.AsLong() & 0xff) / 255.0;
+ col.g = ((fore.AsLong() & 0xff00) >> 8) / 255.0;
+ col.b = (fore.AsLong() >> 16) / 255.0;
+ col.a = alpha / 255.0;
+ if (pBrush) {
+ pBrush->SetColor(col);
+ } else {
+ HRESULT hr = pRenderTarget->CreateSolidColorBrush(col, &pBrush);
+ if (!SUCCEEDED(hr) && pBrush) {
+ pBrush->Release();
+ pBrush = 0;
+ }
+ }
+ }
+}
+
+void SurfaceD2D::SetFont(Font &font_) {
+ FormatAndMetrics *pfm = reinterpret_cast<FormatAndMetrics *>(font_.GetID());
+ PLATFORM_ASSERT(pfm->technology == SCWIN_TECH_DIRECTWRITE);
+ pTextFormat = pfm->pTextFormat;
+ yAscent = pfm->yAscent;
+ yDescent = pfm->yDescent;
+ if (pRenderTarget) {
+ pRenderTarget->SetTextAntialiasMode(DWriteMapFontQuality(pfm->extraFontFlag));
+ }
+}
+
+int SurfaceD2D::LogPixelsY() {
+ return logPixelsY;
+}
+
+int SurfaceD2D::DeviceHeightFont(int points) {
+ return ::MulDiv(points, LogPixelsY(), 72);
+}
+
+void SurfaceD2D::MoveTo(int x_, int y_) {
+ x = x_;
+ y = y_;
+}
+
+static int Delta(int difference) {
+ if (difference < 0)
+ return -1;
+ else if (difference > 0)
+ return 1;
+ else
+ return 0;
+}
+
+static int RoundFloat(float f) {
+ return int(f+0.5);
+}
+
+void SurfaceD2D::LineTo(int x_, int y_) {
+ if (pRenderTarget) {
+ int xDiff = x_ - x;
+ int xDelta = Delta(xDiff);
+ int yDiff = y_ - y;
+ int yDelta = Delta(yDiff);
+ if ((xDiff == 0) || (yDiff == 0)) {
+ // Horizontal or vertical lines can be more precisely drawn as a filled rectangle
+ int xEnd = x_ - xDelta;
+ int left = Platform::Minimum(x, xEnd);
+ int width = abs(x - xEnd) + 1;
+ int yEnd = y_ - yDelta;
+ int top = Platform::Minimum(y, yEnd);
+ int height = abs(y - yEnd) + 1;
+ D2D1_RECT_F rectangle1 = D2D1::RectF(left, top, left+width, top+height);
+ pRenderTarget->FillRectangle(&rectangle1, pBrush);
+ } else if ((abs(xDiff) == abs(yDiff))) {
+ // 45 degree slope
+ pRenderTarget->DrawLine(D2D1::Point2F(x + 0.5, y + 0.5),
+ D2D1::Point2F(x_ + 0.5 - xDelta, y_ + 0.5 - yDelta), pBrush);
+ } else {
+ // Line has a different slope so difficult to avoid last pixel
+ pRenderTarget->DrawLine(D2D1::Point2F(x + 0.5, y + 0.5),
+ D2D1::Point2F(x_ + 0.5, y_ + 0.5), pBrush);
+ }
+ x = x_;
+ y = y_;
+ }
+}
+
+void SurfaceD2D::Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back) {
+ if (pRenderTarget) {
+ ID2D1Factory *pFactory = 0;
+ pRenderTarget->GetFactory(&pFactory);
+ ID2D1PathGeometry *geometry=0;
+ HRESULT hr = pFactory->CreatePathGeometry(&geometry);
+ if (SUCCEEDED(hr)) {
+ ID2D1GeometrySink *sink = 0;
+ hr = geometry->Open(&sink);
+ if (SUCCEEDED(hr)) {
+ sink->BeginFigure(D2D1::Point2F(pts[0].x + 0.5f, pts[0].y + 0.5f), D2D1_FIGURE_BEGIN_FILLED);
+ for (size_t i=1; i<static_cast<size_t>(npts); i++) {
+ sink->AddLine(D2D1::Point2F(pts[i].x + 0.5f, pts[i].y + 0.5f));
+ }
+ sink->EndFigure(D2D1_FIGURE_END_CLOSED);
+ sink->Close();
+ sink->Release();
+
+ D2DPenColour(back);
+ pRenderTarget->FillGeometry(geometry,pBrush);
+ D2DPenColour(fore);
+ pRenderTarget->DrawGeometry(geometry,pBrush);
+ }
+
+ geometry->Release();
+ }
+ }
+}
+
+void SurfaceD2D::RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
+ if (pRenderTarget) {
+ D2DPenColour(back);
+ D2D1_RECT_F rectangle1 = D2D1::RectF(RoundFloat(rc.left) + 0.5, rc.top+0.5, RoundFloat(rc.right) - 0.5, rc.bottom-0.5);
+ D2DPenColour(back);
+ pRenderTarget->FillRectangle(&rectangle1, pBrush);
+ D2DPenColour(fore);
+ pRenderTarget->DrawRectangle(&rectangle1, pBrush);
+ }
+}
+
+void SurfaceD2D::FillRectangle(PRectangle rc, ColourAllocated back) {
+ if (pRenderTarget) {
+ D2DPenColour(back);
+ D2D1_RECT_F rectangle1 = D2D1::RectF(RoundFloat(rc.left), rc.top, RoundFloat(rc.right), rc.bottom);
+ pRenderTarget->FillRectangle(&rectangle1, pBrush);
+ }
+}
+
+void SurfaceD2D::FillRectangle(PRectangle rc, Surface &surfacePattern) {
+ SurfaceD2D &surfOther = static_cast<SurfaceD2D &>(surfacePattern);
+ surfOther.FlushDrawing();
+ ID2D1Bitmap *pBitmap = NULL;
+ ID2D1BitmapRenderTarget *pCompatibleRenderTarget = reinterpret_cast<ID2D1BitmapRenderTarget *>(
+ surfOther.pRenderTarget);
+ HRESULT hr = pCompatibleRenderTarget->GetBitmap(&pBitmap);
+ if (SUCCEEDED(hr)) {
+ ID2D1BitmapBrush *pBitmapBrush = NULL;
+ D2D1_BITMAP_BRUSH_PROPERTIES brushProperties =
+ D2D1::BitmapBrushProperties(D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_WRAP,
+ D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
+ // Create the bitmap brush.
+ hr = pRenderTarget->CreateBitmapBrush(pBitmap, brushProperties, &pBitmapBrush);
+ pBitmap->Release();
+ if (SUCCEEDED(hr)) {
+ pRenderTarget->FillRectangle(
+ D2D1::RectF(rc.left, rc.top, rc.right, rc.bottom),
+ pBitmapBrush);
+ pBitmapBrush->Release();
+ }
+ }
+}
+
+void SurfaceD2D::RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
+ if (pRenderTarget) {
+ D2D1_ROUNDED_RECT roundedRectFill = D2D1::RoundedRect(
+ D2D1::RectF(rc.left+1.0, rc.top+1.0, rc.right-1.0, rc.bottom-1.0),
+ 8, 8);
+ D2DPenColour(back);
+ pRenderTarget->FillRoundedRectangle(roundedRectFill, pBrush);
+
+ D2D1_ROUNDED_RECT roundedRect = D2D1::RoundedRect(
+ D2D1::RectF(rc.left + 0.5, rc.top+0.5, rc.right - 0.5, rc.bottom-0.5),
+ 8, 8);
+ D2DPenColour(fore);
+ pRenderTarget->DrawRoundedRectangle(roundedRect, pBrush);
+ }
+}
+
+void SurfaceD2D::AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill,
+ ColourAllocated outline, int alphaOutline, int /* flags*/ ) {
+ if (pRenderTarget) {
+ D2D1_ROUNDED_RECT roundedRectFill = D2D1::RoundedRect(
+ D2D1::RectF(rc.left+1.0, rc.top+1.0, rc.right-1.0, rc.bottom-1.0),
+ cornerSize, cornerSize);
+ D2DPenColour(fill, alphaFill);
+ pRenderTarget->FillRoundedRectangle(roundedRectFill, pBrush);
+
+ D2D1_ROUNDED_RECT roundedRect = D2D1::RoundedRect(
+ D2D1::RectF(rc.left + 0.5, rc.top+0.5, rc.right - 0.5, rc.bottom-0.5),
+ cornerSize, cornerSize);
+ D2DPenColour(outline, alphaOutline);
+ pRenderTarget->DrawRoundedRectangle(roundedRect, pBrush);
+ }
+}
+
+void SurfaceD2D::DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) {
+ if (pRenderTarget) {
+ if (rc.Width() > width)
+ rc.left += (rc.Width() - width) / 2;
+ rc.right = rc.left + width;
+ if (rc.Height() > height)
+ rc.top += (rc.Height() - height) / 2;
+ rc.bottom = rc.top + height;
+
+ std::vector<unsigned char> image(height * width * 4);
+ for (int y=0; y<height; y++) {
+ for (int x=0; x<width; x++) {
+ unsigned char *pixel = &image[0] + (y*width+x) * 4;
+ unsigned char alpha = pixelsImage[3];
+ // Input is RGBA, output is BGRA with premultiplied alpha
+ pixel[2] = (*pixelsImage++) * alpha / 255;
+ pixel[1] = (*pixelsImage++) * alpha / 255;
+ pixel[0] = (*pixelsImage++) * alpha / 255;
+ pixel[3] = *pixelsImage++;
+ }
+ }
+
+ ID2D1Bitmap *bitmap = 0;
+ D2D1_SIZE_U size = D2D1::SizeU(width, height);
+ D2D1_BITMAP_PROPERTIES props = {{DXGI_FORMAT_B8G8R8A8_UNORM,
+ D2D1_ALPHA_MODE_PREMULTIPLIED}, 72.0, 72.0};
+ HRESULT hr = pRenderTarget->CreateBitmap(size, &image[0],
+ width * 4, &props, &bitmap);
+ if (SUCCEEDED(hr)) {
+ D2D1_RECT_F rcDestination = {rc.left, rc.top, rc.right, rc.bottom};
+ pRenderTarget->DrawBitmap(bitmap, rcDestination);
+ }
+ bitmap->Release();
+ }
+}
+
+void SurfaceD2D::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
+ if (pRenderTarget) {
+ FLOAT radius = rc.Width() / 2.0f - 1.0f;
+ D2D1_ELLIPSE ellipse = D2D1::Ellipse(
+ D2D1::Point2F((rc.left + rc.right) / 2.0f, (rc.top + rc.bottom) / 2.0f),
+ radius,radius);
+
+ PenColour(back);
+ pRenderTarget->FillEllipse(ellipse, pBrush);
+ PenColour(fore);
+ pRenderTarget->DrawEllipse(ellipse, pBrush);
+ }
+}
+
+void SurfaceD2D::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
+ SurfaceD2D &surfOther = static_cast<SurfaceD2D &>(surfaceSource);
+ surfOther.FlushDrawing();
+ ID2D1BitmapRenderTarget *pCompatibleRenderTarget = reinterpret_cast<ID2D1BitmapRenderTarget *>(
+ surfOther.pRenderTarget);
+ ID2D1Bitmap *pBitmap = NULL;
+ HRESULT hr = pCompatibleRenderTarget->GetBitmap(&pBitmap);
+ if (SUCCEEDED(hr)) {
+ D2D1_RECT_F rcDestination = {rc.left, rc.top, rc.right, rc.bottom};
+ D2D1_RECT_F rcSource = {from.x, from.y, from.x + rc.Width(), from.y + rc.Height()};
+ pRenderTarget->DrawBitmap(pBitmap, rcDestination, 1.0f,
+ D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, rcSource);
+ pRenderTarget->Flush();
+ pBitmap->Release();
+ }
+}
+
+void SurfaceD2D::DrawTextCommon(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, UINT) {
+ SetFont(font_);
+ RECT rcw = RectFromPRectangle(rc);
+
+ // Use Unicode calls
+ const TextWide tbuf(s, len, unicodeMode, codePage);
+ if (pRenderTarget && pTextFormat && pBrush) {
+
+ // Explicitly creating a text layout appears a little faster
+ IDWriteTextLayout *pTextLayout;
+ HRESULT hr = pIDWriteFactory->CreateTextLayout(tbuf.buffer, tbuf.tlen, pTextFormat,
+ rc.Width(), rc.Height(), &pTextLayout);
+ if (SUCCEEDED(hr)) {
+ D2D1_POINT_2F origin = {rc.left, ybase-yAscent};
+ pRenderTarget->DrawTextLayout(origin, pTextLayout, pBrush, D2D1_DRAW_TEXT_OPTIONS_NONE);
+ } else {
+ D2D1_RECT_F layoutRect = D2D1::RectF(
+ static_cast<FLOAT>(rcw.left) / dpiScaleX,
+ static_cast<FLOAT>(ybase-yAscent) / dpiScaleY,
+ static_cast<FLOAT>(rcw.right + 1) / dpiScaleX,
+ static_cast<FLOAT>(rcw.bottom) / dpiScaleY);
+ pRenderTarget->DrawText(tbuf.buffer, tbuf.tlen, pTextFormat, layoutRect, pBrush, D2D1_DRAW_TEXT_OPTIONS_NONE);
+ }
+ }
+}
+
+void SurfaceD2D::DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len,
+ ColourAllocated fore, ColourAllocated back) {
+ if (pRenderTarget) {
+ FillRectangle(rc, back);
+ D2DPenColour(fore);
+ DrawTextCommon(rc, font_, ybase, s, len, ETO_OPAQUE);
+ }
+}
+
+void SurfaceD2D::DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len,
+ ColourAllocated fore, ColourAllocated back) {
+ if (pRenderTarget) {
+ FillRectangle(rc, back);
+ D2DPenColour(fore);
+ DrawTextCommon(rc, font_, ybase, s, len, ETO_OPAQUE | ETO_CLIPPED);
+ }
+}
+
+void SurfaceD2D::DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len,
+ ColourAllocated fore) {
+ // Avoid drawing spaces in transparent mode
+ for (int i=0;i<len;i++) {
+ if (s[i] != ' ') {
+ if (pRenderTarget) {
+ D2DPenColour(fore);
+ DrawTextCommon(rc, font_, ybase, s, len, 0);
+ }
+ return;
+ }
+ }
+}
+
+XYPOSITION SurfaceD2D::WidthText(Font &font_, const char *s, int len) {
+ FLOAT width = 1.0;
+ SetFont(font_);
+ const TextWide tbuf(s, len, unicodeMode, codePage);
+ if (pIDWriteFactory && pTextFormat) {
+ // Create a layout
+ IDWriteTextLayout *pTextLayout = 0;
+ HRESULT hr = pIDWriteFactory->CreateTextLayout(tbuf.buffer, tbuf.tlen, pTextFormat, 1000.0, 1000.0, &pTextLayout);
+ if (SUCCEEDED(hr)) {
+ DWRITE_TEXT_METRICS textMetrics;
+ pTextLayout->GetMetrics(&textMetrics);
+ width = textMetrics.widthIncludingTrailingWhitespace;
+ pTextLayout->Release();
+ }
+ }
+ return int(width + 0.5);
+}
+
+void SurfaceD2D::MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions) {
+ SetFont(font_);
+ int fit = 0;
+ const TextWide tbuf(s, len, unicodeMode, codePage);
+ TextPositions poses(tbuf.tlen);
+ fit = tbuf.tlen;
+ const int clusters = 1000;
+ DWRITE_CLUSTER_METRICS clusterMetrics[clusters];
+ UINT32 count = 0;
+ if (pIDWriteFactory && pTextFormat) {
+ SetFont(font_);
+ // Create a layout
+ IDWriteTextLayout *pTextLayout = 0;
+ HRESULT hr = pIDWriteFactory->CreateTextLayout(tbuf.buffer, tbuf.tlen, pTextFormat, 10000.0, 1000.0, &pTextLayout);
+ if (!SUCCEEDED(hr))
+ return;
+ // For now, assuming WCHAR == cluster
+ pTextLayout->GetClusterMetrics(clusterMetrics, clusters, &count);
+ FLOAT position = 0.0f;
+ size_t ti=0;
+ for (size_t ci=0;ci<count;ci++) {
+ position += clusterMetrics[ci].width;
+ for (size_t inCluster=0; inCluster<clusterMetrics[ci].length; inCluster++) {
+ //poses.buffer[ti++] = int(position + 0.5);
+ poses.buffer[ti++] = position;
+ }
+ }
+ PLATFORM_ASSERT(ti == static_cast<size_t>(tbuf.tlen));
+ pTextLayout->Release();
+ }
+ if (unicodeMode) {
+ // Map the widths given for UTF-16 characters back onto the UTF-8 input string
+ int ui=0;
+ const unsigned char *us = reinterpret_cast<const unsigned char *>(s);
+ int i=0;
+ while (ui<fit) {
+ unsigned char uch = us[i];
+ unsigned int lenChar = 1;
+ if (uch >= (0x80 + 0x40 + 0x20 + 0x10)) {
+ lenChar = 4;
+ ui++;
+ } else if (uch >= (0x80 + 0x40 + 0x20)) {
+ lenChar = 3;
+ } else if (uch >= (0x80)) {
+ lenChar = 2;
+ }
+ for (unsigned int bytePos=0; (bytePos<lenChar) && (i<len); bytePos++) {
+ positions[i++] = poses.buffer[ui];
+ }
+ ui++;
+ }
+ int lastPos = 0;
+ if (i > 0)
+ lastPos = positions[i-1];
+ while (i<len) {
+ positions[i++] = lastPos;
+ }
+ } else if (codePage == 0) {
+
+ // One character per position
+ PLATFORM_ASSERT(len == tbuf.tlen);
+ for (size_t kk=0;kk<static_cast<size_t>(len);kk++) {
+ positions[kk] = poses.buffer[kk];
+ }
+
+ } else {
+
+ // May be more than one byte per position
+ int ui = 0;
+ for (int i=0;i<len;) {
+ if (::IsDBCSLeadByteEx(codePage, s[i])) {
+ positions[i] = poses.buffer[ui];
+ positions[i+1] = poses.buffer[ui];
+ i += 2;
+ } else {
+ positions[i] = poses.buffer[ui];
+ i++;
+ }
+
+ ui++;
+ }
+ }
+}
+
+XYPOSITION SurfaceD2D::WidthChar(Font &font_, char ch) {
+ FLOAT width = 1.0;
+ SetFont(font_);
+ if (pIDWriteFactory && pTextFormat) {
+ // Create a layout
+ IDWriteTextLayout *pTextLayout = 0;
+ const WCHAR wch = ch;
+ HRESULT hr = pIDWriteFactory->CreateTextLayout(&wch, 1, pTextFormat, 1000.0, 1000.0, &pTextLayout);
+ if (SUCCEEDED(hr)) {
+ DWRITE_TEXT_METRICS textMetrics;
+ pTextLayout->GetMetrics(&textMetrics);
+ width = textMetrics.widthIncludingTrailingWhitespace;
+ pTextLayout->Release();
+ }
+ }
+ return int(width + 0.5);
+}
+
+XYPOSITION SurfaceD2D::Ascent(Font &font_) {
+ SetFont(font_);
+ return ceil(yAscent);
+}
+
+XYPOSITION SurfaceD2D::Descent(Font &font_) {
+ SetFont(font_);
+ return ceil(yDescent);
+}
+
+XYPOSITION SurfaceD2D::InternalLeading(Font &) {
+ return 0;
+}
+
+XYPOSITION SurfaceD2D::ExternalLeading(Font &) {
+ return 1;
+}
+
+XYPOSITION SurfaceD2D::Height(Font &font_) {
+ return Ascent(font_) + Descent(font_);
+}
+
+XYPOSITION SurfaceD2D::AverageCharWidth(Font &font_) {
+ FLOAT width = 1.0;
+ SetFont(font_);
+ if (pIDWriteFactory && pTextFormat) {
+ // Create a layout
+ IDWriteTextLayout *pTextLayout = 0;
+ const WCHAR wszAllAlpha[] = L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ HRESULT hr = pIDWriteFactory->CreateTextLayout(wszAllAlpha, wcslen(wszAllAlpha), pTextFormat, 1000.0, 1000.0, &pTextLayout);
+ if (SUCCEEDED(hr)) {
+ DWRITE_TEXT_METRICS textMetrics;
+ pTextLayout->GetMetrics(&textMetrics);
+ width = textMetrics.width / wcslen(wszAllAlpha);
+ pTextLayout->Release();
+ }
+ }
+ return int(width + 0.5);
+}
+
+int SurfaceD2D::SetPalette(Palette *, bool) {
+ return 0;
+}
+
+void SurfaceD2D::SetClip(PRectangle rc) {
+ if (pRenderTarget) {
+ D2D1_RECT_F rcClip = {rc.left, rc.top, rc.right, rc.bottom};
+ pRenderTarget->PushAxisAlignedClip(rcClip, D2D1_ANTIALIAS_MODE_ALIASED);
+ clipsActive++;
+ }
+}
+
+void SurfaceD2D::FlushCachedState() {
+}
+
+void SurfaceD2D::SetUnicodeMode(bool unicodeMode_) {
+ unicodeMode=unicodeMode_;
+}
+
+void SurfaceD2D::SetDBCSMode(int codePage_) {
+ // No action on window as automatically handled by system.
+ codePage = codePage_;
+}
+
+Surface *Surface::Allocate(int technology) {
+ if (technology == SCWIN_TECH_GDI)
+ return new SurfaceGDI;
+ else
+ return new SurfaceD2D;
}
Window::~Window() {
@@ -1092,8 +1902,7 @@ void Window::SetPositionRelative(PRectangle rc, Window w) {
#ifdef MONITOR_DEFAULTTONULL
// We're using the stub functionality of MultiMon.h to decay gracefully on machines
// (ie, pre Win2000, Win95) that do not support the newer functions.
- RECT rcMonitor;
- memcpy(&rcMonitor, &rc, sizeof(rcMonitor)); // RECT and Rectangle are the same really.
+ RECT rcMonitor = {rc.left, rc.top, rc.right, rc.bottom};
MONITORINFO mi = {0};
mi.cbSize = sizeof(mi);
@@ -1365,6 +2174,7 @@ ListBox::~ListBox() {
class ListBoxX : public ListBox {
int lineHeight;
FontID fontCopy;
+ int technology;
RGBAImageSet images;
LineToItem lti;
HWND lb;
@@ -1407,7 +2217,7 @@ class ListBoxX : public ListBox {
static const Point ImageInset; // Padding around image
public:
- ListBoxX() : lineHeight(10), fontCopy(0), lb(0), unicodeMode(false),
+ ListBoxX() : lineHeight(10), fontCopy(0), technology(0), lb(0), unicodeMode(false),
desiredVisibleRows(5), maxItemCharacters(0), aveCharWidth(8),
parent(NULL), ctrlID(0), doubleClickAction(NULL), doubleClickActionData(NULL),
widestItem(NULL), maxCharWidth(1), resizeHit(0), wheelDelta(0) {
@@ -1419,7 +2229,7 @@ public:
}
}
virtual void SetFont(Font &font);
- virtual void Create(Window &parent, int ctrlID, Point location_, int lineHeight_, bool unicodeMode_);
+ virtual void Create(Window &parent, int ctrlID, Point location_, int lineHeight_, bool unicodeMode_, int technology_);
virtual void SetAverageCharWidth(int width);
virtual void SetVisibleRows(int rows);
virtual int GetVisibleRows() const;
@@ -1454,12 +2264,13 @@ ListBox *ListBox::Allocate() {
return lb;
}
-void ListBoxX::Create(Window &parent_, int ctrlID_, Point location_, int lineHeight_, bool unicodeMode_) {
+void ListBoxX::Create(Window &parent_, int ctrlID_, Point location_, int lineHeight_, bool unicodeMode_, int technology_) {
parent = &parent_;
ctrlID = ctrlID_;
location = location_;
lineHeight = lineHeight_;
unicodeMode = unicodeMode_;
+ technology = technology_;
HWND hwndParent = reinterpret_cast<HWND>(parent->GetID());
HINSTANCE hinstanceParent = GetWindowInstance(hwndParent);
// Window created as popup so not clipped within parent client area
@@ -1471,17 +2282,19 @@ void ListBoxX::Create(Window &parent_, int ctrlID_, Point location_, int lineHei
hinstanceParent,
this);
- ::MapWindowPoints(hwndParent, NULL, reinterpret_cast<POINT*>(&location), 1);
+ POINT locationw = {location.x, location.y};
+ ::MapWindowPoints(hwndParent, NULL, &locationw, 1);
+ location = Point(locationw.x, locationw.y);
}
void ListBoxX::SetFont(Font &font) {
- LOGFONT lf;
- if (0 != ::GetObject(font.GetID(), sizeof(lf), &lf)) {
+ if (font.GetID()) {
if (fontCopy) {
::DeleteObject(fontCopy);
fontCopy = 0;
}
- fontCopy = ::CreateFontIndirect(&lf);
+ FormatAndMetrics *pfm = reinterpret_cast<FormatAndMetrics *>(font.GetID());
+ fontCopy = pfm->HFont();
::SendMessage(lb, WM_SETFONT, reinterpret_cast<WPARAM>(fontCopy), 0);
}
}
@@ -1650,16 +2463,46 @@ void ListBoxX::Draw(DRAWITEMSTRUCT *pDrawItem) {
// Draw the image, if any
RGBAImage *pimage = images.Get(pixId);
if (pimage) {
- Surface *surfaceItem = Surface::Allocate();
+ Surface *surfaceItem = Surface::Allocate(technology);
if (surfaceItem) {
- surfaceItem->Init(pDrawItem->hDC, pDrawItem->hwndItem);
- int left = pDrawItem->rcItem.left + ItemInset.x + ImageInset.x;
- PRectangle rcImage(left, pDrawItem->rcItem.top,
- left + images.GetWidth(), pDrawItem->rcItem.bottom);
- surfaceItem->DrawRGBAImage(rcImage,
- pimage->GetWidth(), pimage->GetHeight(), pimage->Pixels());
- delete surfaceItem;
- ::SetTextAlign(pDrawItem->hDC, TA_TOP);
+ if (technology == SCWIN_TECH_GDI) {
+ surfaceItem->Init(pDrawItem->hDC, pDrawItem->hwndItem);
+ int left = pDrawItem->rcItem.left + ItemInset.x + ImageInset.x;
+ PRectangle rcImage(left, pDrawItem->rcItem.top,
+ left + images.GetWidth(), pDrawItem->rcItem.bottom);
+ surfaceItem->DrawRGBAImage(rcImage,
+ pimage->GetWidth(), pimage->GetHeight(), pimage->Pixels());
+ delete surfaceItem;
+ ::SetTextAlign(pDrawItem->hDC, TA_TOP);
+ } else {
+ D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(
+ D2D1_RENDER_TARGET_TYPE_DEFAULT,
+ D2D1::PixelFormat(
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ D2D1_ALPHA_MODE_IGNORE),
+ 0,
+ 0,
+ D2D1_RENDER_TARGET_USAGE_NONE,
+ D2D1_FEATURE_LEVEL_DEFAULT
+ );
+ ID2D1DCRenderTarget *pDCRT = 0;
+ HRESULT hr = pD2DFactory->CreateDCRenderTarget(&props, &pDCRT);
+ RECT rcWindow;
+ GetClientRect(pDrawItem->hwndItem, &rcWindow);
+ hr = pDCRT->BindDC(pDrawItem->hDC, &rcWindow);
+ if (SUCCEEDED(hr)) {
+ surfaceItem->Init(pDCRT, pDrawItem->hwndItem);
+ pDCRT->BeginDraw();
+ int left = pDrawItem->rcItem.left + ItemInset.x + ImageInset.x;
+ PRectangle rcImage(left, pDrawItem->rcItem.top,
+ left + images.GetWidth(), pDrawItem->rcItem.bottom);
+ surfaceItem->DrawRGBAImage(rcImage,
+ pimage->GetWidth(), pimage->GetHeight(), pimage->Pixels());
+ delete surfaceItem;
+ pDCRT->EndDraw();
+ pDCRT->Release();
+ }
+ }
}
}
}
@@ -1726,7 +2569,9 @@ void ListBoxX::SetList(const char *list, char separator, char typesep) {
}
void ListBoxX::AdjustWindowRect(PRectangle *rc) const {
- ::AdjustWindowRectEx(reinterpret_cast<RECT*>(rc), WS_THICKFRAME, false, WS_EX_WINDOWEDGE);
+ RECT rcw = {rc->left, rc->top, rc->right, rc->bottom };
+ ::AdjustWindowRectEx(&rcw, WS_THICKFRAME, false, WS_EX_WINDOWEDGE);
+ *rc = PRectangle(rcw.left, rcw.top, rcw.right, rcw.bottom);
}
int ListBoxX::ItemHeight() const {
@@ -1767,8 +2612,9 @@ void ListBoxX::SetRedraw(bool on) {
void ListBoxX::ResizeToCursor() {
PRectangle rc = GetPosition();
- Point pt;
- ::GetCursorPos(reinterpret_cast<POINT*>(&pt));
+ POINT ptw;
+ ::GetCursorPos(&ptw);
+ Point pt(ptw.x, ptw.y);
pt.x += dragOffset.x;
pt.y += dragOffset.y;
diff --git a/win32/PlatWin.h b/win32/PlatWin.h
new file mode 100644
index 000000000..dc3f8e432
--- /dev/null
+++ b/win32/PlatWin.h
@@ -0,0 +1,13 @@
+// Scintilla source code edit control
+/** @file PlatWin.h
+ ** Implementation of platform facilities on Windows.
+ **/
+// Copyright 1998-2011 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+extern bool IsNT();
+extern void Platform_Initialise(void *hInstance);
+extern void Platform_Finalise();
+extern bool LoadD2D();
+extern ID2D1Factory *pD2DFactory;
+extern IDWriteFactory *pIDWriteFactory;
diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx
index d1f450479..a3c141aff 100644
--- a/win32/ScintillaWin.cxx
+++ b/win32/ScintillaWin.cxx
@@ -24,6 +24,9 @@
#include <richedit.h>
#include <windowsx.h>
+#include <d2d1.h>
+#include <dwrite.h>
+
#include "Platform.h"
#include "ILexer.h"
@@ -54,6 +57,7 @@
#include "Editor.h"
#include "ScintillaBase.h"
#include "UniConversion.h"
+#include "PlatWin.h"
#ifdef SCI_LEXER
#include "ExternalLexer.h"
@@ -87,11 +91,6 @@
#define SC_WIN_IDLE 5001
-// Functions imported from PlatWin
-extern bool IsNT();
-extern void Platform_Initialise(void *hInstance);
-extern void Platform_Finalise();
-
typedef BOOL (WINAPI *TrackMouseEventSig)(LPTRACKMOUSEEVENT);
// GCC has trouble with the standard COM ABI so do it the old C way with explicit vtables.
@@ -197,6 +196,8 @@ class ScintillaWin :
static HINSTANCE hInstance;
+ ID2D1HwndRenderTarget *pRenderTarget;
+
ScintillaWin(HWND hwnd);
ScintillaWin(const ScintillaWin &);
virtual ~ScintillaWin();
@@ -204,6 +205,8 @@ class ScintillaWin :
virtual void Initialise();
virtual void Finalise();
+ void EnsureRenderTarget();
+ void DropRenderTarget();
HWND MainHWND();
static sptr_t DirectFunction(
@@ -350,6 +353,8 @@ ScintillaWin::ScintillaWin(HWND hwnd) {
sysCaretWidth = 0;
sysCaretHeight = 0;
+ pRenderTarget = 0;
+
keysAlwaysUnicode = false;
caret.period = ::GetCaretBlinkTime();
@@ -384,12 +389,46 @@ void ScintillaWin::Finalise() {
ScintillaBase::Finalise();
SetTicking(false);
SetIdle(false);
+ DropRenderTarget();
::RevokeDragDrop(MainHWND());
if (SUCCEEDED(hrOle)) {
::OleUninitialize();
}
}
+void ScintillaWin::EnsureRenderTarget() {
+ if (pD2DFactory && !pRenderTarget) {
+ RECT rc;
+ HWND hw = MainHWND();
+ GetClientRect(hw, &rc);
+
+ D2D1_SIZE_U size = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top);
+
+ // Create a Direct2D render target.
+#if 1
+ pD2DFactory->CreateHwndRenderTarget(
+ D2D1::RenderTargetProperties(),
+ D2D1::HwndRenderTargetProperties(hw, size),
+ &pRenderTarget);
+#else
+ pD2DFactory->CreateHwndRenderTarget(
+ D2D1::RenderTargetProperties(
+ D2D1_RENDER_TARGET_TYPE_DEFAULT ,
+ D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED),
+ 96.0f, 96.0f, D2D1_RENDER_TARGET_USAGE_NONE, D2D1_FEATURE_LEVEL_DEFAULT),
+ D2D1::HwndRenderTargetProperties(hw, size),
+ &pRenderTarget);
+#endif
+ }
+}
+
+void ScintillaWin::DropRenderTarget() {
+ if (pRenderTarget) {
+ pRenderTarget->Release();
+ pRenderTarget = 0;
+ }
+}
+
HWND ScintillaWin::MainHWND() {
return reinterpret_cast<HWND>(wMain.GetID());
}
@@ -505,18 +544,35 @@ LRESULT ScintillaWin::WndPaint(uptr_t wParam) {
pps = &ps;
::BeginPaint(MainHWND(), pps);
}
- AutoSurface surfaceWindow(pps->hdc, this);
- if (surfaceWindow) {
- rcPaint = PRectangle(pps->rcPaint.left, pps->rcPaint.top, pps->rcPaint.right, pps->rcPaint.bottom);
- PRectangle rcClient = GetClientRectangle();
- paintingAllText = rcPaint.Contains(rcClient);
- if (paintingAllText) {
- //Platform::DebugPrintf("Performing full text paint\n");
- } else {
- //Platform::DebugPrintf("Performing partial paint %d .. %d\n", rcPaint.top, rcPaint.bottom);
+ if (technology == SC_TECHNOLOGY_DEFAULT) {
+ AutoSurface surfaceWindow(pps->hdc, this);
+ if (surfaceWindow) {
+ rcPaint = PRectangle(pps->rcPaint.left, pps->rcPaint.top, pps->rcPaint.right, pps->rcPaint.bottom);
+ PRectangle rcClient = GetClientRectangle();
+ paintingAllText = rcPaint.Contains(rcClient);
+ Paint(surfaceWindow, rcPaint);
+ surfaceWindow->Release();
+ }
+ } else {
+ EnsureRenderTarget();
+ AutoSurface surfaceWindow(pRenderTarget, this);
+ if (surfaceWindow) {
+ pRenderTarget->BeginDraw();
+ rcPaint = PRectangle(pps->rcPaint.left, pps->rcPaint.top, pps->rcPaint.right, pps->rcPaint.bottom);
+ PRectangle rcClient = GetClientRectangle();
+ paintingAllText = rcPaint.Contains(rcClient);
+ if (paintingAllText) {
+ //Platform::DebugPrintf("Performing full text paint\n");
+ } else {
+ //Platform::DebugPrintf("Performing partial paint %d .. %d\n", rcPaint.top, rcPaint.bottom);
+ }
+ Paint(surfaceWindow, rcPaint);
+ surfaceWindow->Release();
+ HRESULT hr = pRenderTarget->EndDraw();
+ if (hr == D2DERR_RECREATE_TARGET) {
+ DropRenderTarget();
+ }
}
- Paint(surfaceWindow, rcPaint);
- surfaceWindow->Release();
}
if (hRgnUpdate) {
::DeleteRgn(hRgnUpdate);
@@ -674,6 +730,7 @@ sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam
break;
case WM_SIZE: {
+ DropRenderTarget();
//Platform::DebugPrintf("Scintilla WM_SIZE %d %d\n", LoWord(lParam), HiWord(lParam));
ChangeSize();
}
@@ -1085,6 +1142,22 @@ sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam
case SCI_GETKEYSUNICODE:
return keysAlwaysUnicode;
+
+ case SCI_SETTECHNOLOGY:
+ if ((wParam == SC_TECHNOLOGY_DEFAULT) || (wParam == SC_TECHNOLOGY_DIRECTWRITE)) {
+ if (technology != static_cast<int>(wParam)) {
+ if (static_cast<int>(wParam) == SC_TECHNOLOGY_DIRECTWRITE) {
+ if (!LoadD2D())
+ // Failed to load Direct2D or DirectWrite so no effect
+ return 0;
+ }
+ technology = wParam;
+ // Invalidate all cached information including layout.
+ DropGraphics(true);
+ InvalidateStyleRedraw();
+ }
+ }
+ break;
#ifdef SCI_LEXER
case SCI_LOADLEXERLIBRARY:
@@ -1196,11 +1269,12 @@ bool ScintillaWin::PaintContains(PRectangle rc) {
return contains;
}
-void ScintillaWin::ScrollText(int linesToMove) {
+void ScintillaWin::ScrollText(int /* linesToMove */) {
//Platform::DebugPrintf("ScintillaWin::ScrollText %d\n", linesToMove);
- ::ScrollWindow(MainHWND(), 0,
- vs.lineHeight * linesToMove, 0, 0);
- ::UpdateWindow(MainHWND());
+ //::ScrollWindow(MainHWND(), 0,
+ // vs.lineHeight * linesToMove, 0, 0);
+ //::UpdateWindow(MainHWND());
+ Redraw();
}
void ScintillaWin::UpdateSystemCaret() {
@@ -2085,9 +2159,9 @@ void ScintillaWin::ImeStartComposition() {
// The logfont for the IME is recreated here.
int styleHere = (pdoc->StyleAt(sel.MainCaret())) & 31;
LOGFONTA lf = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ""};
- int sizeZoomed = vs.styles[styleHere].size + vs.zoomLevel;
- if (sizeZoomed <= 2) // Hangs if sizeZoomed <= 1
- sizeZoomed = 2;
+ int sizeZoomed = vs.styles[styleHere].size + vs.zoomLevel * SC_FONT_SIZE_MULTIPLIER;
+ if (sizeZoomed <= 2 * SC_FONT_SIZE_MULTIPLIER) // Hangs if sizeZoomed <= 1
+ sizeZoomed = 2 * SC_FONT_SIZE_MULTIPLIER;
AutoSurface surface(this);
int deviceHeight = sizeZoomed;
if (surface) {
@@ -2095,7 +2169,7 @@ void ScintillaWin::ImeStartComposition() {
}
// The negative is to allow for leading
lf.lfHeight = -(abs(deviceHeight));
- lf.lfWeight = vs.styles[styleHere].bold ? FW_BOLD : FW_NORMAL;
+ lf.lfWeight = vs.styles[styleHere].weight;
lf.lfItalic = static_cast<BYTE>(vs.styles[styleHere].italic ? 1 : 0);
lf.lfCharSet = DEFAULT_CHARSET;
lf.lfFaceName[0] = '\0';
@@ -2290,7 +2364,9 @@ void ScintillaWin::HorizontalScrollMessage(WPARAM wParam) {
HorizontalScrollTo(xPos);
}
-void ScintillaWin::RealizeWindowPalette(bool inBackGround) {
+void ScintillaWin::RealizeWindowPalette(bool) {
+ // No support for palette with D2D
+/*
RefreshStyleData();
HDC hdc = ::GetDC(MainHWND());
// Select a stock font to prevent warnings from BoundsChecker
@@ -2303,6 +2379,7 @@ void ScintillaWin::RealizeWindowPalette(bool inBackGround) {
surfaceWindow->Release();
}
::ReleaseDC(MainHWND(), hdc);
+*/
}
/**
@@ -2310,9 +2387,13 @@ void ScintillaWin::RealizeWindowPalette(bool inBackGround) {
* This paint will not be abandoned.
*/
void ScintillaWin::FullPaint() {
- HDC hdc = ::GetDC(MainHWND());
- FullPaintDC(hdc);
- ::ReleaseDC(MainHWND(), hdc);
+ if (technology == SC_TECHNOLOGY_DEFAULT) {
+ HDC hdc = ::GetDC(MainHWND());
+ FullPaintDC(hdc);
+ ::ReleaseDC(MainHWND(), hdc);
+ } else {
+ FullPaintDC(0);
+ }
}
/**
@@ -2323,10 +2404,24 @@ void ScintillaWin::FullPaintDC(HDC hdc) {
paintState = painting;
rcPaint = GetClientRectangle();
paintingAllText = true;
- AutoSurface surfaceWindow(hdc, this);
- if (surfaceWindow) {
- Paint(surfaceWindow, rcPaint);
- surfaceWindow->Release();
+ if (technology == SC_TECHNOLOGY_DEFAULT) {
+ AutoSurface surfaceWindow(hdc, this);
+ if (surfaceWindow) {
+ Paint(surfaceWindow, rcPaint);
+ surfaceWindow->Release();
+ }
+ } else {
+ EnsureRenderTarget();
+ AutoSurface surfaceWindow(pRenderTarget, this);
+ if (surfaceWindow) {
+ pRenderTarget->BeginDraw();
+ Paint(surfaceWindow, rcPaint);
+ surfaceWindow->Release();
+ HRESULT hr = pRenderTarget->EndDraw();
+ if (hr == D2DERR_RECREATE_TARGET) {
+ DropRenderTarget();
+ }
+ }
}
paintState = notPainting;
}
@@ -2698,14 +2793,31 @@ sptr_t PASCAL ScintillaWin::CTWndProc(
} else if (iMessage == WM_PAINT) {
PAINTSTRUCT ps;
::BeginPaint(hWnd, &ps);
- Surface *surfaceWindow = Surface::Allocate();
+ Surface *surfaceWindow = Surface::Allocate(sciThis->technology);
if (surfaceWindow) {
- surfaceWindow->Init(ps.hdc, hWnd);
+ ID2D1HwndRenderTarget *pCTRenderTarget = 0;
+ RECT rc;
+ GetClientRect(hWnd, &rc);
+ // Create a Direct2D render target.
+ if (sciThis->technology == SC_TECHNOLOGY_DEFAULT) {
+ surfaceWindow->Init(ps.hdc, hWnd);
+ } else {
+ pD2DFactory->CreateHwndRenderTarget(
+ D2D1::RenderTargetProperties(),
+ D2D1::HwndRenderTargetProperties(hWnd, D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top)),
+ &pCTRenderTarget);
+ surfaceWindow->Init(pCTRenderTarget, hWnd);
+ pCTRenderTarget->BeginDraw();
+ }
surfaceWindow->SetUnicodeMode(SC_CP_UTF8 == sciThis->ct.codePage);
surfaceWindow->SetDBCSMode(sciThis->ct.codePage);
sciThis->ct.PaintCT(surfaceWindow);
+ if (pCTRenderTarget)
+ pCTRenderTarget->EndDraw();
surfaceWindow->Release();
delete surfaceWindow;
+ if (pCTRenderTarget)
+ pCTRenderTarget->Release();
}
::EndPaint(hWnd, &ps);
return 0;