aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornyamatongwe <unknown>2011-09-24 22:10:59 +1000
committernyamatongwe <unknown>2011-09-24 22:10:59 +1000
commit77d25bd25490fe412a213581e371c7c26eb23f7d (patch)
treee91d99a2328e82067e9781599cb2e058a8400fa3
parentdf08d45447c2b2386629d13004f4ab6006cab2d8 (diff)
parent33e27dc25f933a92566d91a667ba4ee732ba6cfa (diff)
downloadscintilla-mirror-77d25bd25490fe412a213581e371c7c26eb23f7d.tar.gz
Merged fractional text positioning branch.
-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.html39
-rw-r--r--gtk/PlatGTK.cxx156
-rw-r--r--gtk/ScintillaGTK.cxx12
-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, 1593 insertions, 452 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 ca1a29bb4..d917913aa 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"
@@ -2453,10 +2463,22 @@ struct Sci_TextToFind {
<code>fontName</code> is a zero terminated string holding the name of a font. Under Windows,
only the first 32 characters of the name are used and the name is not case sensitive. For
internal caching, Scintilla tracks fonts by name and does care about the casing of font names,
- so please be consistent. On GTK+ 2.x, either GDK or Pango can be used to display text.
- 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>
+ so please be consistent. On GTK+, Pango is used to display text.</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 +3005,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 +3070,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 2a485b3eb..1e36989ad 100644
--- a/gtk/PlatGTK.cxx
+++ b/gtk/PlatGTK.cxx
@@ -79,7 +79,7 @@ enum encodingType { singleByte, UTF8, dbcs};
struct LOGFONT {
int size;
- bool bold;
+ int weight;
bool italic;
int characterSet;
char faceName[300];
@@ -292,10 +292,10 @@ void Palette::Allocate(Window &w) {
#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);
@@ -306,13 +306,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 {
@@ -320,35 +320,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() {
@@ -357,19 +356,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;
@@ -399,17 +398,15 @@ void FontCached::ReleaseId(FontID fid_) {
FontMutexUnlock();
}
-FontID FontCached::CreateNewFont(const char *fontName, int characterSet,
- int size, bool bold, bool italic) {
- if (*fontName == '!')
- fontName++;
+FontID FontCached::CreateNewFont(const FontParameters &fp) {
PangoFontDescription *pfd = pango_font_description_new();
if (pfd) {
- pango_font_description_set_family(pfd, fontName);
- 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[0] == '!') ? fp.faceName+1 : fp.faceName);
+ 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);
}
return new FontHandle();
@@ -419,10 +416,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() {
@@ -476,19 +472,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);
@@ -964,11 +960,11 @@ static size_t UTF8CharLength(const char *s) {
}
}
-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);
if (context) {
- int xText = rc.left;
+ XYPOSITION xText = rc.left;
if (PFont(font_)->pfd) {
char *utfForm = 0;
if (et == UTF8) {
@@ -997,20 +993,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++) {
@@ -1027,9 +1023,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) {
@@ -1044,18 +1040,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) {
@@ -1158,7 +1154,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;
@@ -1183,7 +1179,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);
}
return 1;
} else {
@@ -1191,7 +1187,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);
@@ -1204,7 +1200,7 @@ int SurfaceImpl::WidthChar(Font &font_, char ch) {
// Ascent and descent determined by Pango font metrics.
-int SurfaceImpl::Ascent(Font &font_) {
+XYPOSITION SurfaceImpl::Ascent(Font &font_) {
if (!(font_.GetID()))
return 1;
FontMutexLock();
@@ -1213,7 +1209,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;
}
@@ -1224,32 +1220,32 @@ int SurfaceImpl::Ascent(Font &font_) {
return ascent;
}
-int SurfaceImpl::Descent(Font &font_) {
+XYPOSITION SurfaceImpl::Descent(Font &font_) {
if (!(font_.GetID()))
return 1;
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;
}
return 0;
}
-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');
}
@@ -1275,8 +1271,8 @@ void SurfaceImpl::SetDBCSMode(int codePage) {
et = dbcs;
}
-Surface *Surface::Allocate() {
- return new SurfaceImpl;
+Surface *Surface::Allocate(int) {
+ return new SurfaceImpl();
}
Window::~Window() {}
@@ -1491,7 +1487,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;
@@ -1580,7 +1576,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);
@@ -2022,7 +2018,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 a97967b41..3b757a263 100644
--- a/gtk/ScintillaGTK.cxx
+++ b/gtk/ScintillaGTK.cxx
@@ -574,7 +574,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));
@@ -1102,7 +1102,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));
@@ -2429,7 +2429,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);
@@ -2490,7 +2490,7 @@ gboolean ScintillaGTK::ExposeTextThis(GtkWidget * /*widget*/, GdkEventExpose *os
rgnUpdate = gdk_region_copy(ose->region);
PRectangle rcClient = GetClientRectangle();
paintingAllText = rcPaint.Contains(rcClient);
- Surface *surfaceWindow = Surface::Allocate();
+ Surface *surfaceWindow = Surface::Allocate(SC_TECHNOLOGY_DEFAULT);
if (surfaceWindow) {
surfaceWindow->Init(PWindow(wText), PWidget(wText));
Paint(surfaceWindow, rcPaint);
@@ -2782,7 +2782,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);
@@ -2801,7 +2801,7 @@ gboolean ScintillaGTK::DrawCT(GtkWidget *widget, cairo_t *cr, CallTip *ctip) {
gboolean ScintillaGTK::ExposeCT(GtkWidget *widget, GdkEventExpose * /*ose*/, CallTip *ctip) {
try {
- Surface *surfaceWindow = Surface::Allocate();
+ Surface *surfaceWindow = Surface::Allocate(SC_TECHNOLOGY_DEFAULT);
if (surfaceWindow) {
surfaceWindow->Init(WindowFromWidget(widget), 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 ee706e55d..9b99436ff 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
@@ -820,6 +828,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 f077bf6b7..aa0f030dd 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)
@@ -2178,6 +2197,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 2e4d724e5..507ae60a1 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;
@@ -227,12 +228,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() {
@@ -240,17 +236,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();
@@ -2220,7 +2249,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;
@@ -2241,7 +2270,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) {
@@ -2906,8 +2935,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);
@@ -3383,7 +3414,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
@@ -3928,7 +3959,7 @@ void Editor::SetScrollBars() {
}
void Editor::ChangeSize() {
- DropGraphics();
+ DropGraphics(false);
SetScrollBars();
if (wrapState != eWrapNone) {
PRectangle rcTextArea = GetClientRectangle();
@@ -6983,7 +7014,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;
@@ -6992,6 +7026,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:
@@ -7029,12 +7066,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)
@@ -8146,9 +8187,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:
@@ -8162,9 +8205,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:
@@ -9203,6 +9248,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 cd5695c09..06b905961 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;
@@ -280,7 +281,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();
@@ -575,7 +577,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());
@@ -585,7 +587,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 4d937ac81..3317dc0d3 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;