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