diff options
-rw-r--r-- | cocoa/PlatCocoa.h | 20 | ||||
-rw-r--r-- | cocoa/PlatCocoa.mm | 140 | ||||
-rw-r--r-- | cocoa/QuartzTextLayout.h | 4 | ||||
-rw-r--r-- | cocoa/QuartzTextStyle.h | 10 | ||||
-rwxr-xr-x | gtk/PlatGTK.cxx | 305 | ||||
-rw-r--r-- | qt/ScintillaEditBase/PlatQt.cpp | 122 | ||||
-rw-r--r-- | qt/ScintillaEditBase/PlatQt.h | 24 | ||||
-rw-r--r-- | src/CallTip.cxx | 15 | ||||
-rw-r--r-- | src/CallTip.h | 2 | ||||
-rw-r--r-- | src/EditView.cxx | 30 | ||||
-rw-r--r-- | src/Editor.cxx | 2 | ||||
-rw-r--r-- | src/LineMarker.cxx | 2 | ||||
-rw-r--r-- | src/LineMarker.h | 4 | ||||
-rw-r--r-- | src/MarginView.cxx | 2 | ||||
-rw-r--r-- | src/Platform.h | 40 | ||||
-rw-r--r-- | src/PositionCache.cxx | 4 | ||||
-rw-r--r-- | src/PositionCache.h | 2 | ||||
-rw-r--r-- | src/ScintillaBase.cxx | 2 | ||||
-rw-r--r-- | src/Style.cxx | 31 | ||||
-rw-r--r-- | src/Style.h | 18 | ||||
-rw-r--r-- | src/ViewStyle.cxx | 15 | ||||
-rw-r--r-- | src/ViewStyle.h | 2 | ||||
-rw-r--r-- | win32/PlatWin.cxx | 310 |
23 files changed, 485 insertions, 621 deletions
diff --git a/cocoa/PlatCocoa.h b/cocoa/PlatCocoa.h index c19ac8bca..f140295c5 100644 --- a/cocoa/PlatCocoa.h +++ b/cocoa/PlatCocoa.h @@ -101,18 +101,18 @@ public: void Ellipse(PRectangle rc, ColourDesired fore, ColourDesired back) override; void Copy(PRectangle rc, Scintilla::Point from, Surface &surfaceSource) override; std::unique_ptr<IScreenLineLayout> Layout(const IScreenLine *screenLine) override; - void DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, std::string_view text, ColourDesired fore, + void DrawTextNoClip(PRectangle rc, const Font *font_, XYPOSITION ybase, std::string_view text, ColourDesired fore, ColourDesired back) override; - void DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, std::string_view text, ColourDesired fore, + void DrawTextClipped(PRectangle rc, const Font *font_, XYPOSITION ybase, std::string_view text, ColourDesired fore, ColourDesired back) override; - void DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, std::string_view text, ColourDesired fore) override; - void MeasureWidths(Font &font_, std::string_view text, XYPOSITION *positions) override; - XYPOSITION WidthText(Font &font_, std::string_view text) override; - XYPOSITION Ascent(Font &font_) override; - XYPOSITION Descent(Font &font_) override; - XYPOSITION InternalLeading(Font &font_) override; - XYPOSITION Height(Font &font_) override; - XYPOSITION AverageCharWidth(Font &font_) override; + void DrawTextTransparent(PRectangle rc, const Font *font_, XYPOSITION ybase, std::string_view text, ColourDesired fore) override; + void MeasureWidths(const Font *font_, std::string_view text, XYPOSITION *positions) override; + XYPOSITION WidthText(const Font *font_, std::string_view text) override; + XYPOSITION Ascent(const Font *font_) override; + XYPOSITION Descent(const Font *font_) override; + XYPOSITION InternalLeading(const Font *font_) override; + XYPOSITION Height(const Font *font_) override; + XYPOSITION AverageCharWidth(const Font *font_) override; void SetClip(PRectangle rc) override; void FlushCachedState() override; diff --git a/cocoa/PlatCocoa.mm b/cocoa/PlatCocoa.mm index be9ee23cd..149949048 100644 --- a/cocoa/PlatCocoa.mm +++ b/cocoa/PlatCocoa.mm @@ -75,27 +75,33 @@ inline CGRect PRectangleToCGRect(PRectangle &rc) { return CGRectMake(rc.left, rc.top, rc.Width(), rc.Height()); } -//----------------- Font --------------------------------------------------------------------------- +//----------------- FontQuartz --------------------------------------------------------------------- -Font::Font() noexcept : fid(0) { -} - -//-------------------------------------------------------------------------------------------------- - -Font::~Font() { - Release(); -} - -//-------------------------------------------------------------------------------------------------- - -static QuartzTextStyle *TextStyleFromFont(const Font &f) { - return static_cast<QuartzTextStyle *>(f.GetID()); -} +class FontQuartz : public Font { +public: + std::unique_ptr<QuartzTextStyle> style; + FontQuartz(const FontParameters &fp) { + style = std::make_unique<QuartzTextStyle>(); + // Create the font with attributes + QuartzFont font(fp.faceName, strlen(fp.faceName), fp.size, fp.weight, fp.italic); + CTFontRef fontRef = font.getFontID(); + style->setFontRef(fontRef, fp.characterSet); + } + FontQuartz(const QuartzTextStyle *style_) { + style = std::make_unique<QuartzTextStyle>(style_); + } +}; //-------------------------------------------------------------------------------------------------- -static int FontCharacterSet(Font &f) { - return TextStyleFromFont(f)->getCharacterSet(); +static QuartzTextStyle *TextStyleFromFont(const Font *f) noexcept { + if (f) { + const FontQuartz *pfq = dynamic_cast<const FontQuartz *>(f); + if (pfq) { + return pfq->style.get(); + } + } + return nullptr; } //-------------------------------------------------------------------------------------------------- @@ -103,24 +109,8 @@ static int FontCharacterSet(Font &f) { /** * Creates a CTFontRef with the given properties. */ -void Font::Create(const FontParameters &fp) { - Release(); - - QuartzTextStyle *style = new QuartzTextStyle(); - fid = style; - - // Create the font with attributes - QuartzFont font(fp.faceName, strlen(fp.faceName), fp.size, fp.weight, fp.italic); - CTFontRef fontRef = font.getFontID(); - style->setFontRef(fontRef, fp.characterSet); -} - -//-------------------------------------------------------------------------------------------------- - -void Font::Release() { - if (fid) - delete static_cast<QuartzTextStyle *>(fid); - fid = 0; +std::shared_ptr<Font> Font::Allocate(const FontParameters &fp) { + return std::make_shared<FontQuartz>(fp); } //-------------------------------------------------------------------------------------------------- @@ -202,7 +192,7 @@ ScreenLineLayout::ScreenLineLayout(const IScreenLine *screenLine) : text(screenL byteCount, kCFStringEncodingUTF8, false); - QuartzTextStyle *qts = static_cast<QuartzTextStyle *>(screenLine->FontOfPosition(bp)->GetID()); + const QuartzTextStyle *qts = TextStyleFromFont(screenLine->FontOfPosition(bp)); CFMutableDictionaryRef pieceAttributes = qts->getCTStyle(); as = CFAttributedStringCreate(NULL, piece, pieceAttributes); CFRelease(piece); @@ -1037,7 +1027,7 @@ std::unique_ptr<IScreenLineLayout> SurfaceImpl::Layout(const IScreenLine *screen //-------------------------------------------------------------------------------------------------- -void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, std::string_view text, +void SurfaceImpl::DrawTextNoClip(PRectangle rc, const Font *font_, XYPOSITION ybase, std::string_view text, ColourDesired fore, ColourDesired back) { FillRectangle(rc, back); DrawTextTransparent(rc, font_, ybase, text, fore); @@ -1045,7 +1035,7 @@ void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, s //-------------------------------------------------------------------------------------------------- -void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, std::string_view text, +void SurfaceImpl::DrawTextClipped(PRectangle rc, const Font *font_, XYPOSITION ybase, std::string_view text, ColourDesired fore, ColourDesired back) { CGContextSaveGState(gc); CGContextClipToRect(gc, PRectangleToCGRect(rc)); @@ -1110,27 +1100,34 @@ CFStringEncoding EncodingFromCharacterSet(bool unicode, int characterSet) { } } -void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, std::string_view text, +void SurfaceImpl::DrawTextTransparent(PRectangle rc, const Font *font_, XYPOSITION ybase, std::string_view text, ColourDesired fore) { - CFStringEncoding encoding = EncodingFromCharacterSet(unicodeMode, FontCharacterSet(font_)); + QuartzTextStyle *style = TextStyleFromFont(font_); + if (!style) { + return; + } + CFStringEncoding encoding = EncodingFromCharacterSet(unicodeMode, style->getCharacterSet()); ColourDesired colour(fore.AsInteger()); CGColorRef color = CGColorCreateGenericRGB(colour.GetRed()/255.0, colour.GetGreen()/255.0, colour.GetBlue()/255.0, 1.0); - QuartzTextStyle *style = TextStyleFromFont(font_); style->setCTStyleColour(color); CGColorRelease(color); - textLayout->setText(text, encoding, *style); + textLayout->setText(text, encoding, style); textLayout->draw(gc, rc.left, ybase); } //-------------------------------------------------------------------------------------------------- -void SurfaceImpl::MeasureWidths(Font &font_, std::string_view text, XYPOSITION *positions) { - CFStringEncoding encoding = EncodingFromCharacterSet(unicodeMode, FontCharacterSet(font_)); +void SurfaceImpl::MeasureWidths(const Font *font_, std::string_view text, XYPOSITION *positions) { + const QuartzTextStyle *style = TextStyleFromFont(font_); + if (!style) { + return; + } + CFStringEncoding encoding = EncodingFromCharacterSet(unicodeMode, style->getCharacterSet()); const CFStringEncoding encodingUsed = - textLayout->setText(text, encoding, *TextStyleFromFont(font_)); + textLayout->setText(text, encoding, style); CTLineRef mLine = textLayout->getCTLine(); assert(mLine); @@ -1186,51 +1183,53 @@ void SurfaceImpl::MeasureWidths(Font &font_, std::string_view text, XYPOSITION * } -XYPOSITION SurfaceImpl::WidthText(Font &font_, std::string_view text) { - if (font_.GetID()) { - CFStringEncoding encoding = EncodingFromCharacterSet(unicodeMode, FontCharacterSet(font_)); - textLayout->setText(text, encoding, *TextStyleFromFont(font_)); - - return static_cast<XYPOSITION>(textLayout->MeasureStringWidth()); +XYPOSITION SurfaceImpl::WidthText(const Font *font_, std::string_view text) { + const QuartzTextStyle *style = TextStyleFromFont(font_); + if (!style) { + return 1; } - return 1; + CFStringEncoding encoding = EncodingFromCharacterSet(unicodeMode, style->getCharacterSet()); + textLayout->setText(text, encoding, style); + + return static_cast<XYPOSITION>(textLayout->MeasureStringWidth()); } // This string contains a good range of characters to test for size. const char sizeString[] = "`~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890" "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; -XYPOSITION SurfaceImpl::Ascent(Font &font_) { - if (!font_.GetID()) +XYPOSITION SurfaceImpl::Ascent(const Font *font_) { + const QuartzTextStyle *style = TextStyleFromFont(font_); + if (!style) { return 1; + } - float ascent = TextStyleFromFont(font_)->getAscent(); + float ascent = style->getAscent(); return ascent + 0.5f; } -XYPOSITION SurfaceImpl::Descent(Font &font_) { - if (!font_.GetID()) +XYPOSITION SurfaceImpl::Descent(const Font *font_) { + const QuartzTextStyle *style = TextStyleFromFont(font_); + if (!style) { return 1; + } - float descent = TextStyleFromFont(font_)->getDescent(); + float descent = style->getDescent(); return descent + 0.5f; } -XYPOSITION SurfaceImpl::InternalLeading(Font &) { +XYPOSITION SurfaceImpl::InternalLeading(const Font *) { return 0; } -XYPOSITION SurfaceImpl::Height(Font &font_) { +XYPOSITION SurfaceImpl::Height(const Font *font_) { return Ascent(font_) + Descent(font_); } -XYPOSITION SurfaceImpl::AverageCharWidth(Font &font_) { - - if (!font_.GetID()) - return 1; +XYPOSITION SurfaceImpl::AverageCharWidth(const Font *font_) { XYPOSITION width = WidthText(font_, sizeString); @@ -1407,7 +1406,7 @@ void Window::InvalidateRectangle(PRectangle rc) { //-------------------------------------------------------------------------------------------------- -void Window::SetFont(Font &) { +void Window::SetFont(const Font *) { // Implemented on list subclass on Cocoa. } @@ -1630,7 +1629,7 @@ private: XYPOSITION maxItemWidth; unsigned int aveCharWidth; XYPOSITION maxIconWidth; - Font font; + std::unique_ptr<Font> font; int maxWidth; NSTableView *table; @@ -1666,7 +1665,7 @@ public: } // ListBox methods - void SetFont(Font &font) override; + void SetFont(const Font *font_) override; void Create(Window &parent, int ctrlID, Scintilla::Point pt, int lineHeight_, bool unicodeMode_, int technology_) override; void SetAverageCharWidth(int width) override; void SetVisibleRows(int rows) override; @@ -1744,12 +1743,11 @@ void ListBoxImpl::Create(Window & /*parent*/, int /*ctrlID*/, Scintilla::Point p wid = (__bridge_retained WindowID)winLB; } -void ListBoxImpl::SetFont(Font &font_) { +void ListBoxImpl::SetFont(const Font *font_) { // NSCell setFont takes an NSFont* rather than a CTFontRef but they // are the same thing toll-free bridged. QuartzTextStyle *style = TextStyleFromFont(font_); - font.Release(); - font.SetID(new QuartzTextStyle(*style)); + font = std::make_unique<FontQuartz>(style); NSFont *pfont = (__bridge NSFont *)style->getFontRef(); [colText.dataCell setFont: pfont]; CGFloat itemHeight = std::ceil(pfont.boundingRectForFont.size.height); @@ -1831,7 +1829,7 @@ void ListBoxImpl::Append(char *s, int type) { ld.Add(count, type, s); Scintilla::SurfaceImpl surface; - XYPOSITION width = surface.WidthText(font, s); + XYPOSITION width = surface.WidthText(font.get(), s); if (width > maxItemWidth) { maxItemWidth = width; colText.width = maxItemWidth; diff --git a/cocoa/QuartzTextLayout.h b/cocoa/QuartzTextLayout.h index 0c6eb08dd..0c234fe39 100644 --- a/cocoa/QuartzTextLayout.h +++ b/cocoa/QuartzTextLayout.h @@ -33,7 +33,7 @@ public: } } - CFStringEncoding setText(std::string_view sv, CFStringEncoding encoding, const QuartzTextStyle &r) { + CFStringEncoding setText(std::string_view sv, CFStringEncoding encoding, const QuartzTextStyle *r) { // First clear current values in case of failure. if (mString) { CFRelease(mString); @@ -58,7 +58,7 @@ public: stringLength = CFStringGetLength(str); - CFMutableDictionaryRef stringAttribs = r.getCTStyle(); + CFMutableDictionaryRef stringAttribs = r->getCTStyle(); mString = ::CFAttributedStringCreate(NULL, str, stringAttribs); diff --git a/cocoa/QuartzTextStyle.h b/cocoa/QuartzTextStyle.h index 3c5684685..f8d50ebe9 100644 --- a/cocoa/QuartzTextStyle.h +++ b/cocoa/QuartzTextStyle.h @@ -21,14 +21,14 @@ public: characterSet = 0; } - QuartzTextStyle(const QuartzTextStyle &other) { + QuartzTextStyle(const QuartzTextStyle *other) { // Does not copy font colour attribute - fontRef = static_cast<CTFontRef>(CFRetain(other.fontRef)); + fontRef = static_cast<CTFontRef>(CFRetain(other->fontRef)); styleDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionaryAddValue(styleDict, kCTFontAttributeName, fontRef); - characterSet = other.characterSet; + characterSet = other->characterSet; } ~QuartzTextStyle() { @@ -77,11 +77,11 @@ public: CFDictionaryAddValue(styleDict, kCTFontAttributeName, fontRef); } - CTFontRef getFontRef() { + CTFontRef getFontRef() const noexcept { return fontRef; } - int getCharacterSet() { + int getCharacterSet() const noexcept { return characterSet; } diff --git a/gtk/PlatGTK.cxx b/gtk/PlatGTK.cxx index b9b9ab029..5471a7289 100755 --- a/gtk/PlatGTK.cxx +++ b/gtk/PlatGTK.cxx @@ -71,9 +71,9 @@ GtkWidget *PWidget(WindowID wid) noexcept { enum encodingType { singleByte, UTF8, dbcs }; // Holds a PangoFontDescription*. -class FontHandle { +class FontHandle : public Font { public: - PangoFontDescription *pfd; + PangoFontDescription *pfd = nullptr; int characterSet; FontHandle() noexcept : pfd(nullptr), characterSet(-1) { } @@ -81,6 +81,17 @@ public: pfd = pfd_; characterSet = characterSet_; } + FontHandle(const FontParameters &fp) { + pfd = pango_font_description_new(); + if (pfd) { + pango_font_description_set_family(pfd, + (fp.faceName[0] == '!') ? fp.faceName + 1 : fp.faceName); + pango_font_description_set_size(pfd, pangoUnitsFromDouble(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); + } + characterSet = fp.characterSet; + } // Deleted so FontHandle objects can not be copied. FontHandle(const FontHandle &) = delete; FontHandle(FontHandle &&) = delete; @@ -91,45 +102,19 @@ public: pango_font_description_free(pfd); pfd = nullptr; } - static FontHandle *CreateNewFont(const FontParameters &fp); }; -FontHandle *FontHandle::CreateNewFont(const FontParameters &fp) { - PangoFontDescription *pfd = pango_font_description_new(); - if (pfd) { - pango_font_description_set_family(pfd, - (fp.faceName[0] == '!') ? fp.faceName+1 : fp.faceName); - pango_font_description_set_size(pfd, pangoUnitsFromDouble(fp.size)); - pango_font_description_set_weight(pfd, static_cast<PangoWeight>(fp.weight)); - pango_font_description_set_style(pfd, fp.italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL); - return new FontHandle(pfd, fp.characterSet); - } - - return nullptr; -} - // X has a 16 bit coordinate space, so stop drawing here to avoid wrapping constexpr int maxCoordinate = 32000; -FontHandle *PFont(const Font &f) noexcept { - return static_cast<FontHandle *>(f.GetID()); +const FontHandle *PFont(const Font *f) noexcept { + return dynamic_cast<const FontHandle *>(f); } } -Font::Font() noexcept : fid(nullptr) {} - -Font::~Font() {} - -void Font::Create(const FontParameters &fp) { - Release(); - fid = FontHandle::CreateNewFont(fp); -} - -void Font::Release() { - if (fid) - delete static_cast<FontHandle *>(fid); - fid = nullptr; +std::shared_ptr<Font> Font::Allocate(const FontParameters &fp) { + return std::make_shared<FontHandle>(fp); } // Required on OS X @@ -184,17 +169,17 @@ public: std::unique_ptr<IScreenLineLayout> Layout(const IScreenLine *screenLine) override; - void DrawTextBase(PRectangle rc, const Font &font_, XYPOSITION ybase, std::string_view text, ColourDesired fore); - void DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, std::string_view text, ColourDesired fore, ColourDesired back) override; - void DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, std::string_view text, ColourDesired fore, ColourDesired back) override; - void DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, std::string_view text, ColourDesired fore) override; - void MeasureWidths(Font &font_, std::string_view text, XYPOSITION *positions) override; - XYPOSITION WidthText(Font &font_, std::string_view text) override; - XYPOSITION Ascent(Font &font_) override; - XYPOSITION Descent(Font &font_) override; - XYPOSITION InternalLeading(Font &font_) override; - XYPOSITION Height(Font &font_) override; - XYPOSITION AverageCharWidth(Font &font_) override; + void DrawTextBase(PRectangle rc, const Font *font_, XYPOSITION ybase, std::string_view text, ColourDesired fore); + void DrawTextNoClip(PRectangle rc, const Font *font_, XYPOSITION ybase, std::string_view text, ColourDesired fore, ColourDesired back) override; + void DrawTextClipped(PRectangle rc, const Font *font_, XYPOSITION ybase, std::string_view text, ColourDesired fore, ColourDesired back) override; + void DrawTextTransparent(PRectangle rc, const Font *font_, XYPOSITION ybase, std::string_view text, ColourDesired fore) override; + void MeasureWidths(const Font *font_, std::string_view text, XYPOSITION *positions) override; + XYPOSITION WidthText(const Font *font_, std::string_view text) override; + XYPOSITION Ascent(const Font *font_) override; + XYPOSITION Descent(const Font *font_) override; + XYPOSITION InternalLeading(const Font *font_) override; + XYPOSITION Height(const Font *font_) override; + XYPOSITION AverageCharWidth(const Font *font_) override; void SetClip(PRectangle rc) override; void FlushCachedState() override; @@ -684,7 +669,7 @@ size_t MultiByteLenFromIconv(const Converter &conv, const char *s, size_t len) n } -void SurfaceImpl::DrawTextBase(PRectangle rc, const Font &font_, XYPOSITION ybase, std::string_view text, +void SurfaceImpl::DrawTextBase(PRectangle rc, const Font *font_, XYPOSITION ybase, std::string_view text, ColourDesired fore) { PenColour(fore); if (context) { @@ -710,20 +695,20 @@ void SurfaceImpl::DrawTextBase(PRectangle rc, const Font &font_, XYPOSITION ybas } } -void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, std::string_view text, +void SurfaceImpl::DrawTextNoClip(PRectangle rc, const Font *font_, XYPOSITION ybase, std::string_view text, ColourDesired fore, ColourDesired back) { FillRectangle(rc, back); DrawTextBase(rc, font_, ybase, text, fore); } // On GTK+, exactly same as DrawTextNoClip -void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, std::string_view text, +void SurfaceImpl::DrawTextClipped(PRectangle rc, const Font *font_, XYPOSITION ybase, std::string_view text, ColourDesired fore, ColourDesired back) { FillRectangle(rc, back); DrawTextBase(rc, font_, ybase, text, fore); } -void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, std::string_view text, +void SurfaceImpl::DrawTextTransparent(PRectangle rc, const Font *font_, XYPOSITION ybase, std::string_view text, ColourDesired fore) { // Avoid drawing spaces in transparent mode for (size_t i=0; i<text.length(); i++) { @@ -774,102 +759,100 @@ public: } }; -void SurfaceImpl::MeasureWidths(Font &font_, std::string_view text, XYPOSITION *positions) { - if (font_.GetID()) { - if (PFont(font_)->pfd) { - pango_layout_set_font_description(layout, PFont(font_)->pfd); - if (et == UTF8) { - // Simple and direct as UTF-8 is native Pango encoding - int i = 0; - pango_layout_set_text(layout, text.data(), text.length()); - ClusterIterator iti(layout, text.length()); - while (!iti.finished) { - iti.Next(); - const int places = iti.curIndex - i; - while (i < iti.curIndex) { - // Evenly distribute space among bytes of this cluster. - // Would be better to find number of characters and then - // divide evenly between characters with each byte of a character - // being at the same position. - positions[i] = iti.position - (iti.curIndex - 1 - i) * iti.distance / places; - i++; - } - } - PLATFORM_ASSERT(static_cast<size_t>(i) == text.length()); - } else { - int positionsCalculated = 0; - if (et == dbcs) { - SetConverter(PFont(font_)->characterSet); - std::string utfForm = UTF8FromIconv(conv, text); - if (!utfForm.empty()) { - // Convert to UTF-8 so can ask Pango for widths, then - // Loop through UTF-8 and DBCS forms, taking account of different - // character byte lengths. - Converter convMeasure("UCS-2", CharacterSetID(characterSet), false); - pango_layout_set_text(layout, utfForm.c_str(), strlen(utfForm.c_str())); - int i = 0; - int clusterStart = 0; - ClusterIterator iti(layout, strlen(utfForm.c_str())); - while (!iti.finished) { - iti.Next(); - const int clusterEnd = iti.curIndex; - const int places = g_utf8_strlen(utfForm.c_str() + clusterStart, clusterEnd - clusterStart); - int place = 1; - while (clusterStart < clusterEnd) { - size_t lenChar = MultiByteLenFromIconv(convMeasure, text.data()+i, text.length()-i); - while (lenChar--) { - positions[i++] = iti.position - (places - place) * iti.distance / places; - positionsCalculated++; - } - clusterStart += UTF8BytesOfLead[static_cast<unsigned char>(utfForm[clusterStart])]; - place++; - } - } - PLATFORM_ASSERT(static_cast<size_t>(i) == text.length()); - } +void SurfaceImpl::MeasureWidths(const Font *font_, std::string_view text, XYPOSITION *positions) { + if (PFont(font_)->pfd) { + pango_layout_set_font_description(layout, PFont(font_)->pfd); + if (et == UTF8) { + // Simple and direct as UTF-8 is native Pango encoding + int i = 0; + pango_layout_set_text(layout, text.data(), text.length()); + ClusterIterator iti(layout, text.length()); + while (!iti.finished) { + iti.Next(); + const int places = iti.curIndex - i; + while (i < iti.curIndex) { + // Evenly distribute space among bytes of this cluster. + // Would be better to find number of characters and then + // divide evenly between characters with each byte of a character + // being at the same position. + positions[i] = iti.position - (iti.curIndex - 1 - i) * iti.distance / places; + i++; } - if (positionsCalculated < 1) { - const size_t lenPositions = text.length(); - // Either 8-bit or DBCS conversion failed so treat as 8-bit. - SetConverter(PFont(font_)->characterSet); - const bool rtlCheck = PFont(font_)->characterSet == SC_CHARSET_HEBREW || - PFont(font_)->characterSet == SC_CHARSET_ARABIC; - std::string utfForm = UTF8FromIconv(conv, text); - if (utfForm.empty()) { - utfForm = UTF8FromLatin1(text); - } - pango_layout_set_text(layout, utfForm.c_str(), utfForm.length()); - size_t i = 0; + } + PLATFORM_ASSERT(static_cast<size_t>(i) == text.length()); + } else { + int positionsCalculated = 0; + if (et == dbcs) { + SetConverter(PFont(font_)->characterSet); + std::string utfForm = UTF8FromIconv(conv, text); + if (!utfForm.empty()) { + // Convert to UTF-8 so can ask Pango for widths, then + // Loop through UTF-8 and DBCS forms, taking account of different + // character byte lengths. + Converter convMeasure("UCS-2", CharacterSetID(characterSet), false); + pango_layout_set_text(layout, utfForm.c_str(), strlen(utfForm.c_str())); + int i = 0; int clusterStart = 0; - // Each 8-bit input character may take 1 or 2 bytes in UTF-8 - // and groups of up to 3 may be represented as ligatures. - ClusterIterator iti(layout, utfForm.length()); + ClusterIterator iti(layout, strlen(utfForm.c_str())); while (!iti.finished) { iti.Next(); const int clusterEnd = iti.curIndex; - const int ligatureLength = g_utf8_strlen(utfForm.c_str() + clusterStart, clusterEnd - clusterStart); - if (rtlCheck && ((clusterEnd <= clusterStart) || (ligatureLength == 0) || (ligatureLength > 3))) { - // Something has gone wrong: exit quickly but pretend all the characters are equally spaced: - int widthLayout = 0; - pango_layout_get_size(layout, &widthLayout, nullptr); - const XYPOSITION widthTotal = floatFromPangoUnits(widthLayout); - for (size_t bytePos=0; bytePos<lenPositions; bytePos++) { - positions[bytePos] = widthTotal / lenPositions * (bytePos + 1); + const int places = g_utf8_strlen(utfForm.c_str() + clusterStart, clusterEnd - clusterStart); + int place = 1; + while (clusterStart < clusterEnd) { + size_t lenChar = MultiByteLenFromIconv(convMeasure, text.data()+i, text.length()-i); + while (lenChar--) { + positions[i++] = iti.position - (places - place) * iti.distance / places; + positionsCalculated++; } - return; + clusterStart += UTF8BytesOfLead[static_cast<unsigned char>(utfForm[clusterStart])]; + place++; } - PLATFORM_ASSERT(ligatureLength > 0 && ligatureLength <= 3); - for (int charInLig=0; charInLig<ligatureLength; charInLig++) { - positions[i++] = iti.position - (ligatureLength - 1 - charInLig) * iti.distance / ligatureLength; + } + PLATFORM_ASSERT(static_cast<size_t>(i) == text.length()); + } + } + if (positionsCalculated < 1) { + const size_t lenPositions = text.length(); + // Either 8-bit or DBCS conversion failed so treat as 8-bit. + SetConverter(PFont(font_)->characterSet); + const bool rtlCheck = PFont(font_)->characterSet == SC_CHARSET_HEBREW || + PFont(font_)->characterSet == SC_CHARSET_ARABIC; + std::string utfForm = UTF8FromIconv(conv, text); + if (utfForm.empty()) { + utfForm = UTF8FromLatin1(text); + } + pango_layout_set_text(layout, utfForm.c_str(), utfForm.length()); + size_t i = 0; + int clusterStart = 0; + // Each 8-bit input character may take 1 or 2 bytes in UTF-8 + // and groups of up to 3 may be represented as ligatures. + ClusterIterator iti(layout, utfForm.length()); + while (!iti.finished) { + iti.Next(); + const int clusterEnd = iti.curIndex; + const int ligatureLength = g_utf8_strlen(utfForm.c_str() + clusterStart, clusterEnd - clusterStart); + if (rtlCheck && ((clusterEnd <= clusterStart) || (ligatureLength == 0) || (ligatureLength > 3))) { + // Something has gone wrong: exit quickly but pretend all the characters are equally spaced: + int widthLayout = 0; + pango_layout_get_size(layout, &widthLayout, nullptr); + const XYPOSITION widthTotal = floatFromPangoUnits(widthLayout); + for (size_t bytePos=0; bytePos<lenPositions; bytePos++) { + positions[bytePos] = widthTotal / lenPositions * (bytePos + 1); } - clusterStart = clusterEnd; + return; } - while (i < lenPositions) { - // If something failed, fill in rest of the positions - positions[i++] = clusterStart; + PLATFORM_ASSERT(ligatureLength > 0 && ligatureLength <= 3); + for (int charInLig=0; charInLig<ligatureLength; charInLig++) { + positions[i++] = iti.position - (ligatureLength - 1 - charInLig) * iti.distance / ligatureLength; } - PLATFORM_ASSERT(i == text.length()); + clusterStart = clusterEnd; } + while (i < lenPositions) { + // If something failed, fill in rest of the positions + positions[i++] = clusterStart; + } + PLATFORM_ASSERT(i == text.length()); } } } else { @@ -880,37 +863,31 @@ void SurfaceImpl::MeasureWidths(Font &font_, std::string_view text, XYPOSITION * } } -XYPOSITION SurfaceImpl::WidthText(Font &font_, std::string_view text) { - if (font_.GetID()) { - if (PFont(font_)->pfd) { - std::string utfForm; - pango_layout_set_font_description(layout, PFont(font_)->pfd); - if (et == UTF8) { - pango_layout_set_text(layout, text.data(), text.length()); - } else { - SetConverter(PFont(font_)->characterSet); - utfForm = UTF8FromIconv(conv, text); - if (utfForm.empty()) { // iconv failed so treat as Latin1 - utfForm = UTF8FromLatin1(text); - } - pango_layout_set_text(layout, utfForm.c_str(), utfForm.length()); +XYPOSITION SurfaceImpl::WidthText(const Font *font_, std::string_view text) { + if (PFont(font_)->pfd) { + std::string utfForm; + pango_layout_set_font_description(layout, PFont(font_)->pfd); + if (et == UTF8) { + pango_layout_set_text(layout, text.data(), text.length()); + } else { + SetConverter(PFont(font_)->characterSet); + utfForm = UTF8FromIconv(conv, text); + if (utfForm.empty()) { // iconv failed so treat as Latin1 + utfForm = UTF8FromLatin1(text); } - PangoLayoutLine *pangoLine = pango_layout_get_line_readonly(layout, 0); - PangoRectangle pos {}; - pango_layout_line_get_extents(pangoLine, nullptr, &pos); - return floatFromPangoUnits(pos.width); + pango_layout_set_text(layout, utfForm.c_str(), utfForm.length()); } - return 1; - } else { - return 1; + PangoLayoutLine *pangoLine = pango_layout_get_line_readonly(layout, 0); + PangoRectangle pos {}; + pango_layout_line_get_extents(pangoLine, nullptr, &pos); + return floatFromPangoUnits(pos.width); } + return 1; } // Ascent and descent determined by Pango font metrics. -XYPOSITION SurfaceImpl::Ascent(Font &font_) { - if (!(font_.GetID())) - return 1; +XYPOSITION SurfaceImpl::Ascent(const Font *font_) { XYPOSITION ascent = 0; if (PFont(font_)->pfd) { PangoFontMetrics *metrics = pango_context_get_metrics(pcontext, @@ -925,9 +902,7 @@ XYPOSITION SurfaceImpl::Ascent(Font &font_) { return ascent; } -XYPOSITION SurfaceImpl::Descent(Font &font_) { - if (!(font_.GetID())) - return 1; +XYPOSITION SurfaceImpl::Descent(const Font *font_) { if (PFont(font_)->pfd) { PangoFontMetrics *metrics = pango_context_get_metrics(pcontext, PFont(font_)->pfd, pango_context_get_language(pcontext)); @@ -939,15 +914,15 @@ XYPOSITION SurfaceImpl::Descent(Font &font_) { return 0; } -XYPOSITION SurfaceImpl::InternalLeading(Font &) { +XYPOSITION SurfaceImpl::InternalLeading(const Font *) { return 0; } -XYPOSITION SurfaceImpl::Height(Font &font_) { +XYPOSITION SurfaceImpl::Height(const Font *font_) { return Ascent(font_) + Descent(font_); } -XYPOSITION SurfaceImpl::AverageCharWidth(Font &font_) { +XYPOSITION SurfaceImpl::AverageCharWidth(const Font *font_) { return WidthText(font_, "n"); } @@ -1092,7 +1067,7 @@ void Window::InvalidateRectangle(PRectangle rc) { } } -void Window::SetFont(Font &) { +void Window::SetFont(const Font *) { // Can not be done generically but only needed for ListBox } @@ -1240,7 +1215,7 @@ public: } #endif } - void SetFont(Font &font) override; + void SetFont(const Font *font) override; void Create(Window &parent, int ctrlID, Point location_, int lineHeight_, bool unicodeMode_, int technology_) override; void SetAverageCharWidth(int width) override; void SetVisibleRows(int rows) override; @@ -1508,7 +1483,7 @@ void ListBoxX::Create(Window &parent, int, Point, int, bool, int) { GTK_WINDOW(top)); } -void ListBoxX::SetFont(Font &font) { +void ListBoxX::SetFont(const Font *font) { // Only do for Pango font as there have been crashes for GDK fonts if (Created() && PFont(font)->pfd) { // Current font is Pango font diff --git a/qt/ScintillaEditBase/PlatQt.cpp b/qt/ScintillaEditBase/PlatQt.cpp index 9ea1d88f5..ee17bf0f7 100644 --- a/qt/ScintillaEditBase/PlatQt.cpp +++ b/qt/ScintillaEditBase/PlatQt.cpp @@ -100,12 +100,30 @@ QString UnicodeFromText(QTextCodec *codec, std::string_view text) { return codec->toUnicode(text.data(), static_cast<int>(text.length())); } -class FontAndCharacterSet { +static QFont::StyleStrategy ChooseStrategy(int eff) +{ + switch (eff) { + case SC_EFF_QUALITY_DEFAULT: return QFont::PreferDefault; + case SC_EFF_QUALITY_NON_ANTIALIASED: return QFont::NoAntialias; + case SC_EFF_QUALITY_ANTIALIASED: return QFont::PreferAntialias; + case SC_EFF_QUALITY_LCD_OPTIMIZED: return QFont::PreferAntialias; + default: return QFont::PreferDefault; + } +} + +class FontAndCharacterSet : public Font { public: - int characterSet; - QFont *pfont; - FontAndCharacterSet(int characterSet_, QFont *pfont): - characterSet(characterSet_), pfont(pfont) { + int characterSet = 0; + QFont *pfont = nullptr; + FontAndCharacterSet(const FontParameters &fp) { + pfont = new QFont; + pfont->setStyleStrategy(ChooseStrategy(fp.extraFontFlag)); + pfont->setFamily(QString::fromUtf8(fp.faceName)); + pfont->setPointSizeF(fp.size); + pfont->setBold(fp.weight > 500); + pfont->setItalic(fp.italic); + + characterSet = fp.characterSet; } ~FontAndCharacterSet() { delete pfont; @@ -115,59 +133,22 @@ public: namespace { -FontAndCharacterSet *AsFontAndCharacterSet(const Font &f) { - return reinterpret_cast<FontAndCharacterSet *>(f.GetID()); -} - -int FontCharacterSet(const Font &f) -{ - return AsFontAndCharacterSet(f)->characterSet; +const FontAndCharacterSet *AsFontAndCharacterSet(const Font *f) { + return dynamic_cast<const FontAndCharacterSet *>(f); } -QFont *FontPointer(const Font &f) +QFont *FontPointer(const Font *f) { return AsFontAndCharacterSet(f)->pfont; } } -Font::Font() noexcept : fid(nullptr) {} -Font::~Font() +std::shared_ptr<Font> Font::Allocate(const FontParameters &fp) { - delete reinterpret_cast<FontAndCharacterSet *>(fid); - fid = nullptr; -} -static QFont::StyleStrategy ChooseStrategy(int eff) -{ - switch (eff) { - case SC_EFF_QUALITY_DEFAULT: return QFont::PreferDefault; - case SC_EFF_QUALITY_NON_ANTIALIASED: return QFont::NoAntialias; - case SC_EFF_QUALITY_ANTIALIASED: return QFont::PreferAntialias; - case SC_EFF_QUALITY_LCD_OPTIMIZED: return QFont::PreferAntialias; - default: return QFont::PreferDefault; - } -} - -void Font::Create(const FontParameters &fp) -{ - Release(); - - QFont *font = new QFont; - font->setStyleStrategy(ChooseStrategy(fp.extraFontFlag)); - font->setFamily(QString::fromUtf8(fp.faceName)); - font->setPointSizeF(fp.size); - font->setBold(fp.weight > 500); - font->setItalic(fp.italic); - - fid = new FontAndCharacterSet(fp.characterSet, font); + return std::make_shared<FontAndCharacterSet>(fp); } -void Font::Release() -{ - if (fid) - delete reinterpret_cast<FontAndCharacterSet *>(fid); - fid = nullptr; -} SurfaceImpl::SurfaceImpl() : device(nullptr), painter(nullptr), deviceOwned(false), painterOwned(false), x(0), y(0), unicodeMode(false), codePage(0), codecName(nullptr), codec(nullptr) @@ -241,12 +222,13 @@ void SurfaceImpl::BrushColour(ColourDesired back) GetPainter()->setBrush(QBrush(QColorFromCA(back))); } -void SurfaceImpl::SetCodec(const Font &font) +void SurfaceImpl::SetCodec(const Font *font) { - if (font.GetID()) { + const FontAndCharacterSet *pfacs = AsFontAndCharacterSet(font); + if (pfacs && pfacs->pfont) { const char *csid = "UTF-8"; if (!unicodeMode) - csid = CharacterSetID(FontCharacterSet(font)); + csid = CharacterSetID(pfacs->characterSet); if (csid != codecName) { codecName = csid; codec = QTextCodec::codecForName(csid); @@ -254,10 +236,11 @@ void SurfaceImpl::SetCodec(const Font &font) } } -void SurfaceImpl::SetFont(const Font &font) +void SurfaceImpl::SetFont(const Font *font) { - if (font.GetID()) { - GetPainter()->setFont(*FontPointer(font)); + const FontAndCharacterSet *pfacs = AsFontAndCharacterSet(font); + if (pfacs && pfacs->pfont) { + GetPainter()->setFont(*(pfacs->pfont)); SetCodec(font); } } @@ -444,7 +427,7 @@ std::unique_ptr<IScreenLineLayout> SurfaceImpl::Layout(const IScreenLine *) } void SurfaceImpl::DrawTextNoClip(PRectangle rc, - Font &font, + const Font *font, XYPOSITION ybase, std::string_view text, ColourDesired fore, @@ -460,7 +443,7 @@ void SurfaceImpl::DrawTextNoClip(PRectangle rc, } void SurfaceImpl::DrawTextClipped(PRectangle rc, - Font &font, + const Font *font, XYPOSITION ybase, std::string_view text, ColourDesired fore, @@ -472,7 +455,7 @@ void SurfaceImpl::DrawTextClipped(PRectangle rc, } void SurfaceImpl::DrawTextTransparent(PRectangle rc, - Font &font, + const Font *font, XYPOSITION ybase, std::string_view text, ColourDesired fore) @@ -490,11 +473,11 @@ void SurfaceImpl::SetClip(PRectangle rc) GetPainter()->setClipRect(QRectFFromPRect(rc)); } -void SurfaceImpl::MeasureWidths(Font &font, +void SurfaceImpl::MeasureWidths(const Font *font, std::string_view text, XYPOSITION *positions) { - if (!font.GetID()) + if (!font) return; SetCodec(font); QString su = UnicodeFromText(codec, text); @@ -541,7 +524,7 @@ void SurfaceImpl::MeasureWidths(Font &font, } } -XYPOSITION SurfaceImpl::WidthText(Font &font, std::string_view text) +XYPOSITION SurfaceImpl::WidthText(const Font *font, std::string_view text) { QFontMetricsF metrics(*FontPointer(font), device); SetCodec(font); @@ -549,13 +532,13 @@ XYPOSITION SurfaceImpl::WidthText(Font &font, std::string_view text) return metrics.width(su); } -XYPOSITION SurfaceImpl::Ascent(Font &font) +XYPOSITION SurfaceImpl::Ascent(const Font *font) { QFontMetricsF metrics(*FontPointer(font), device); return metrics.ascent(); } -XYPOSITION SurfaceImpl::Descent(Font &font) +XYPOSITION SurfaceImpl::Descent(const Font *font) { QFontMetricsF metrics(*FontPointer(font), device); // Qt returns 1 less than true descent @@ -565,18 +548,18 @@ XYPOSITION SurfaceImpl::Descent(Font &font) return metrics.descent() + 1; } -XYPOSITION SurfaceImpl::InternalLeading(Font & /* font */) +XYPOSITION SurfaceImpl::InternalLeading(const Font * /* font */) { return 0; } -XYPOSITION SurfaceImpl::Height(Font &font) +XYPOSITION SurfaceImpl::Height(const Font *font) { QFontMetricsF metrics(*FontPointer(font), device); return metrics.height(); } -XYPOSITION SurfaceImpl::AverageCharWidth(Font &font) +XYPOSITION SurfaceImpl::AverageCharWidth(const Font *font) { QFontMetricsF metrics(*FontPointer(font), device); return metrics.averageCharWidth(); @@ -727,7 +710,7 @@ void Window::InvalidateRectangle(PRectangle rc) window(wid)->update(QRectFromPRect(rc)); } -void Window::SetFont(Font &font) +void Window::SetFont(const Font *font) { if (wid) window(wid)->setFont(*FontPointer(font)); @@ -793,7 +776,7 @@ public: ListBoxImpl(); ~ListBoxImpl(); - void SetFont(Font &font) override; + void SetFont(const Font *font) override; void Create(Window &parent, int ctrlID, Point location, int lineHeight, bool unicodeMode_, int technology) override; void SetAverageCharWidth(int width) override; @@ -874,10 +857,13 @@ void ListBoxImpl::Create(Window &parent, wid = list; } -void ListBoxImpl::SetFont(Font &font) +void ListBoxImpl::SetFont(const Font *font) { ListWidget *list = GetWidget(); - list->setFont(*FontPointer(font)); + const FontAndCharacterSet *pfacs = AsFontAndCharacterSet(font); + if (pfacs && pfacs->pfont) { + list->setFont(*(pfacs->pfont)); + } } void ListBoxImpl::SetAverageCharWidth(int /*width*/) {} diff --git a/qt/ScintillaEditBase/PlatQt.h b/qt/ScintillaEditBase/PlatQt.h index 63364a3d7..2860e1397 100644 --- a/qt/ScintillaEditBase/PlatQt.h +++ b/qt/ScintillaEditBase/PlatQt.h @@ -113,20 +113,20 @@ public: std::unique_ptr<IScreenLineLayout> Layout(const IScreenLine *screenLine) override; - void DrawTextNoClip(PRectangle rc, Font &font, XYPOSITION ybase, + void DrawTextNoClip(PRectangle rc, const Font *font, XYPOSITION ybase, std::string_view text, ColourDesired fore, ColourDesired back) override; - void DrawTextClipped(PRectangle rc, Font &font, XYPOSITION ybase, + void DrawTextClipped(PRectangle rc, const Font *font, XYPOSITION ybase, std::string_view text, ColourDesired fore, ColourDesired back) override; - void DrawTextTransparent(PRectangle rc, Font &font, XYPOSITION ybase, + void DrawTextTransparent(PRectangle rc, const Font *font, XYPOSITION ybase, std::string_view text, ColourDesired fore) override; - void MeasureWidths(Font &font, std::string_view text, + void MeasureWidths(const Font *font, std::string_view text, XYPOSITION *positions) override; - XYPOSITION WidthText(Font &font, std::string_view text) override; - XYPOSITION Ascent(Font &font) override; - XYPOSITION Descent(Font &font) override; - XYPOSITION InternalLeading(Font &font) override; - XYPOSITION Height(Font &font) override; - XYPOSITION AverageCharWidth(Font &font) override; + XYPOSITION WidthText(const Font *font, std::string_view text) override; + XYPOSITION Ascent(const Font *font) override; + XYPOSITION Descent(const Font *font) override; + XYPOSITION InternalLeading(const Font *font) override; + XYPOSITION Height(const Font *font) override; + XYPOSITION AverageCharWidth(const Font *font) override; void SetClip(PRectangle rc) override; void FlushCachedState() override; @@ -136,8 +136,8 @@ public: void SetBidiR2L(bool bidiR2L_) override; void BrushColour(ColourDesired back); - void SetCodec(const Font &font); - void SetFont(const Font &font); + void SetCodec(const Font *font); + void SetFont(const Font *font); QPaintDevice *GetPaintDevice(); void SetPainter(QPainter *painter); diff --git a/src/CallTip.cxx b/src/CallTip.cxx index 667e41c96..e6bfc2b7e 100644 --- a/src/CallTip.cxx +++ b/src/CallTip.cxx @@ -67,7 +67,6 @@ CallTip::CallTip() noexcept { } CallTip::~CallTip() { - font.Release(); wCallTip.Destroy(); } @@ -168,11 +167,11 @@ int CallTip::DrawChunk(Surface *surface, int x, std::string_view sv, xEnd = NextTabPos(x); } else { const std::string_view segText = sv.substr(startSeg, endSeg - startSeg); - xEnd = x + static_cast<int>(std::lround(surface->WidthText(font, segText))); + xEnd = x + static_cast<int>(std::lround(surface->WidthText(font.get(), segText))); if (draw) { rcClient.left = static_cast<XYPOSITION>(x); rcClient.right = static_cast<XYPOSITION>(xEnd); - surface->DrawTextTransparent(rcClient, font, static_cast<XYPOSITION>(ytext), + surface->DrawTextTransparent(rcClient, font.get(), static_cast<XYPOSITION>(ytext), segText, asHighlight ? colourSel : colourUnSel); } } @@ -189,12 +188,12 @@ int CallTip::PaintContents(Surface *surfaceWindow, bool draw) { PRectangle rcClient(1.0f, 1.0f, rcClientSize.right - 1, rcClientSize.bottom - 1); // To make a nice small call tip window, it is only sized to fit most normal characters without accents - const int ascent = static_cast<int>(std::round(surfaceWindow->Ascent(font) - surfaceWindow->InternalLeading(font))); + const int ascent = static_cast<int>(std::round(surfaceWindow->Ascent(font.get()) - surfaceWindow->InternalLeading(font.get()))); // For each line... // Draw the definition in three parts: before highlight, highlighted, after highlight int ytext = static_cast<int>(rcClient.top) + ascent + 1; - rcClient.bottom = ytext + surfaceWindow->Descent(font) + 1; + rcClient.bottom = ytext + surfaceWindow->Descent(font.get()) + 1; std::string_view remaining(val); int maxWidth = 0; size_t lineStart = 0; @@ -286,7 +285,7 @@ PRectangle CallTip::CallTipStart(Sci::Position pos, Point pt, int textHeight, co posStartCallTip = pos; const XYPOSITION deviceHeight = static_cast<XYPOSITION>(surfaceMeasure->DeviceHeightFont(size)); const FontParameters fp(faceName, deviceHeight / SC_FONT_SIZE_MULTIPLIER, SC_WEIGHT_NORMAL, false, 0, technology, characterSet); - font.Create(fp); + font = Font::Allocate(fp); // Look for multiple lines in the text // Only support \n here - simply means container must avoid \r! const int numLines = 1 + static_cast<int>(std::count(val.begin(), val.end(), '\n')); @@ -294,12 +293,12 @@ PRectangle CallTip::CallTipStart(Sci::Position pos, Point pt, int textHeight, co rectDown = PRectangle(0,0,0,0); offsetMain = insetX; // changed to right edge of any arrows const int width = PaintContents(surfaceMeasure.get(), false) + insetX; - lineHeight = static_cast<int>(std::lround(surfaceMeasure->Height(font))); + lineHeight = static_cast<int>(std::lround(surfaceMeasure->Height(font.get()))); // The returned // rectangle is aligned to the right edge of the last arrow encountered in // the tip text, else to the tip text left edge. - const int height = lineHeight * numLines - static_cast<int>(surfaceMeasure->InternalLeading(font)) + borderHeight * 2; + const int height = lineHeight * numLines - static_cast<int>(surfaceMeasure->InternalLeading(font.get())) + borderHeight * 2; if (above) { return PRectangle(pt.x - offsetMain, pt.y - verticalOffset - height, pt.x + width - offsetMain, pt.y - verticalOffset); } else { diff --git a/src/CallTip.h b/src/CallTip.h index 562b24f9d..6cc89d3a5 100644 --- a/src/CallTip.h +++ b/src/CallTip.h @@ -24,7 +24,7 @@ struct Chunk { class CallTip { Chunk highlight; // character offset to start and end of highlighted text std::string val; - Font font; + std::shared_ptr<Font> font; PRectangle rectUp; // rectangle of last up angle in the tip PRectangle rectDown; // rectangle of last down arrow in the tip int lineHeight; // vertical line spacing diff --git a/src/EditView.cxx b/src/EditView.cxx index 87d8134c6..fcb747d21 100644 --- a/src/EditView.cxx +++ b/src/EditView.cxx @@ -90,7 +90,7 @@ static int WidthStyledText(Surface *surface, const ViewStyle &vs, int styleOffse size_t endSegment = start; while ((endSegment + 1 < len) && (styles[endSegment + 1] == style)) endSegment++; - FontAlias fontText = vs.styles[style + styleOffset].font; + const Font *fontText = vs.styles[style + styleOffset].font.get(); const std::string_view sv(text + start, endSegment - start + 1); width += static_cast<int>(surface->WidthText(fontText, sv)); start = endSegment + 1; @@ -107,7 +107,7 @@ int WidestLineWidth(Surface *surface, const ViewStyle &vs, int styleOffset, cons if (st.multipleStyles) { widthSubLine = WidthStyledText(surface, vs, styleOffset, st.text + start, st.styles + start, lenLine); } else { - FontAlias fontText = vs.styles[styleOffset + st.style].font; + const Font *fontText = vs.styles[styleOffset + st.style].font.get(); const std::string_view text(st.text + start, lenLine); widthSubLine = static_cast<int>(surface->WidthText(fontText, text)); } @@ -120,7 +120,7 @@ int WidestLineWidth(Surface *surface, const ViewStyle &vs, int styleOffset, cons void DrawTextNoClipPhase(Surface *surface, PRectangle rc, const Style &style, XYPOSITION ybase, std::string_view text, DrawPhase phase) { - FontAlias fontText = style.font; + const Font *fontText = style.font.get(); if (phase & drawBack) { if (phase & drawText) { // Drawing both @@ -146,7 +146,7 @@ void DrawStyledText(Surface *surface, const ViewStyle &vs, int styleOffset, PRec while (end < length - 1 && st.styles[start + end + 1] == style) end++; style += styleOffset; - FontAlias fontText = vs.styles[style].font; + const Font *fontText = vs.styles[style].font.get(); const std::string_view text(st.text + start + i, end - i + 1); const int width = static_cast<int>(surface->WidthText(fontText, text)); PRectangle rcSegment = rcText; @@ -601,9 +601,9 @@ void EditView::UpdateBidiData(const EditModel &model, const ViewStyle &vstyle, L if (model.BidirectionalEnabled()) { ll->EnsureBidiData(); for (int stylesInLine = 0; stylesInLine < ll->numCharsInLine; stylesInLine++) { - ll->bidiData->stylesFonts[stylesInLine].MakeAlias(vstyle.styles[ll->styles[stylesInLine]].font); + ll->bidiData->stylesFonts[stylesInLine] = vstyle.styles[ll->styles[stylesInLine]].font; } - ll->bidiData->stylesFonts[ll->numCharsInLine].ClearFont(); + ll->bidiData->stylesFonts[ll->numCharsInLine].reset(); for (int charsInLine = 0; charsInLine < ll->numCharsInLine; charsInLine++) { const int charWidth = UTF8DrawBytes(reinterpret_cast<unsigned char *>(&ll->chars[charsInLine]), ll->numCharsInLine - charsInLine); @@ -877,7 +877,7 @@ static void DrawTextBlob(Surface *surface, const ViewStyle &vsDraw, PRectangle r if (fillBackground) { surface->FillRectangle(rcSegment, textBack); } - FontAlias ctrlCharsFont = vsDraw.styles[STYLE_CONTROLCHAR].font; + const Font *ctrlCharsFont = vsDraw.styles[STYLE_CONTROLCHAR].font.get(); const int normalCharHeight = static_cast<int>(std::ceil(vsDraw.styles[STYLE_CONTROLCHAR].capitalHeight)); PRectangle rcCChar = rcSegment; rcCChar.left = rcCChar.left + 1; @@ -1202,7 +1202,7 @@ void EditView::DrawFoldDisplayText(Surface *surface, const EditModel &model, con PRectangle rcSegment = rcLine; const std::string_view foldDisplayText(text); - FontAlias fontText = vsDraw.styles[STYLE_FOLDDISPLAYTEXT].font; + const Font *fontText = vsDraw.styles[STYLE_FOLDDISPLAYTEXT].font.get(); const int widthFoldDisplayText = static_cast<int>(surface->WidthText(fontText, foldDisplayText)); int eolInSelection = 0; @@ -1300,7 +1300,7 @@ void EditView::DrawEOLAnnotationText(Surface *surface, const EditModel &model, c const size_t style = stEOLAnnotation.style + vsDraw.eolAnnotationStyleOffset; PRectangle rcSegment = rcLine; - FontAlias fontText = vsDraw.styles[style].font; + const Font *fontText = vsDraw.styles[style].font.get(); const int widthEOLAnnotationText = static_cast<int>(surface->WidthText(fontText, eolAnnotationText)); const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth; @@ -1493,7 +1493,7 @@ static void DrawBlockCaret(Surface *surface, const EditModel &model, const ViewS // This character is where the caret block is, we override the colours // (inversed) for drawing the caret here. const int styleMain = ll->styles[offsetFirstChar]; - FontAlias fontText = vsDraw.styles[styleMain].font; + const Font *fontText = vsDraw.styles[styleMain].font.get(); const std::string_view text(&ll->chars[offsetFirstChar], numCharsToDraw); surface->DrawTextClipped(rcCaret, fontText, rcCaret.top + vsDraw.maxAscent, text, vsDraw.styles[styleMain].back, @@ -1883,7 +1883,7 @@ void EditView::DrawForeground(Surface *surface, const EditModel &model, const Vi if (rcSegment.Intersects(rcLine)) { const int styleMain = ll->styles[i]; ColourDesired textFore = vsDraw.styles[styleMain].fore; - FontAlias textFont = vsDraw.styles[styleMain].font; + const Font *textFont = vsDraw.styles[styleMain].font.get(); //hotspot foreground const bool inHotspot = (ll->hotspot.Valid()) && ll->hotspot.ContainsCharacter(iDoc); if (inHotspot) { @@ -1961,7 +1961,7 @@ void EditView::DrawForeground(Surface *surface, const EditModel &model, const Vi // Using one font for all control characters so it can be controlled independently to ensure // the box goes around the characters tightly. Seems to be no way to work out what height // is taken by an individual character - internal leading gives varying results. - FontAlias ctrlCharsFont = vsDraw.styles[STYLE_CONTROLCHAR].font; + const Font *ctrlCharsFont = vsDraw.styles[STYLE_CONTROLCHAR].font.get(); const char cc[2] = { static_cast<char>(vsDraw.controlCharSymbol), '\0' }; surface->DrawTextNoClip(rcSegment, ctrlCharsFont, rcSegment.top + vsDraw.maxAscent, @@ -2509,7 +2509,7 @@ Sci::Position EditView::FormatRange(bool draw, const Sci_RangeToFormat *pfr, Sur // Determining width must happen after fonts have been realised in Refresh int lineNumberWidth = 0; if (lineNumberIndex >= 0) { - lineNumberWidth = static_cast<int>(surfaceMeasure->WidthText(vsPrint.styles[STYLE_LINENUMBER].font, + lineNumberWidth = static_cast<int>(surfaceMeasure->WidthText(vsPrint.styles[STYLE_LINENUMBER].font.get(), "99999" lineNumberPrintSpace)); vsPrint.ms[lineNumberIndex].width = lineNumberWidth; vsPrint.Refresh(*surfaceMeasure, model.pdoc->tabInChars); // Recalculate fixedColumnWidth @@ -2589,9 +2589,9 @@ Sci::Position EditView::FormatRange(bool draw, const Sci_RangeToFormat *pfr, Sur rcNumber.right = rcNumber.left + lineNumberWidth; // Right justify rcNumber.left = rcNumber.right - surfaceMeasure->WidthText( - vsPrint.styles[STYLE_LINENUMBER].font, number); + vsPrint.styles[STYLE_LINENUMBER].font.get(), number); surface->FlushCachedState(); - surface->DrawTextNoClip(rcNumber, vsPrint.styles[STYLE_LINENUMBER].font, + surface->DrawTextNoClip(rcNumber, vsPrint.styles[STYLE_LINENUMBER].font.get(), static_cast<XYPOSITION>(ypos + vsPrint.maxAscent), number, vsPrint.styles[STYLE_LINENUMBER].fore, vsPrint.styles[STYLE_LINENUMBER].back); diff --git a/src/Editor.cxx b/src/Editor.cxx index f9bf5a582..7fa790469 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -1829,7 +1829,7 @@ long Editor::TextWidth(uptr_t style, const char *text) { RefreshStyleData(); AutoSurface surface(this); if (surface) { - return std::lround(surface->WidthText(vs.styles[style].font, text)); + return std::lround(surface->WidthText(vs.styles[style].font.get(), text)); } else { return 1; } diff --git a/src/LineMarker.cxx b/src/LineMarker.cxx index 286f334f5..861ae58aa 100644 --- a/src/LineMarker.cxx +++ b/src/LineMarker.cxx @@ -111,7 +111,7 @@ static void DrawMinus(Surface *surface, int centreX, int centreY, int armSize, C surface->FillRectangle(rcH, fore); } -void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharacter, FoldPart part, int marginStyle) const { +void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, const Font *fontForCharacter, FoldPart part, int marginStyle) const { if (customDraw) { customDraw(surface, rcWhole, fontForCharacter, static_cast<int>(part), marginStyle, this); return; diff --git a/src/LineMarker.h b/src/LineMarker.h index 4173f065e..468c53f13 100644 --- a/src/LineMarker.h +++ b/src/LineMarker.h @@ -13,7 +13,7 @@ namespace Scintilla { class XPM; class RGBAImage; -typedef void (*DrawLineMarkerFn)(Surface *surface, PRectangle &rcWhole, Font &fontForCharacter, int tFold, int marginStyle, const void *lineMarker); +typedef void (*DrawLineMarkerFn)(Surface *surface, PRectangle &rcWhole, const Font *fontForCharacter, int tFold, int marginStyle, const void *lineMarker); /** */ @@ -44,7 +44,7 @@ public: void SetXPM(const char *textForm); void SetXPM(const char *const *linesForm); void SetRGBAImage(Point sizeRGBAImage, float scale, const unsigned char *pixelsRGBAImage); - void Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharacter, FoldPart part, int marginStyle) const; + void Draw(Surface *surface, PRectangle &rcWhole, const Font *fontForCharacter, FoldPart part, int marginStyle) const; }; } diff --git a/src/MarginView.cxx b/src/MarginView.cxx index d2fb5f77d..27b057bd4 100644 --- a/src/MarginView.cxx +++ b/src/MarginView.cxx @@ -188,7 +188,7 @@ void MarginView::PaintMargin(Surface *surface, Sci::Line topLine, PRectangle rc, rcSelMargin.bottom = rc.bottom; const Point ptOrigin = model.GetVisibleOriginInMain(); - FontAlias fontLineNumber = vs.styles[STYLE_LINENUMBER].font; + const Font *fontLineNumber = vs.styles[STYLE_LINENUMBER].font.get(); for (size_t margin = 0; margin < vs.ms.size(); margin++) { if (vs.ms[margin].width > 0) { diff --git a/src/Platform.h b/src/Platform.h index 778c9a810..cd096af6b 100644 --- a/src/Platform.h +++ b/src/Platform.h @@ -81,7 +81,6 @@ namespace Scintilla { // 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 -typedef void *FontID; typedef void *SurfaceID; typedef void *WindowID; typedef void *MenuID; @@ -124,25 +123,16 @@ struct FontParameters { }; class Font { -protected: - FontID fid; public: - Font() noexcept; + Font() noexcept=default; // Deleted so Font objects can not be copied Font(const Font &) = delete; Font(Font &&) = delete; Font &operator=(const Font &) = delete; Font &operator=(Font &&) = delete; - virtual ~Font(); - - virtual void Create(const FontParameters &fp); - virtual void Release(); + virtual ~Font()=default; - FontID GetID() const noexcept { return fid; } - // Alias another font - caller guarantees not to Release - void SetID(FontID fid_) noexcept { fid = fid_; } - friend class Surface; - friend class SurfaceImpl; + static std::shared_ptr<Font> Allocate(const FontParameters &fp); }; class IScreenLine { @@ -206,16 +196,16 @@ public: virtual std::unique_ptr<IScreenLineLayout> Layout(const IScreenLine *screenLine) = 0; - virtual void DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, std::string_view text, ColourDesired fore, ColourDesired back) = 0; - virtual void DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, std::string_view text, ColourDesired fore, ColourDesired back) = 0; - virtual void DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, std::string_view text, ColourDesired fore) = 0; - virtual void MeasureWidths(Font &font_, std::string_view text, XYPOSITION *positions) = 0; - virtual XYPOSITION WidthText(Font &font_, std::string_view text) = 0; - virtual XYPOSITION Ascent(Font &font_)=0; - virtual XYPOSITION Descent(Font &font_)=0; - virtual XYPOSITION InternalLeading(Font &font_)=0; - virtual XYPOSITION Height(Font &font_)=0; - virtual XYPOSITION AverageCharWidth(Font &font_)=0; + virtual void DrawTextNoClip(PRectangle rc, const Font *font_, XYPOSITION ybase, std::string_view text, ColourDesired fore, ColourDesired back) = 0; + virtual void DrawTextClipped(PRectangle rc, const Font *font_, XYPOSITION ybase, std::string_view text, ColourDesired fore, ColourDesired back) = 0; + virtual void DrawTextTransparent(PRectangle rc, const Font *font_, XYPOSITION ybase, std::string_view text, ColourDesired fore) = 0; + virtual void MeasureWidths(const Font *font_, std::string_view text, XYPOSITION *positions) = 0; + virtual XYPOSITION WidthText(const Font *font_, std::string_view text) = 0; + virtual XYPOSITION Ascent(const Font *font_)=0; + virtual XYPOSITION Descent(const Font *font_)=0; + virtual XYPOSITION InternalLeading(const Font *font_)=0; + virtual XYPOSITION Height(const Font *font_)=0; + virtual XYPOSITION AverageCharWidth(const Font *font_)=0; virtual void SetClip(PRectangle rc)=0; virtual void FlushCachedState()=0; @@ -255,7 +245,7 @@ public: void Show(bool show=true); void InvalidateAll(); void InvalidateRectangle(PRectangle rc); - virtual void SetFont(Font &font); + virtual void SetFont(const Font *font); enum Cursor { cursorInvalid, cursorText, cursorArrow, cursorUp, cursorWait, cursorHoriz, cursorVert, cursorReverseArrow, cursorHand }; void SetCursor(Cursor curs); PRectangle GetMonitorRect(Point pt); @@ -286,7 +276,7 @@ public: ~ListBox() override; static ListBox *Allocate(); - void SetFont(Font &font) override =0; + void SetFont(const Font *font) override =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; diff --git a/src/PositionCache.cxx b/src/PositionCache.cxx index 55af2dabb..8665c19be 100644 --- a/src/PositionCache.cxx +++ b/src/PositionCache.cxx @@ -342,7 +342,7 @@ XYPOSITION ScreenLine::TabWidthMinimumPixels() const { } const Font *ScreenLine::FontOfPosition(size_t position) const { - return &ll->bidiData->stylesFonts[start + position]; + return ll->bidiData->stylesFonts[start + position].get(); } XYPOSITION ScreenLine::RepresentationWidth(size_t position) const { @@ -795,7 +795,7 @@ void PositionCache::MeasureWidths(Surface *surface, const ViewStyle &vstyle, uns probe = probe2; } } - FontAlias fontStyle = vstyle.styles[styleNumber].font; + const Font *fontStyle = vstyle.styles[styleNumber].font.get(); if (len > BreakFinder::lengthStartSubdivision) { // Break up into segments unsigned int startSegment = 0; diff --git a/src/PositionCache.h b/src/PositionCache.h index 7573a2dc3..8968092e7 100644 --- a/src/PositionCache.h +++ b/src/PositionCache.h @@ -46,7 +46,7 @@ enum PointEnd { class BidiData { public: - std::vector<FontAlias> stylesFonts; + std::vector<std::shared_ptr<Font>> stylesFonts; std::vector<XYPOSITION> widthReprs; void Resize(size_t maxLineLength_); }; diff --git a/src/ScintillaBase.cxx b/src/ScintillaBase.cxx index 4830357ed..b46a2207a 100644 --- a/src/ScintillaBase.cxx +++ b/src/ScintillaBase.cxx @@ -289,7 +289,7 @@ void ScintillaBase::AutoCompleteStart(Sci::Position lenEntered, const char *list rcac.right = rcac.left + widthLB; rcac.bottom = static_cast<XYPOSITION>(std::min(static_cast<int>(rcac.top) + heightLB, static_cast<int>(rcPopupBounds.bottom))); ac.lb->SetPositionRelative(rcac, &wMain); - ac.lb->SetFont(vs.styles[STYLE_DEFAULT].font); + ac.lb->SetFont(vs.styles[STYLE_DEFAULT].font.get()); const unsigned int aveCharWidth = static_cast<unsigned int>(vs.styles[STYLE_DEFAULT].aveCharWidth); ac.lb->SetAverageCharWidth(aveCharWidth); ac.lb->SetDelegate(this); diff --git a/src/Style.cxx b/src/Style.cxx index 5a3628e8f..85ac58738 100644 --- a/src/Style.cxx +++ b/src/Style.cxx @@ -18,31 +18,6 @@ using namespace Scintilla; -FontAlias::FontAlias() noexcept { -} - -FontAlias::FontAlias(const FontAlias &other) noexcept : Font() { - SetID(other.fid); -} - -FontAlias::FontAlias(FontAlias &&other) noexcept : Font() { - SetID(other.fid); - other.ClearFont(); -} - -FontAlias::~FontAlias() { - SetID(FontID{}); - // ~Font will not release the actual font resource since it is now 0 -} - -void FontAlias::MakeAlias(const Font &fontOrigin) noexcept { - SetID(fontOrigin.GetID()); -} - -void FontAlias::ClearFont() noexcept { - SetID(FontID{}); -} - bool FontSpecification::operator==(const FontSpecification &other) const noexcept { return fontName == other.fontName && weight == other.weight && @@ -148,7 +123,7 @@ void Style::Clear(ColourDesired fore_, ColourDesired back_, int size_, visible = visible_; changeable = changeable_; hotspot = hotspot_; - font.ClearFont(); + font.reset(); FontMeasurements::ClearMeasurements(); } @@ -169,7 +144,7 @@ void Style::ClearTo(const Style &source) noexcept { source.hotspot); } -void Style::Copy(const Font &font_, const FontMeasurements &fm_) noexcept { - font.MakeAlias(font_); +void Style::Copy(std::shared_ptr<Font> font_, const FontMeasurements &fm_) noexcept { + font = std::move(font_); (FontMeasurements &)(*this) = fm_; } diff --git a/src/Style.h b/src/Style.h index 071d752ca..769386359 100644 --- a/src/Style.h +++ b/src/Style.h @@ -29,20 +29,6 @@ struct FontSpecification { bool operator<(const FontSpecification &other) const noexcept; }; -// Just like Font but only has a copy of the FontID so should not delete it -class FontAlias : public Font { -public: - FontAlias() noexcept; - // FontAlias objects can be copy or move constructed but not be assigned - FontAlias(const FontAlias &) noexcept; - FontAlias(FontAlias &&) noexcept; - FontAlias &operator=(const FontAlias &) = delete; - FontAlias &operator=(FontAlias &&) = delete; - ~FontAlias() override; - void MakeAlias(const Font &fontOrigin) noexcept; - void ClearFont() noexcept; -}; - struct FontMeasurements { unsigned int ascent; unsigned int descent; @@ -68,7 +54,7 @@ public: bool changeable; bool hotspot; - FontAlias font; + std::shared_ptr<Font> font; Style(); Style(const Style &source) noexcept; @@ -83,7 +69,7 @@ public: bool underline_, ecaseForced caseForce_, bool visible_, bool changeable_, bool hotspot_) noexcept; void ClearTo(const Style &source) noexcept; - void Copy(const Font &font_, const FontMeasurements &fm_) noexcept; + void Copy(std::shared_ptr<Font> font_, const FontMeasurements &fm_) noexcept; bool IsProtected() const noexcept { return !(changeable && visible);} }; diff --git a/src/ViewStyle.cxx b/src/ViewStyle.cxx index d05e82749..0a3451026 100644 --- a/src/ViewStyle.cxx +++ b/src/ViewStyle.cxx @@ -37,7 +37,6 @@ MarginStyle::MarginStyle(int style_, int width_, int mask_) noexcept : FontRealised::FontRealised() noexcept = default; FontRealised::~FontRealised() { - font.Release(); } void FontRealised::Realise(Surface &surface, int zoomLevel, int technology, const FontSpecification &fs) { @@ -48,13 +47,13 @@ void FontRealised::Realise(Surface &surface, int zoomLevel, int technology, cons const float deviceHeight = static_cast<float>(surface.DeviceHeightFont(sizeZoomed)); const FontParameters fp(fs.fontName, deviceHeight / SC_FONT_SIZE_MULTIPLIER, fs.weight, fs.italic, fs.extraFontFlag, technology, fs.characterSet); - font.Create(fp); + font = Font::Allocate(fp); - ascent = static_cast<unsigned int>(surface.Ascent(font)); - descent = static_cast<unsigned int>(surface.Descent(font)); - capitalHeight = surface.Ascent(font) - surface.InternalLeading(font); - aveCharWidth = surface.AverageCharWidth(font); - spaceWidth = surface.WidthText(font, " "); + ascent = static_cast<unsigned int>(surface.Ascent(font.get())); + descent = static_cast<unsigned int>(surface.Descent(font.get())); + capitalHeight = surface.Ascent(font.get()) - surface.InternalLeading(font.get()); + aveCharWidth = surface.AverageCharWidth(font.get()); + spaceWidth = surface.WidthText(font.get(), " "); } ViewStyle::ViewStyle() : markers(MARKER_MAX + 1), indicators(INDICATOR_MAX + 1) { @@ -345,7 +344,7 @@ void ViewStyle::Refresh(Surface &surface, int tabInChars) { controlCharWidth = 0.0; if (controlCharSymbol >= 32) { const char cc[2] = { static_cast<char>(controlCharSymbol), '\0' }; - controlCharWidth = surface.WidthText(styles[STYLE_CONTROLCHAR].font, cc); + controlCharWidth = surface.WidthText(styles[STYLE_CONTROLCHAR].font.get(), cc); } CalculateMarginWidthAndMask(); diff --git a/src/ViewStyle.h b/src/ViewStyle.h index dc47ed380..b07c34a08 100644 --- a/src/ViewStyle.h +++ b/src/ViewStyle.h @@ -29,7 +29,7 @@ public: class FontRealised : public FontMeasurements { public: - Font font; + std::shared_ptr<Font> font; FontRealised() noexcept; // FontRealised objects can not be copied. FontRealised(const FontRealised &) = delete; diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx index 63c5a30ab..f63262cfe 100644 --- a/win32/PlatWin.cxx +++ b/win32/PlatWin.cxx @@ -152,85 +152,6 @@ bool LoadD2D() { #endif -struct FormatAndMetrics { - int technology; - HFONT hfont; -#if defined(USE_D2D) - IDWriteTextFormat *pTextFormat; -#endif - int extraFontFlag; - int characterSet; - FLOAT yAscent; - FLOAT yDescent; - FLOAT yInternalLeading; - FormatAndMetrics(HFONT hfont_, int extraFontFlag_, int characterSet_) noexcept : - technology(SCWIN_TECH_GDI), hfont(hfont_), -#if defined(USE_D2D) - pTextFormat(nullptr), -#endif - extraFontFlag(extraFontFlag_), characterSet(characterSet_), yAscent(2), yDescent(1), yInternalLeading(0) { - } -#if defined(USE_D2D) - FormatAndMetrics(IDWriteTextFormat *pTextFormat_, - int extraFontFlag_, - int characterSet_, - FLOAT yAscent_, - FLOAT yDescent_, - FLOAT yInternalLeading_) noexcept : - technology(SCWIN_TECH_DIRECTWRITE), - hfont{}, - pTextFormat(pTextFormat_), - extraFontFlag(extraFontFlag_), - characterSet(characterSet_), - yAscent(yAscent_), - yDescent(yDescent_), - yInternalLeading(yInternalLeading_) { - } -#endif - FormatAndMetrics(const FormatAndMetrics &) = delete; - FormatAndMetrics(FormatAndMetrics &&) = delete; - FormatAndMetrics &operator=(const FormatAndMetrics &) = delete; - FormatAndMetrics &operator=(FormatAndMetrics &&) = delete; - - ~FormatAndMetrics() { - if (hfont) - ::DeleteObject(hfont); -#if defined(USE_D2D) - ReleaseUnknown(pTextFormat); -#endif - extraFontFlag = 0; - characterSet = 0; - yAscent = 2; - yDescent = 1; - yInternalLeading = 0; - } - HFONT HFont() noexcept; -}; - -HFONT FormatAndMetrics::HFont() noexcept { - LOGFONTW lf = {}; -#if defined(USE_D2D) - if (technology == SCWIN_TECH_GDI) { - if (0 == ::GetObjectW(hfont, sizeof(lf), &lf)) { - return {}; - } - } else { - const HRESULT hr = pTextFormat->GetFontFamilyName(lf.lfFaceName, LF_FACESIZE); - if (!SUCCEEDED(hr)) { - return {}; - } - lf.lfWeight = pTextFormat->GetFontWeight(); - lf.lfItalic = pTextFormat->GetFontStyle() == DWRITE_FONT_STYLE_ITALIC; - lf.lfHeight = -static_cast<int>(pTextFormat->GetFontSize()); - } -#else - if (0 == ::GetObjectW(hfont, sizeof(lf), &lf)) { - return {}; - } -#endif - return ::CreateFontIndirectW(&lf); -} - #ifndef CLEARTYPE_QUALITY #define CLEARTYPE_QUALITY 5 #endif @@ -287,10 +208,6 @@ void LoadDpiForWindow() noexcept { HINSTANCE hinstPlatformRes {}; -FormatAndMetrics *FamFromFontID(void *fid) noexcept { - return static_cast<FormatAndMetrics *>(fid); -} - constexpr BYTE Win32MapFontQuality(int extraFontFlag) noexcept { switch (extraFontFlag & SC_EFF_QUALITY_MASK) { @@ -327,6 +244,11 @@ constexpr D2D1_TEXT_ANTIALIAS_MODE DWriteMapFontQuality(int extraFontFlag) noexc } #endif +// Both GDI and DirectWrite can produce a HFONT for use in list boxes +struct FontWin : public Font { + virtual HFONT HFont() const noexcept = 0; +}; + void SetLogFont(LOGFONTW &lf, const char *faceName, int characterSet, float size, int weight, bool italic, int extraFontFlag) { lf = LOGFONTW(); // The negative is to allow for leading @@ -338,16 +260,44 @@ void SetLogFont(LOGFONTW &lf, const char *faceName, int characterSet, float size UTF16FromUTF8(faceName, lf.lfFaceName, LF_FACESIZE); } -FontID CreateFontFromParameters(const FontParameters &fp) { - LOGFONTW lf; - SetLogFont(lf, fp.faceName, fp.characterSet, fp.size, fp.weight, fp.italic, fp.extraFontFlag); - FontID fid = nullptr; - if (fp.technology == SCWIN_TECH_GDI) { - HFONT hfont = ::CreateFontIndirectW(&lf); - fid = new FormatAndMetrics(hfont, fp.extraFontFlag, fp.characterSet); - } else { +struct FontGDI : public FontWin { + HFONT hfont = {}; + FontGDI(const FontParameters &fp) { + LOGFONTW lf; + SetLogFont(lf, fp.faceName, fp.characterSet, fp.size, fp.weight, fp.italic, fp.extraFontFlag); + hfont = ::CreateFontIndirectW(&lf); + } + // Deleted so FontGDI objects can not be copied. + FontGDI(const FontGDI &) = delete; + FontGDI(FontGDI &&) = delete; + FontGDI &operator=(const FontGDI &) = delete; + FontGDI &operator=(FontGDI &&) = delete; + ~FontGDI() { + if (hfont) + ::DeleteObject(hfont); + } + HFONT HFont() const noexcept override { + // Duplicating hfont + LOGFONTW lf = {}; + if (0 == ::GetObjectW(hfont, sizeof(lf), &lf)) { + return {}; + } + return ::CreateFontIndirectW(&lf); + } +}; + #if defined(USE_D2D) - IDWriteTextFormat *pTextFormat = nullptr; +struct FontDirectWrite : public FontWin { + IDWriteTextFormat *pTextFormat = nullptr; + int extraFontFlag = SC_EFF_QUALITY_DEFAULT; + int characterSet = 0; + FLOAT yAscent = 2.0f; + FLOAT yDescent = 1.0f; + FLOAT yInternalLeading = 0.0f; + + FontDirectWrite(const FontParameters &fp) : + extraFontFlag(fp.extraFontFlag), + characterSet(fp.characterSet) { const std::wstring wsFace = WStringFromUTF8(fp.faceName); const FLOAT fHeight = fp.size; const DWRITE_FONT_STYLE style = fp.italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL; @@ -358,9 +308,6 @@ FontID CreateFontFromParameters(const FontParameters &fp) { if (SUCCEEDED(hr)) { pTextFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP); - FLOAT yAscent = 1.0f; - FLOAT yDescent = 1.0f; - FLOAT yInternalLeading = 0.0f; IDWriteTextLayout *pTextLayout = nullptr; hr = pIDWriteFactory->CreateTextLayout(L"X", 1, pTextFormat, 100.0f, 100.0f, &pTextLayout); @@ -382,31 +329,39 @@ FontID CreateFontFromParameters(const FontParameters &fp) { ReleaseUnknown(pTextLayout); pTextFormat->SetLineSpacing(DWRITE_LINE_SPACING_METHOD_UNIFORM, lineMetrics[0].height, lineMetrics[0].baseline); } - fid = new FormatAndMetrics(pTextFormat, fp.extraFontFlag, fp.characterSet, yAscent, yDescent, yInternalLeading); } -#endif } - return fid; -} - -} - -Font::Font() noexcept : fid{} { -} - -Font::~Font() { -} + // Deleted so FontDirectWrite objects can not be copied. + FontDirectWrite(const FontDirectWrite &) = delete; + FontDirectWrite(FontDirectWrite &&) = delete; + FontDirectWrite &operator=(const FontDirectWrite &) = delete; + FontDirectWrite &operator=(FontDirectWrite &&) = delete; + ~FontDirectWrite() { + ReleaseUnknown(pTextFormat); + } + HFONT HFont() const noexcept override { + LOGFONTW lf = {}; + const HRESULT hr = pTextFormat->GetFontFamilyName(lf.lfFaceName, LF_FACESIZE); + if (!SUCCEEDED(hr)) { + return {}; + } + lf.lfWeight = pTextFormat->GetFontWeight(); + lf.lfItalic = pTextFormat->GetFontStyle() == DWRITE_FONT_STYLE_ITALIC; + lf.lfHeight = -static_cast<int>(pTextFormat->GetFontSize()); + return ::CreateFontIndirectW(&lf); + } +}; +#endif -void Font::Create(const FontParameters &fp) { - Release(); - if (fp.faceName) - fid = CreateFontFromParameters(fp); } -void Font::Release() { - if (fid) - delete FamFromFontID(fid); - fid = nullptr; +std::shared_ptr<Font> Font::Allocate(const FontParameters &fp) { +#if defined(USE_D2D) + if (fp.technology == SCWIN_TECH_DIRECTWRITE) { + return std::make_shared<FontDirectWrite>(fp); + } +#endif + return std::make_shared<FontGDI>(fp); } // Buffer to hold strings and string position arrays without always allocating on heap. @@ -501,7 +456,7 @@ class SurfaceGDI : public Surface { int codePage = 0; void BrushColour(ColourDesired back) noexcept; - void SetFont(const Font &font_) noexcept; + void SetFont(const Font *font_) noexcept; void Clear() noexcept; public: @@ -539,17 +494,17 @@ public: std::unique_ptr<IScreenLineLayout> Layout(const IScreenLine *screenLine) override; - void DrawTextCommon(PRectangle rc, const Font &font_, XYPOSITION ybase, std::string_view text, UINT fuOptions); - void DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, std::string_view text, ColourDesired fore, ColourDesired back) override; - void DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, std::string_view text, ColourDesired fore, ColourDesired back) override; - void DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, std::string_view text, ColourDesired fore) override; - void MeasureWidths(Font &font_, std::string_view text, XYPOSITION *positions) override; - XYPOSITION WidthText(Font &font_, std::string_view text) override; - XYPOSITION Ascent(Font &font_) override; - XYPOSITION Descent(Font &font_) override; - XYPOSITION InternalLeading(Font &font_) override; - XYPOSITION Height(Font &font_) override; - XYPOSITION AverageCharWidth(Font &font_) override; + void DrawTextCommon(PRectangle rc, const Font *font_, XYPOSITION ybase, std::string_view text, UINT fuOptions); + void DrawTextNoClip(PRectangle rc, const Font *font_, XYPOSITION ybase, std::string_view text, ColourDesired fore, ColourDesired back) override; + void DrawTextClipped(PRectangle rc, const Font *font_, XYPOSITION ybase, std::string_view text, ColourDesired fore, ColourDesired back) override; + void DrawTextTransparent(PRectangle rc, const Font *font_, XYPOSITION ybase, std::string_view text, ColourDesired fore) override; + void MeasureWidths(const Font *font_, std::string_view text, XYPOSITION *positions) override; + XYPOSITION WidthText(const Font *font_, std::string_view text) override; + XYPOSITION Ascent(const Font *font_) override; + XYPOSITION Descent(const Font *font_) override; + XYPOSITION InternalLeading(const Font *font_) override; + XYPOSITION Height(const Font *font_) override; + XYPOSITION AverageCharWidth(const Font *font_) override; void SetClip(PRectangle rc) override; void FlushCachedState() override; @@ -659,9 +614,9 @@ void SurfaceGDI::BrushColour(ColourDesired back) noexcept { brushOld = SelectBrush(hdc, brush); } -void SurfaceGDI::SetFont(const Font &font_) noexcept { - const FormatAndMetrics *pfm = FamFromFontID(font_.GetID()); - PLATFORM_ASSERT(pfm->technology == SCWIN_TECH_GDI); +void SurfaceGDI::SetFont(const Font *font_) noexcept { + const FontGDI *pfm = dynamic_cast<const FontGDI *>(font_); + PLATFORM_ASSERT(pfm); if (fontOld) { SelectFont(hdc, pfm->hfont); } else { @@ -989,7 +944,7 @@ std::unique_ptr<IScreenLineLayout> SurfaceGDI::Layout(const IScreenLine *) { typedef VarBuffer<int, stackBufferLength> TextPositionsI; -void SurfaceGDI::DrawTextCommon(PRectangle rc, const Font &font_, XYPOSITION ybase, std::string_view text, UINT fuOptions) { +void SurfaceGDI::DrawTextCommon(PRectangle rc, const Font *font_, XYPOSITION ybase, std::string_view text, UINT fuOptions) { SetFont(font_); const RECT rcw = RectFromPRectangle(rc); const int x = static_cast<int>(rc.left); @@ -1003,21 +958,21 @@ void SurfaceGDI::DrawTextCommon(PRectangle rc, const Font &font_, XYPOSITION yba } } -void SurfaceGDI::DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, std::string_view text, +void SurfaceGDI::DrawTextNoClip(PRectangle rc, const Font *font_, XYPOSITION ybase, std::string_view text, ColourDesired fore, ColourDesired back) { ::SetTextColor(hdc, fore.AsInteger()); ::SetBkColor(hdc, back.AsInteger()); DrawTextCommon(rc, font_, ybase, text, ETO_OPAQUE); } -void SurfaceGDI::DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, std::string_view text, +void SurfaceGDI::DrawTextClipped(PRectangle rc, const Font *font_, XYPOSITION ybase, std::string_view text, ColourDesired fore, ColourDesired back) { ::SetTextColor(hdc, fore.AsInteger()); ::SetBkColor(hdc, back.AsInteger()); DrawTextCommon(rc, font_, ybase, text, ETO_OPAQUE | ETO_CLIPPED); } -void SurfaceGDI::DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, std::string_view text, +void SurfaceGDI::DrawTextTransparent(PRectangle rc, const Font *font_, XYPOSITION ybase, std::string_view text, ColourDesired fore) { // Avoid drawing spaces in transparent mode for (const char ch : text) { @@ -1031,7 +986,7 @@ void SurfaceGDI::DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybas } } -XYPOSITION SurfaceGDI::WidthText(Font &font_, std::string_view text) { +XYPOSITION SurfaceGDI::WidthText(const Font *font_, std::string_view text) { SetFont(font_); SIZE sz={0,0}; if (!unicodeMode) { @@ -1043,7 +998,7 @@ XYPOSITION SurfaceGDI::WidthText(Font &font_, std::string_view text) { return static_cast<XYPOSITION>(sz.cx); } -void SurfaceGDI::MeasureWidths(Font &font_, std::string_view text, XYPOSITION *positions) { +void SurfaceGDI::MeasureWidths(const Font *font_, std::string_view text, XYPOSITION *positions) { // Zero positions to avoid random behaviour on failure. std::fill(positions, positions + text.length(), 0.0f); SetFont(font_); @@ -1085,35 +1040,35 @@ void SurfaceGDI::MeasureWidths(Font &font_, std::string_view text, XYPOSITION *p std::fill(positions+i, positions + text.length(), lastPos); } -XYPOSITION SurfaceGDI::Ascent(Font &font_) { +XYPOSITION SurfaceGDI::Ascent(const Font *font_) { SetFont(font_); TEXTMETRIC tm; ::GetTextMetrics(hdc, &tm); return static_cast<XYPOSITION>(tm.tmAscent); } -XYPOSITION SurfaceGDI::Descent(Font &font_) { +XYPOSITION SurfaceGDI::Descent(const Font *font_) { SetFont(font_); TEXTMETRIC tm; ::GetTextMetrics(hdc, &tm); return static_cast<XYPOSITION>(tm.tmDescent); } -XYPOSITION SurfaceGDI::InternalLeading(Font &font_) { +XYPOSITION SurfaceGDI::InternalLeading(const Font *font_) { SetFont(font_); TEXTMETRIC tm; ::GetTextMetrics(hdc, &tm); return static_cast<XYPOSITION>(tm.tmInternalLeading); } -XYPOSITION SurfaceGDI::Height(Font &font_) { +XYPOSITION SurfaceGDI::Height(const Font *font_) { SetFont(font_); TEXTMETRIC tm; ::GetTextMetrics(hdc, &tm); return static_cast<XYPOSITION>(tm.tmHeight); } -XYPOSITION SurfaceGDI::AverageCharWidth(Font &font_) { +XYPOSITION SurfaceGDI::AverageCharWidth(const Font *font_) { SetFont(font_); TEXTMETRIC tm; ::GetTextMetrics(hdc, &tm); @@ -1176,7 +1131,7 @@ class SurfaceD2D : public Surface { int logPixelsY; void Clear() noexcept; - void SetFont(const Font &font_) noexcept; + void SetFont(const Font *font_) noexcept; HRESULT GetBitmap(ID2D1Bitmap **ppBitmap); public: @@ -1218,17 +1173,17 @@ public: std::unique_ptr<IScreenLineLayout> Layout(const IScreenLine *screenLine) override; - void DrawTextCommon(PRectangle rc, const Font &font_, XYPOSITION ybase, std::string_view text, UINT fuOptions); - void DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, std::string_view text, ColourDesired fore, ColourDesired back) override; - void DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, std::string_view text, ColourDesired fore, ColourDesired back) override; - void DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, std::string_view text, ColourDesired fore) override; - void MeasureWidths(Font &font_, std::string_view text, XYPOSITION *positions) override; - XYPOSITION WidthText(Font &font_, std::string_view text) override; - XYPOSITION Ascent(Font &font_) override; - XYPOSITION Descent(Font &font_) override; - XYPOSITION InternalLeading(Font &font_) override; - XYPOSITION Height(Font &font_) override; - XYPOSITION AverageCharWidth(Font &font_) override; + void DrawTextCommon(PRectangle rc, const Font *font_, XYPOSITION ybase, std::string_view text, UINT fuOptions); + void DrawTextNoClip(PRectangle rc, const Font *font_, XYPOSITION ybase, std::string_view text, ColourDesired fore, ColourDesired back) override; + void DrawTextClipped(PRectangle rc, const Font *font_, XYPOSITION ybase, std::string_view text, ColourDesired fore, ColourDesired back) override; + void DrawTextTransparent(PRectangle rc, const Font *font_, XYPOSITION ybase, std::string_view text, ColourDesired fore) override; + void MeasureWidths(const Font *font_, std::string_view text, XYPOSITION *positions) override; + XYPOSITION WidthText(const Font *font_, std::string_view text) override; + XYPOSITION Ascent(const Font *font_) override; + XYPOSITION Descent(const Font *font_) override; + XYPOSITION InternalLeading(const Font *font_) override; + XYPOSITION Height(const Font *font_) override; + XYPOSITION AverageCharWidth(const Font *font_) override; void SetClip(PRectangle rc) override; void FlushCachedState() override; @@ -1361,9 +1316,9 @@ void SurfaceD2D::D2DPenColour(ColourDesired fore, int alpha) { } } -void SurfaceD2D::SetFont(const Font &font_) noexcept { - const FormatAndMetrics *pfm = FamFromFontID(font_.GetID()); - PLATFORM_ASSERT(pfm->technology == SCWIN_TECH_DIRECTWRITE); +void SurfaceD2D::SetFont(const Font *font_) noexcept { + const FontDirectWrite *pfm = dynamic_cast<const FontDirectWrite *>(font_); + PLATFORM_ASSERT(pfm); pTextFormat = pfm->pTextFormat; yAscent = pfm->yAscent; yDescent = pfm->yDescent; @@ -1830,8 +1785,8 @@ void ScreenLineLayout::FillTextLayoutFormats(const IScreenLine *screenLine, IDWr textLayout->SetInlineObject(&blobs.back(), textRange); }; - FormatAndMetrics *pfm = - static_cast<FormatAndMetrics *>(screenLine->FontOfPosition(bytePosition)->GetID()); + const FontDirectWrite *pfm = + dynamic_cast<const FontDirectWrite *>(screenLine->FontOfPosition(bytePosition)); const unsigned int fontFamilyNameSize = pfm->pTextFormat->GetFontFamilyNameLength(); std::wstring fontFamilyName(fontFamilyNameSize, 0); @@ -1888,7 +1843,7 @@ ScreenLineLayout::ScreenLineLayout(const IScreenLine *screenLine) { text = screenLine->Text(); // Get textFormat - FormatAndMetrics *pfm = static_cast<FormatAndMetrics *>(screenLine->FontOfPosition(0)->GetID()); + const FontDirectWrite *pfm = dynamic_cast<const FontDirectWrite *>(screenLine->FontOfPosition(0)); if (!pIDWriteFactory || !pfm->pTextFormat) { return; @@ -2058,7 +2013,7 @@ std::unique_ptr<IScreenLineLayout> SurfaceD2D::Layout(const IScreenLine *screenL return std::make_unique<ScreenLineLayout>(screenLine); } -void SurfaceD2D::DrawTextCommon(PRectangle rc, const Font &font_, XYPOSITION ybase, std::string_view text, UINT fuOptions) { +void SurfaceD2D::DrawTextCommon(PRectangle rc, const Font *font_, XYPOSITION ybase, std::string_view text, UINT fuOptions) { SetFont(font_); // Use Unicode calls @@ -2085,7 +2040,7 @@ void SurfaceD2D::DrawTextCommon(PRectangle rc, const Font &font_, XYPOSITION yba } } -void SurfaceD2D::DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, std::string_view text, +void SurfaceD2D::DrawTextNoClip(PRectangle rc, const Font *font_, XYPOSITION ybase, std::string_view text, ColourDesired fore, ColourDesired back) { if (pRenderTarget) { FillRectangle(rc, back); @@ -2094,7 +2049,7 @@ void SurfaceD2D::DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, st } } -void SurfaceD2D::DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, std::string_view text, +void SurfaceD2D::DrawTextClipped(PRectangle rc, const Font *font_, XYPOSITION ybase, std::string_view text, ColourDesired fore, ColourDesired back) { if (pRenderTarget) { FillRectangle(rc, back); @@ -2103,7 +2058,7 @@ void SurfaceD2D::DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, s } } -void SurfaceD2D::DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, std::string_view text, +void SurfaceD2D::DrawTextTransparent(PRectangle rc, const Font *font_, XYPOSITION ybase, std::string_view text, ColourDesired fore) { // Avoid drawing spaces in transparent mode for (const char ch : text) { @@ -2117,7 +2072,7 @@ void SurfaceD2D::DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybas } } -XYPOSITION SurfaceD2D::WidthText(Font &font_, std::string_view text) { +XYPOSITION SurfaceD2D::WidthText(const Font *font_, std::string_view text) { FLOAT width = 1.0; SetFont(font_); const TextWide tbuf(text, unicodeMode, codePageText); @@ -2135,7 +2090,7 @@ XYPOSITION SurfaceD2D::WidthText(Font &font_, std::string_view text) { return width; } -void SurfaceD2D::MeasureWidths(Font &font_, std::string_view text, XYPOSITION *positions) { +void SurfaceD2D::MeasureWidths(const Font *font_, std::string_view text, XYPOSITION *positions) { SetFont(font_); if (!pIDWriteFactory || !pTextFormat) { // SetFont failed or no access to DirectWrite so give up. @@ -2216,26 +2171,26 @@ void SurfaceD2D::MeasureWidths(Font &font_, std::string_view text, XYPOSITION *p } } -XYPOSITION SurfaceD2D::Ascent(Font &font_) { +XYPOSITION SurfaceD2D::Ascent(const Font *font_) { SetFont(font_); return std::ceil(yAscent); } -XYPOSITION SurfaceD2D::Descent(Font &font_) { +XYPOSITION SurfaceD2D::Descent(const Font *font_) { SetFont(font_); return std::ceil(yDescent); } -XYPOSITION SurfaceD2D::InternalLeading(Font &font_) { +XYPOSITION SurfaceD2D::InternalLeading(const Font *font_) { SetFont(font_); return std::floor(yInternalLeading); } -XYPOSITION SurfaceD2D::Height(Font &font_) { +XYPOSITION SurfaceD2D::Height(const Font *font_) { return Ascent(font_) + Descent(font_); } -XYPOSITION SurfaceD2D::AverageCharWidth(Font &font_) { +XYPOSITION SurfaceD2D::AverageCharWidth(const Font *font_) { FLOAT width = 1.0; SetFont(font_); if (pIDWriteFactory && pTextFormat) { @@ -2386,8 +2341,9 @@ void Window::InvalidateRectangle(PRectangle rc) { ::InvalidateRect(HwndFromWindowID(wid), &rcw, FALSE); } -void Window::SetFont(Font &font) { - SetWindowFont(HwndFromWindowID(wid), font.GetID(), 0); +void Window::SetFont(const Font *font) { + const FontWin *pfm = dynamic_cast<const FontWin *>(font); + SetWindowFont(HwndFromWindowID(wid), pfm->HFont(), 0); } namespace { @@ -2541,7 +2497,7 @@ ListBox::~ListBox() { class ListBoxX : public ListBox { int lineHeight; - FontID fontCopy; + HFONT fontCopy; int technology; RGBAImageSet images; LineToItem lti; @@ -2598,7 +2554,7 @@ public: fontCopy = 0; } } - void SetFont(Font &font) override; + void SetFont(const Font *font) override; void Create(Window &parent_, int ctrlID_, Point location_, int lineHeight_, bool unicodeMode_, int technology_) override; void SetAverageCharWidth(int width) override; void SetVisibleRows(int rows) override; @@ -2651,13 +2607,13 @@ void ListBoxX::Create(Window &parent_, int ctrlID_, Point location_, int lineHei location = PointFromPOINT(locationw); } -void ListBoxX::SetFont(Font &font) { - if (font.GetID()) { +void ListBoxX::SetFont(const Font *font) { + const FontWin *pfm = dynamic_cast<const FontWin *>(font); + if (pfm) { if (fontCopy) { ::DeleteObject(fontCopy); fontCopy = 0; } - FormatAndMetrics *pfm = static_cast<FormatAndMetrics *>(font.GetID()); fontCopy = pfm->HFont(); SetWindowFont(lb, fontCopy, 0); } |