4#include "Stroika/Frameworks/StroikaPreComp.h"
8#include "StandardStyledTextImager.h"
12using Memory::MakeSharedPtr;
14using namespace Stroika::Frameworks;
15using namespace Stroika::Frameworks::Led;
22#if qStroika_Foundation_Debug_AssertionsChecked
23void AbstractStyleDatabaseRep::Invariant_ ()
const
33#if qStroika_Frameworks_Led_SupportGDI
34void StandardStyleMarker::DrawSegment (
const StyledTextImager* imager,
const StyleRunElement& , Tablet* tablet,
size_t from,
35 size_t to,
const TextLayoutBlock& text,
const Led_Rect& drawInto,
const Led_Rect& ,
36 CoordinateType useBaseLine, DistanceType* pixelsDrawn)
39 imager->DrawSegment_ (tablet, fFontSpecification, from, to, text, drawInto, useBaseLine, pixelsDrawn);
42void StandardStyleMarker::MeasureSegmentWidth (
const StyledTextImager* imager,
const StyleRunElement& ,
size_t from,
43 size_t to,
const Led_tChar* text, DistanceType* distanceResults)
const
46 imager->MeasureSegmentWidth_ (fFontSpecification, from, to, text, distanceResults);
49DistanceType StandardStyleMarker::MeasureSegmentHeight (
const StyledTextImager* imager,
const StyleRunElement& ,
size_t from,
size_t to)
const
52 return (imager->MeasureSegmentHeight_ (fFontSpecification, from, to));
55DistanceType StandardStyleMarker::MeasureSegmentBaseLine (
const StyledTextImager* imager,
const StyleRunElement& ,
size_t from,
size_t to)
const
58 return (imager->MeasureSegmentBaseLine_ (fFontSpecification, from, to));
67StyleDatabaseRep::StyleDatabaseRep (TextStore& textStore)
68 : inheritedMC{textStore, GetStaticDefaultFont ()}
72vector<StyledInfoSummaryRecord> StyleDatabaseRep::GetStyleInfo (
size_t charAfterPos,
size_t nTCharsFollowing)
const
74 MarkerVector standardStyleMarkers = GetInfoMarkers (charAfterPos, nTCharsFollowing);
76 vector<StyledInfoSummaryRecord> result;
77 size_t tCharsSoFar = 0;
78 size_t nStandardStyleMarkers = standardStyleMarkers.size ();
79 for (
size_t i = 0; i < nStandardStyleMarkers; ++i) {
80 StandardStyleMarker* marker = standardStyleMarkers[i];
84 marker->GetRange (&markerStart, &markerEnd);
88 size_t length = markerEnd - markerStart;
90 Assert (charAfterPos >= markerStart);
91 Assert (charAfterPos - markerStart < length);
92 length -= (charAfterPos - markerStart);
94 if (i == nStandardStyleMarkers - 1) {
95 Assert (length >= nTCharsFollowing - tCharsSoFar);
96 length = nTCharsFollowing - tCharsSoFar;
98 Assert (length > 0 or nTCharsFollowing == 0);
99 Assert (length <= nTCharsFollowing);
100 result.push_back (StyledInfoSummaryRecord (marker->fFontSpecification, length));
101 tCharsSoFar += length;
103 Assert (tCharsSoFar == nTCharsFollowing);
107void StyleDatabaseRep::SetStyleInfo (
size_t charAfterPos,
size_t nTCharsFollowing,
const IncrementalFontSpecification& styleInfo)
109 SetInfo (charAfterPos, nTCharsFollowing, styleInfo);
112void StyleDatabaseRep::SetStyleInfo (
size_t charAfterPos,
size_t nTCharsFollowing,
size_t nStyleInfos,
const StyledInfoSummaryRecord* styleInfos)
114 size_t setAt = charAfterPos;
115 size_t lengthUsedSoFar = 0;
116 for (
size_t i = 0; i < nStyleInfos and lengthUsedSoFar < nTCharsFollowing; ++i) {
117 StyledInfoSummaryRecord isr = styleInfos[i];
118 size_t length = isr.fLength;
119 Assert (nTCharsFollowing >= lengthUsedSoFar);
120 length = min (nTCharsFollowing - lengthUsedSoFar, length);
121 SetStyleInfo (setAt, length, IncrementalFontSpecification{isr});
123 lengthUsedSoFar += length;
127#if qStroika_Foundation_Debug_AssertionsChecked
128void StyleDatabaseRep::Invariant_ ()
const
130 inheritedMC::Invariant_ ();
134#if qStroika_Frameworks_Led_SupportGDI
140void StandardStyledTextImager::HookLosingTextStore ()
142 inherited::HookLosingTextStore ();
143 HookLosingTextStore_ ();
146void StandardStyledTextImager::HookLosingTextStore_ ()
149 if (fICreatedDatabase) {
150 fICreatedDatabase =
false;
151 if (fStyleDatabase.get () !=
nullptr) {
152 fStyleDatabase =
nullptr;
153 HookStyleDatabaseChanged ();
158void StandardStyledTextImager::HookGainedNewTextStore ()
160 inherited::HookGainedNewTextStore ();
161 HookGainedNewTextStore_ ();
164void StandardStyledTextImager::HookGainedNewTextStore_ ()
166 if (fStyleDatabase ==
nullptr) {
167 fStyleDatabase = MakeSharedPtr<StyleDatabaseRep> (GetTextStore ());
168 fICreatedDatabase =
true;
169 HookStyleDatabaseChanged ();
173void StandardStyledTextImager::SetStyleDatabase (
const shared_ptr<AbstractStyleDatabaseRep>& styleDatabase)
175 fStyleDatabase = styleDatabase;
176 fICreatedDatabase =
false;
177 if (fStyleDatabase ==
nullptr and PeekAtTextStore () !=
nullptr) {
178 fStyleDatabase = MakeSharedPtr<StyleDatabaseRep> (GetTextStore ());
179 fICreatedDatabase =
true;
181 HookStyleDatabaseChanged ();
190void StandardStyledTextImager::HookStyleDatabaseChanged ()
194FontMetrics StandardStyledTextImager::GetFontMetricsAt (
size_t charAfterPos)
const
196 Tablet_Acquirer tablet (
this);
199 FontCacheInfoUpdater fontCacheUpdater (
this, tablet, GetStyleInfo (charAfterPos));
200 return (fontCacheUpdater.GetMetrics ());
209 vector<StyledInfoSummaryRecord> summaryInfo = GetStyleInfo (GetSelectionEnd (), 0);
210 Assert (summaryInfo.size () == 1);
211 return summaryInfo[0];
222IncrementalFontSpecification StandardStyledTextImager::GetContinuousStyleInfo (
size_t from,
size_t nTChars)
const
224 vector<StyledInfoSummaryRecord> summaryInfo = GetStyleInfo (from, nTChars);
225 return (GetContinuousStyleInfo_ (summaryInfo));
228IncrementalFontSpecification StandardStyledTextImager::GetContinuousStyleInfo_ (
const vector<StyledInfoSummaryRecord>& summaryInfo)
const
230 IncrementalFontSpecification fontSpec;
241 int countOfValidThings = 7 +
242#if qStroika_Foundation_Common_Platform_MacOS
244#elif qStroika_Foundation_Common_Platform_Windows
246#elif qStroika_FeatureSupported_XWindows
251 for (
size_t i = 0; i < summaryInfo.size (); ++i) {
253 fontSpec = IncrementalFontSpecification{summaryInfo[0]};
258 StyledInfoSummaryRecord isr = summaryInfo[i];
261 if (fontSpec.GetFontNameSpecifier_Valid () and fontSpec.GetFontNameSpecifier () != isr.GetFontNameSpecifier ()) {
262 fontSpec.InvalidateFontNameSpecifier ();
263 if (--countOfValidThings == 0) {
269 if (fontSpec.GetStyle_Bold_Valid () and fontSpec.GetStyle_Bold () != isr.GetStyle_Bold ()) {
270 fontSpec.InvalidateStyle_Bold ();
271 if (--countOfValidThings == 0) {
275 if (fontSpec.GetStyle_Italic_Valid () and fontSpec.GetStyle_Italic () != isr.GetStyle_Italic ()) {
276 fontSpec.InvalidateStyle_Italic ();
277 if (--countOfValidThings == 0) {
281 if (fontSpec.GetStyle_Underline_Valid () and fontSpec.GetStyle_Underline () != isr.GetStyle_Underline ()) {
282 fontSpec.InvalidateStyle_Underline ();
283 if (--countOfValidThings == 0) {
287 if (fontSpec.GetStyle_SubOrSuperScript_Valid () and fontSpec.GetStyle_SubOrSuperScript () != isr.GetStyle_SubOrSuperScript ()) {
288 fontSpec.InvalidateStyle_SubOrSuperScript ();
289 if (--countOfValidThings == 0) {
293#if qStroika_Foundation_Common_Platform_MacOS
294 if (fontSpec.GetStyle_Outline_Valid () and fontSpec.GetStyle_Outline () != isr.GetStyle_Outline ()) {
295 fontSpec.InvalidateStyle_Outline ();
296 if (--countOfValidThings == 0) {
300 if (fontSpec.GetStyle_Shadow_Valid () and fontSpec.GetStyle_Shadow () != isr.GetStyle_Shadow ()) {
301 fontSpec.InvalidateStyle_Shadow ();
302 if (--countOfValidThings == 0) {
306 if (fontSpec.GetStyle_Condensed_Valid () and fontSpec.GetStyle_Condensed () != isr.GetStyle_Condensed ()) {
307 fontSpec.InvalidateStyle_Condensed ();
308 if (--countOfValidThings == 0) {
312 if (fontSpec.GetStyle_Extended_Valid () and fontSpec.GetStyle_Extended () != isr.GetStyle_Extended ()) {
313 fontSpec.InvalidateStyle_Extended ();
314 if (--countOfValidThings == 0) {
318#elif qStroika_Foundation_Common_Platform_Windows
319 if (fontSpec.GetStyle_Strikeout_Valid () and fontSpec.GetStyle_Strikeout () != isr.GetStyle_Strikeout ()) {
320 fontSpec.InvalidateStyle_Strikeout ();
321 if (--countOfValidThings == 0) {
328 if (fontSpec.GetPointSize_Valid () and fontSpec.GetPointSize () != isr.GetPointSize ()) {
329 fontSpec.InvalidatePointSize ();
330 if (--countOfValidThings == 0) {
336 if (fontSpec.GetTextColor_Valid () and fontSpec.GetTextColor () != isr.GetTextColor ()) {
337 fontSpec.InvalidateTextColor ();
338 if (--countOfValidThings == 0) {
348#if qStroika_Foundation_Common_Platform_MacOS
349bool StandardStyledTextImager::DoContinuousStyle_Mac (
size_t from,
size_t nTChars,
short* mode, TextStyle* theStyle)
353 Require ((*mode & addSize) == 0);
356 unsigned int resultMode = *mode;
357 IncrementalFontSpecification resultSpec = GetContinuousStyleInfo (from, nTChars);
358 if (resultMode & doFont) {
359 resultSpec.GetOSRep (&theStyle->tsFont,
nullptr,
nullptr);
361 if (resultMode & doFace) {
362 resultSpec.GetOSRep (
nullptr,
nullptr, &theStyle->tsFace);
364 if (resultMode & doSize) {
365 resultSpec.GetOSRep (
nullptr, &theStyle->tsSize,
nullptr);
368 bool result = (resultMode != *mode);
373vector<StyledInfoSummaryRecord> StandardStyledTextImager::Convert (
const ScrpSTElement* teScrapFmt,
size_t nElts)
375 vector<StyledInfoSummaryRecord> result;
376 for (
size_t i = 0; i < nElts; ++i) {
377 IncrementalFontSpecification fsp;
378 fsp.SetOSRep (teScrapFmt[i].scrpFont, teScrapFmt[i].scrpSize, teScrapFmt[i].scrpFace);
379 size_t length = (i < (nElts - 1)) ? (teScrapFmt[i + 1].scrpStartChar - teScrapFmt[i].scrpStartChar) : 9999999;
380 StyledInfoSummaryRecord isr (fsp, length);
381 result.push_back (isr);
386void StandardStyledTextImager::Convert (
const vector<StyledInfoSummaryRecord>& fromLedStyleRuns, ScrpSTElement* teScrapFmt)
388 size_t nElts = fromLedStyleRuns.size ();
389 size_t startChar = 0;
391 GrafPtr oldPort = Led_GetCurrentGDIPort ();
393 CGrafPtr tmpPort = ::CreateNewPort ();
397 ::OpenCPort (&tmpPort);
400 for (
size_t i = 0; i < nElts; ++i) {
401 StyledInfoSummaryRecord isr = fromLedStyleRuns[i];
403 (void)::memset (&teScrapFmt[i], 0,
sizeof (teScrapFmt[i]));
404 teScrapFmt[i].scrpStartChar = startChar;
406 isr.GetOSRep (&teScrapFmt[i].scrpFont, &teScrapFmt[i].scrpSize, &teScrapFmt[i].scrpFace);
408 ::TextFont (teScrapFmt[i].scrpFont);
409 ::TextFace (teScrapFmt[i].scrpFace);
410 ::TextSize (teScrapFmt[i].scrpSize);
413 ::GetFontInfo (&info);
415 teScrapFmt[i].scrpHeight = info.ascent + info.descent + info.leading;
416 teScrapFmt[i].scrpAscent = info.ascent;
418 startChar += isr.fLength;
422 ::DisposePort (tmpPort);
424 ::CloseCPort (&tmpPort);
430#if qStroika_Foundation_Debug_AssertionsChecked
431void StandardStyledTextImager::Invariant_ ()
const
433 StyledTextImager::Invariant_ ();
434 if (fStyleDatabase.get () !=
nullptr) {
435 fStyleDatabase->Invariant ();
#define RequireNotNull(p)