From a888218a3440c9ba77b86cef35a5ae5198a774bf Mon Sep 17 00:00:00 2001 From: vczh Date: Wed, 28 Jan 2026 18:48:25 -0800 Subject: [PATCH] Update release --- Import/GacUI.UnitTest.UI.cpp | 409 +++-- Import/GacUI.UnitTest.cpp | 1400 +++++++++++++++++ Import/GacUI.UnitTest.h | 1037 +++--------- Import/GacUI.cpp | 635 +++++--- Import/GacUI.h | 105 +- Import/GacUICompiler.cpp | 403 +++-- Import/GacUICompiler.h | 34 +- Import/GacUIReflection.cpp | 2 +- Import/Metadata/RemoteProtocol.json | 143 +- .../Protocol_Renderer_Document.txt | 33 +- .../RemoteProtocol/Protocol_UnitTest.txt | 8 +- Tools/Reflection32.bin | Bin 957176 -> 957217 bytes Tools/Reflection64.bin | Bin 957176 -> 957217 bytes Tutorial/GacUI_HelloWorlds/UIRes/Xml.bin.x64 | Bin 25176 -> 25176 bytes Tutorial/GacUI_HelloWorlds/UIRes/Xml.bin.x86 | Bin 25176 -> 25176 bytes .../GacUI_Layout/UIRes/RichTextEmbedding.bin | Bin 63725 -> 63711 bytes 16 files changed, 2795 insertions(+), 1414 deletions(-) diff --git a/Import/GacUI.UnitTest.UI.cpp b/Import/GacUI.UnitTest.UI.cpp index 676f6874..2269d6f0 100644 --- a/Import/GacUI.UnitTest.UI.cpp +++ b/Import/GacUI.UnitTest.UI.cpp @@ -58,6 +58,198 @@ namespace gaclib_controls } } + using ImageCreationMap = remoteprotocol::ArrayMap; + using ElementDescMap = Dictionary; + + Ptr CreateImageElement(const remoteprotocol::ElementDesc_ImageFrame& desc, Ptr imageCreations) + { + auto element = Ptr(GuiImageFrameElement::Create()); + element->SetAlignments(GetAlignment(desc.horizontalAlignment), GetAlignment(desc.verticalAlignment)); + element->SetStretch(desc.stretch); + element->SetEnabled(desc.enabled); + + if (desc.imageId) + { + vint index = imageCreations->Keys().IndexOf(desc.imageId.Value()); + if (index != -1) + { + auto binary = imageCreations->Values()[index].imageData; + binary->SeekFromBegin(0); + element->SetImage(GetCurrentController()->ImageService()->CreateImageFromStream(*binary.Obj()), desc.imageFrame); + } + } + + return element; + } + + /*********************************************************************** + GuiGraphicsParagraphWrapperElement + ***********************************************************************/ + + class GuiGraphicsParagraphWrapperElement + : public Object + , public IGuiGraphicsElement + , protected IGuiGraphicsRenderer + , protected IGuiGraphicsRendererFactory + , protected IGuiGraphicsParagraphCallback + { + protected: + remoteprotocol::ElementDesc_DocumentParagraphFull desc; + Ptr elementDescs; + Ptr imageCreations; + + Ptr paragraph; + GuiGraphicsComposition* ownerComposition = nullptr; + IGuiGraphicsRenderTarget* renderTarget = nullptr; + + void SetOwnerComposition(GuiGraphicsComposition* _ownerComposition) override + { + ownerComposition = _ownerComposition; + } + + public: + + GuiGraphicsParagraphWrapperElement(const remoteprotocol::ElementDesc_DocumentParagraphFull& _desc, Ptr _elementDescs, Ptr _imageCreations) + :desc(_desc) + , elementDescs(_elementDescs) + , imageCreations(_imageCreations) + { + } + + IGuiGraphicsRenderer* GetRenderer() override + { + return this; + } + + GuiGraphicsComposition* GetOwnerComposition() override + { + return ownerComposition; + } + + protected: + + IGuiGraphicsRendererFactory* GetFactory() override + { + return this; + } + + void Initialize(IGuiGraphicsElement* element) override + { + } + + void Finalize() override + { + } + + void SetRenderTarget(IGuiGraphicsRenderTarget* _renderTarget) override + { + if (renderTarget != _renderTarget) + { + renderTarget = _renderTarget; + paragraph = nullptr; + } + } + + void Render(Rect bounds) override + { + if (!renderTarget) return; + if (!paragraph) + { + auto text = desc.paragraph.text ? desc.paragraph.text.Value() : WString::Empty; + paragraph = GetGuiGraphicsResourceManager()->GetLayoutProvider()->CreateParagraph(text, renderTarget, this); + + paragraph->SetWrapLine(desc.paragraph.wrapLine); + paragraph->SetMaxWidth(desc.paragraph.maxWidth); + paragraph->SetParagraphAlignment(GetAlignment(desc.paragraph.alignment)); + + if (desc.paragraph.runsDiff) + { + for (auto run : *desc.paragraph.runsDiff.Obj()) + { + auto length = run.caretEnd - run.caretBegin; + if (length <= 0) continue; + + run.props.Apply(Overloading( + [&](const remoteprotocol::DocumentTextRunProperty& textProp) + { + paragraph->SetFont(run.caretBegin, length, textProp.fontProperties.fontFamily); + paragraph->SetSize(run.caretBegin, length, textProp.fontProperties.size); + + IGuiGraphicsParagraph::TextStyle style = (IGuiGraphicsParagraph::TextStyle)0; + if (textProp.fontProperties.bold) style = (IGuiGraphicsParagraph::TextStyle)((vint)style | IGuiGraphicsParagraph::Bold); + if (textProp.fontProperties.italic) style = (IGuiGraphicsParagraph::TextStyle)((vint)style | IGuiGraphicsParagraph::Italic); + if (textProp.fontProperties.underline) style = (IGuiGraphicsParagraph::TextStyle)((vint)style | IGuiGraphicsParagraph::Underline); + if (textProp.fontProperties.strikeline) style = (IGuiGraphicsParagraph::TextStyle)((vint)style | IGuiGraphicsParagraph::Strikeline); + paragraph->SetStyle(run.caretBegin, length, style); + + paragraph->SetColor(run.caretBegin, length, textProp.textColor); + paragraph->SetBackgroundColor(run.caretBegin, length, textProp.backgroundColor); + }, + [&](const remoteprotocol::DocumentInlineObjectRunProperty& inlineProp) + { + IGuiGraphicsParagraph::InlineObjectProperties properties; + properties.size = inlineProp.size; + properties.baseline = inlineProp.baseline; + properties.breakCondition = inlineProp.breakCondition; + properties.callbackId = inlineProp.callbackId; + if (inlineProp.backgroundElementId != -1) + { + auto& desc = elementDescs->Get(inlineProp.backgroundElementId).Get(); + auto element = CreateImageElement(desc, imageCreations); + properties.backgroundImage = element; + } + paragraph->SetInlineObject(run.caretBegin, length, properties); + } + )); + } + } + + if (desc.caret) + { + auto& caret = desc.caret.Value(); + paragraph->OpenCaret(caret.caret, caret.caretColor, caret.frontSide); + } + } + paragraph->Render(bounds); + } + + void OnElementStateChanged() override + { + } + + Size GetMinSize() override + { + return {}; + } + + protected: + + IGuiGraphicsRenderer* Create() override + { + CHECK_FAIL(L"Not Implemented!"); + } + + protected: + + Size OnRenderInlineObject(vint callbackId, Rect location) override + { + if (!desc.paragraph.runsDiff) return {}; + Size result; + bool found = false; + for (auto&& run : *desc.paragraph.runsDiff.Obj()) + { + if (auto props = run.props.TryGet()) + { + if (props->callbackId == callbackId) + { + return props->size; + } + } + } + return {}; + } + }; + void InstallDom( const remoteprotocol::UnitTest_RenderingTrace& trace, const remoteprotocol::UnitTest_RenderingFrame& frame, @@ -124,128 +316,120 @@ namespace gaclib_controls switch (trace.createdElements->Get(dom->content.element.Value())) { case remoteprotocol::RendererType::FocusRectangle: - { - auto element = Ptr(GuiFocusRectangleElement::Create()); - bounds->SetOwnedElement(element); - } - break; + { + auto element = Ptr(GuiFocusRectangleElement::Create()); + bounds->SetOwnedElement(element); + } + break; case remoteprotocol::RendererType::Raw: // Do Nothing break; case remoteprotocol::RendererType::SolidBorder: - { - auto element = Ptr(GuiSolidBorderElement::Create()); - bounds->SetOwnedElement(element); - auto& desc = frame.elements->Get(dom->content.element.Value()).Get(); - - element->SetColor(desc.borderColor); - element->SetShape(desc.shape); - } - break; - case remoteprotocol::RendererType::SinkBorder: - { - auto element = Ptr(Gui3DBorderElement::Create()); - bounds->SetOwnedElement(element); - auto& desc = frame.elements->Get(dom->content.element.Value()).Get(); - - element->SetColors(desc.leftTopColor, desc.rightBottomColor); - } - break; - case remoteprotocol::RendererType::SinkSplitter: - { - auto element = Ptr(Gui3DSplitterElement::Create()); - bounds->SetOwnedElement(element); - auto& desc = frame.elements->Get(dom->content.element.Value()).Get(); - - element->SetColors(desc.leftTopColor, desc.rightBottomColor); - element->SetDirection(desc.direction); - } - break; - case remoteprotocol::RendererType::SolidBackground: - { - auto element = Ptr(GuiSolidBackgroundElement::Create()); - bounds->SetOwnedElement(element); - auto& desc = frame.elements->Get(dom->content.element.Value()).Get(); - - element->SetColor(desc.backgroundColor); - element->SetShape(desc.shape); - } - break; - case remoteprotocol::RendererType::GradientBackground: - { - auto element = Ptr(GuiGradientBackgroundElement::Create()); - bounds->SetOwnedElement(element); - auto& desc = frame.elements->Get(dom->content.element.Value()).Get(); - - element->SetColors(desc.leftTopColor, desc.rightBottomColor); - element->SetDirection(desc.direction); - element->SetShape(desc.shape); - } - break; - case remoteprotocol::RendererType::InnerShadow: - { - auto element = Ptr(GuiInnerShadowElement::Create()); - bounds->SetOwnedElement(element); - auto& desc = frame.elements->Get(dom->content.element.Value()).Get(); - - element->SetColor(desc.shadowColor); - element->SetThickness(desc.thickness); - } - break; - case remoteprotocol::RendererType::SolidLabel: - { - auto element = Ptr(GuiSolidLabelElement::Create()); - bounds->SetOwnedElement(element); - auto& desc = frame.elements->Get(dom->content.element.Value()).Get(); - - element->SetColor(desc.textColor); - element->SetAlignments(GetAlignment(desc.horizontalAlignment), GetAlignment(desc.verticalAlignment)); - element->SetWrapLine(desc.wrapLine); - element->SetWrapLineHeightCalculation(desc.wrapLineHeightCalculation); - element->SetEllipse(desc.ellipse); - element->SetMultiline(desc.multiline); - element->SetFont(desc.font.Value()); - element->SetText(desc.text.Value()); - } - break; - case remoteprotocol::RendererType::Polygon: - { - auto element = Ptr(GuiPolygonElement::Create()); - bounds->SetOwnedElement(element); - auto& desc = frame.elements->Get(dom->content.element.Value()).Get(); - - element->SetSize(desc.size); - element->SetBorderColor(desc.borderColor); - element->SetBackgroundColor(desc.backgroundColor); - - if (desc.points && desc.points->Count() > 0) { - element->SetPoints(&desc.points->Get(0), desc.points->Count()); + auto element = Ptr(GuiSolidBorderElement::Create()); + bounds->SetOwnedElement(element); + auto& desc = frame.elements->Get(dom->content.element.Value()).Get(); + + element->SetColor(desc.borderColor); + element->SetShape(desc.shape); } - } - break; - case remoteprotocol::RendererType::ImageFrame: - { - auto element = Ptr(GuiImageFrameElement::Create()); - bounds->SetOwnedElement(element); - auto& desc = frame.elements->Get(dom->content.element.Value()).Get(); - - element->SetAlignments(GetAlignment(desc.horizontalAlignment), GetAlignment(desc.verticalAlignment)); - element->SetStretch(desc.stretch); - element->SetEnabled(desc.enabled); - - if (desc.imageId) + break; + case remoteprotocol::RendererType::SinkBorder: { - vint index = trace.imageCreations->Keys().IndexOf(desc.imageId.Value()); - if (index != -1) + auto element = Ptr(Gui3DBorderElement::Create()); + bounds->SetOwnedElement(element); + auto& desc = frame.elements->Get(dom->content.element.Value()).Get(); + + element->SetColors(desc.leftTopColor, desc.rightBottomColor); + } + break; + case remoteprotocol::RendererType::SinkSplitter: + { + auto element = Ptr(Gui3DSplitterElement::Create()); + bounds->SetOwnedElement(element); + auto& desc = frame.elements->Get(dom->content.element.Value()).Get(); + + element->SetColors(desc.leftTopColor, desc.rightBottomColor); + element->SetDirection(desc.direction); + } + break; + case remoteprotocol::RendererType::SolidBackground: + { + auto element = Ptr(GuiSolidBackgroundElement::Create()); + bounds->SetOwnedElement(element); + auto& desc = frame.elements->Get(dom->content.element.Value()).Get(); + + element->SetColor(desc.backgroundColor); + element->SetShape(desc.shape); + } + break; + case remoteprotocol::RendererType::GradientBackground: + { + auto element = Ptr(GuiGradientBackgroundElement::Create()); + bounds->SetOwnedElement(element); + auto& desc = frame.elements->Get(dom->content.element.Value()).Get(); + + element->SetColors(desc.leftTopColor, desc.rightBottomColor); + element->SetDirection(desc.direction); + element->SetShape(desc.shape); + } + break; + case remoteprotocol::RendererType::InnerShadow: + { + auto element = Ptr(GuiInnerShadowElement::Create()); + bounds->SetOwnedElement(element); + auto& desc = frame.elements->Get(dom->content.element.Value()).Get(); + + element->SetColor(desc.shadowColor); + element->SetThickness(desc.thickness); + } + break; + case remoteprotocol::RendererType::SolidLabel: + { + auto element = Ptr(GuiSolidLabelElement::Create()); + bounds->SetOwnedElement(element); + auto& desc = frame.elements->Get(dom->content.element.Value()).Get(); + + element->SetColor(desc.textColor); + element->SetAlignments(GetAlignment(desc.horizontalAlignment), GetAlignment(desc.verticalAlignment)); + element->SetWrapLine(desc.wrapLine); + element->SetWrapLineHeightCalculation(desc.wrapLineHeightCalculation); + element->SetEllipse(desc.ellipse); + element->SetMultiline(desc.multiline); + element->SetFont(desc.font.Value()); + element->SetText(desc.text.Value()); + } + break; + case remoteprotocol::RendererType::Polygon: + { + auto element = Ptr(GuiPolygonElement::Create()); + bounds->SetOwnedElement(element); + auto& desc = frame.elements->Get(dom->content.element.Value()).Get(); + + element->SetSize(desc.size); + element->SetBorderColor(desc.borderColor); + element->SetBackgroundColor(desc.backgroundColor); + + if (desc.points && desc.points->Count() > 0) { - auto binary = trace.imageCreations->Values()[index].imageData; - binary->SeekFromBegin(0); - element->SetImage(GetCurrentController()->ImageService()->CreateImageFromStream(*binary.Obj()), desc.imageFrame); + element->SetPoints(&desc.points->Get(0), desc.points->Count()); } } - } - break; + break; + case remoteprotocol::RendererType::ImageFrame: + { + auto& desc = frame.elements->Get(dom->content.element.Value()).Get(); + auto element = CreateImageElement(desc, trace.imageCreations); + bounds->SetOwnedElement(element); + } + break; + case remoteprotocol::RendererType::DocumentParagraph: + { + auto& desc = frame.elements->Get(dom->content.element.Value()).Get(); + auto element = Ptr(new GuiGraphicsParagraphWrapperElement(desc, frame.elements, trace.imageCreations)); + bounds->SetOwnedElement(element); + } + break; default: CHECK_FAIL(L"This element is not supported yet."); break; @@ -465,6 +649,7 @@ namespace gaclib_controls } } + /*********************************************************************** .\SOURCE\GUIUNITTESTSNAPSHOTVIEWER.CPP ***********************************************************************/ diff --git a/Import/GacUI.UnitTest.cpp b/Import/GacUI.UnitTest.cpp index 4aeca9b5..193a86f7 100644 --- a/Import/GacUI.UnitTest.cpp +++ b/Import/GacUI.UnitTest.cpp @@ -4,6 +4,1406 @@ DEVELOPER: Zihan Chen(vczh) ***********************************************************************/ #include "GacUI.UnitTest.h" +/*********************************************************************** +.\GUIUNITTESTPROTOCOL_RENDERING _DOCUMENT.CPP +***********************************************************************/ + +namespace vl::presentation::unittest +{ + using namespace collections; + using namespace remoteprotocol; + +/*********************************************************************** +Helper Functions for Document Paragraph +***********************************************************************/ + + vint GetFontSizeForPosition( + const DocumentParagraphState& state, + vint pos, + Nullable>& inlineProp) + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::GetFontSizeForPosition(...)#" + inlineProp.Reset(); + + for (auto [range, prop] : state.mergedRuns) + { + if (pos >= range.caretBegin && pos < range.caretEnd) + { + if (auto textProp = prop.TryGet()) + { + return textProp->fontProperties.size; + } + if (auto objProp = prop.TryGet()) + { + inlineProp = { range.caretEnd - range.caretBegin,*objProp }; + return 0; + } + } + } + CHECK_FAIL(ERROR_MESSAGE_PREFIX L"Every character is expected to have a font."); +#undef ERROR_MESSAGE_PREFIX + } + + double GetCharacterWidth(wchar_t c, vint fontSize) + { + return (c < 128 ? 0.6 : 1.0) * fontSize; + } + + void CalculateParagraphLayout(DocumentParagraphState& state) + { + state.characterLayouts.Clear(); + state.lines.Clear(); + state.cachedSize = Size(0, 16); + state.cachedInlineObjectBounds.Clear(); + + const WString& text = state.text; + + if (text.Length() == 0) + { + // Empty paragraph has default size + DocumentParagraphLineInfo line; + line.startPos = 0; + line.endPos = 0; + line.y = 0; + line.height = 16; // Default: 12 (font) + 4 + line.baseline = 12; + line.width = 0; + state.lines.Add(line); + return; + } + + // First pass: calculate per-character metrics + struct TempCharInfo + { + double x; + double width; + vint height; + Nullable inlineObjectProp; + }; + List tempChars; + List> lineRanges; // [start, end) for each line + + double currentX = 0; + vint currentLineStart = 0; + + for (vint i = 0; i < text.Length(); i++) + { + wchar_t c = text[i]; + TempCharInfo info = { currentX, 0, 0, {} }; + + // Handle \r - zero width, no line break + if (c == L'\r') + { + tempChars.Add(info); + continue; + } + + // Get character properties + Nullable> inlinePair; + vint fontSize = GetFontSizeForPosition(state, i, inlinePair); + + if (inlinePair) + { + auto& prop = inlinePair.Value().value; + info.width = (double)prop.size.x; + info.height = prop.size.y; + info.inlineObjectProp = inlinePair.Value().value; + } + else + { + if (fontSize <= 0) fontSize = 12; + info.width = GetCharacterWidth(c, fontSize); + info.height = fontSize; + } + + // Handle \n - always break line + if (c == L'\n') + { + info.width = 0; + tempChars.Add(info); + lineRanges.Add({ currentLineStart, i + 1 }); + currentLineStart = i + 1; + currentX = 0; + continue; + } + + // Check word wrap + if (state.wrapLine && state.maxWidth > 0 && currentX > 0) + { + if (currentX + info.width > state.maxWidth) + { + lineRanges.Add({ currentLineStart, i }); + currentLineStart = i; + currentX = 0; + } + } + + info.x = currentX; + tempChars.Add(info); + currentX += info.width; + + if(inlinePair) + { + i += inlinePair.Value().key - 1; + } + } + + // Add final line + if (currentLineStart <= text.Length()) + { + lineRanges.Add({ currentLineStart, text.Length() }); + } + + // Handle empty case + if (lineRanges.Count() == 0) + { + lineRanges.Add({ 0, 0 }); + } + + // Second pass: calculate line heights using baseline alignment + vint currentY = 0; + for (auto [lineStart, lineEnd] : lineRanges) + { + vint maxAboveBaseline = 0; + vint maxBelowBaseline = 0; + + for (vint i = lineStart; i < lineEnd && i < tempChars.Count(); i++) + { + auto& info = tempChars[i]; + if (info.inlineObjectProp) + { + auto&& prop = info.inlineObjectProp.Value(); + vint baseline = prop.baseline; + if (baseline == -1) + baseline = info.height; + vint above = baseline; + vint below = info.height - baseline; + if (above < 0) above = 0; + if (below < 0) below = 0; + if (maxAboveBaseline < above) + maxAboveBaseline = above; + if (maxBelowBaseline < below) + maxBelowBaseline = below; + } + else + { + if (maxAboveBaseline < info.height) + maxAboveBaseline = info.height; + } + } + + DocumentParagraphLineInfo line; + line.startPos = lineStart; + line.endPos = lineEnd; + line.y = currentY; + line.height = maxAboveBaseline + maxBelowBaseline + 4; + line.baseline = maxAboveBaseline; + + // Calculate line width + double lineWidth = 0; + for (vint i = lineStart; i < lineEnd && i < tempChars.Count(); i++) + { + double endX = tempChars[i].x + tempChars[i].width; + if (endX > lineWidth) lineWidth = endX; + } + line.width = (vint)lineWidth; + + // Fill inline object bounds + + for (vint i = lineStart; i < lineEnd && i < tempChars.Count(); i++) + { + auto& info = tempChars[i]; + if (info.inlineObjectProp) + { + auto&& prop = info.inlineObjectProp.Value(); + if (prop.callbackId != -1) + { + vint baseline = prop.baseline; + if (baseline == -1) + baseline = info.height; + vint y = line.y + 2 + line.baseline - baseline; + state.cachedInlineObjectBounds.Add(prop.callbackId, Rect(Point((vint)info.x, y), prop.size)); + } + } + } + + state.lines.Add(line); + currentY += line.height; + } + + // Third pass: create final character layouts with line indices + vint lineIdx = 0; + for (vint i = 0; i < tempChars.Count(); i++) + { + while (lineIdx < state.lines.Count() - 1 && i >= state.lines[lineIdx].endPos) + { + lineIdx++; + } + DocumentParagraphCharLayout cl; + cl.x = tempChars[i].x; + cl.width = tempChars[i].width; + cl.lineIndex = lineIdx; + cl.height = tempChars[i].height; + state.characterLayouts.Add(cl); + } + + // Calculate total size + vint maxWidth = 0; + for (auto&& line : state.lines) + { + if (line.width > maxWidth) maxWidth = line.width; + } + state.cachedSize = Size(maxWidth, currentY > 0 ? currentY : 16); + } + +/*********************************************************************** +IGuiRemoteProtocolMessages (Elements - Document) +***********************************************************************/ + + void UnitTestRemoteProtocol_Rendering::Impl_RendererUpdateElement_DocumentParagraph(vint id, const ElementDesc_DocumentParagraph& arguments) + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::Impl_RendererUpdateElement_DocumentParagraph(vint, const ElementDesc_DocumentParagraph&)#" + vint index = paragraphStates.Keys().IndexOf(arguments.id); + CHECK_ERROR(index != -1, ERROR_MESSAGE_PREFIX L"Paragraph not created."); + auto state = paragraphStates.Values()[index]; + + // Apply text if provided (distinguish null vs empty string) + if (arguments.text) + { + state->text = arguments.text.Value(); + // Text changed - clear run maps since positions may be invalid + state->textRuns.Clear(); + state->inlineObjectRuns.Clear(); + } + + // Always update these + state->wrapLine = arguments.wrapLine; + state->maxWidth = arguments.maxWidth; + state->alignment = arguments.alignment; + + // Process removed inline objects first + if (arguments.removedInlineObjects) + { + for (auto callbackId : *arguments.removedInlineObjects.Obj()) + { + // Find the range for this inline object and reset it + for (auto [range, prop] : state->inlineObjectRuns) + { + if (prop.callbackId == callbackId) + { + elements::ResetInlineObjectRun(state->inlineObjectRuns, range); + break; + } + } + } + } + + // Apply runsDiff using helper functions + if (arguments.runsDiff) + { + for (auto run : *arguments.runsDiff.Obj()) + { + elements::CaretRange range{ run.caretBegin, run.caretEnd }; + + if (auto textProp = run.props.TryGet()) + { + elements::DocumentTextRunPropertyOverrides overrides; + overrides.textColor = textProp->textColor; + overrides.backgroundColor = textProp->backgroundColor; + overrides.fontFamily = textProp->fontProperties.fontFamily; + overrides.size = textProp->fontProperties.size; + // Convert bool flags back to TextStyle + elements::IGuiGraphicsParagraph::TextStyle style = (elements::IGuiGraphicsParagraph::TextStyle)0; + if (textProp->fontProperties.bold) style = (elements::IGuiGraphicsParagraph::TextStyle)((vint)style | (vint)elements::IGuiGraphicsParagraph::TextStyle::Bold); + if (textProp->fontProperties.italic) style = (elements::IGuiGraphicsParagraph::TextStyle)((vint)style | (vint)elements::IGuiGraphicsParagraph::TextStyle::Italic); + if (textProp->fontProperties.underline) style = (elements::IGuiGraphicsParagraph::TextStyle)((vint)style | (vint)elements::IGuiGraphicsParagraph::TextStyle::Underline); + if (textProp->fontProperties.strikeline) style = (elements::IGuiGraphicsParagraph::TextStyle)((vint)style | (vint)elements::IGuiGraphicsParagraph::TextStyle::Strikeline); + overrides.textStyle = style; + elements::AddTextRun(state->textRuns, range, overrides); + } + else if (auto inlineProp = run.props.TryGet()) + { + elements::AddInlineObjectRun(state->inlineObjectRuns, range, *inlineProp); + } + } + } + + // Merge runs to create final result + state->mergedRuns.Clear(); + elements::MergeRuns(state->textRuns, state->inlineObjectRuns, state->mergedRuns); + + // Recalculate layout + CalculateParagraphLayout(*state.Obj()); + + { + index = loggedTrace.createdElements->Keys().IndexOf(arguments.id); + CHECK_ERROR(index != -1, ERROR_MESSAGE_PREFIX L"Renderer with the specified id has not been created."); + + auto rendererType = loggedTrace.createdElements->Values()[index]; + CHECK_ERROR(rendererType == RendererType::DocumentParagraph, ERROR_MESSAGE_PREFIX L"Renderer with the specified id is not of the expected type."); + + index = lastElementDescs.Keys().IndexOf(arguments.id); + ElementDesc_DocumentParagraphFull element; + if (index != -1) + { + auto paragraphRef = lastElementDescs.Values()[index].TryGet(); + CHECK_ERROR(paragraphRef, ERROR_MESSAGE_PREFIX L"Renderer with the specified id is not of the expected type."); + element = *paragraphRef; + } + element.paragraph = arguments; + element.paragraph.text = state->text; + element.paragraph.createdInlineObjects = {}; + element.paragraph.removedInlineObjects = {}; + element.paragraph.runsDiff = Ptr(new List); + for (auto [range, props] : state->mergedRuns) + { + remoteprotocol::DocumentRun run; + run.caretBegin = range.caretBegin; + run.caretEnd = range.caretEnd; + run.props = props; + element.paragraph.runsDiff->Add(run); + } + lastElementDescs.Set(arguments.id, element); + } + + // Send response with calculated size and inline object bounds + UpdateElement_DocumentParagraphResponse response; + response.documentSize = state->cachedSize; + if (state->cachedInlineObjectBounds.Count() > 0) + { + response.inlineObjectBounds = Ptr(new Dictionary); + CopyFrom(*response.inlineObjectBounds.Obj(), state->cachedInlineObjectBounds); + } + + GetEvents()->RespondRendererUpdateElement_DocumentParagraph(id, response); +#undef ERROR_MESSAGE_PREFIX + } + + void UnitTestRemoteProtocol_Rendering::Impl_DocumentParagraph_GetCaretBounds(vint id, const GetCaretBoundsRequest& arguments) + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::Impl_DocumentParagraph_GetCaretBounds(vint, const GetCaretBoundsRequest&)#" + vint index = paragraphStates.Keys().IndexOf(arguments.id); + CHECK_ERROR(index != -1, ERROR_MESSAGE_PREFIX L"No active paragraph."); + auto state = paragraphStates.Values()[index]; + + vint caret = arguments.caret; + + // Handle empty text + if (state->text.Length() == 0 || state->lines.Count() == 0) + { + auto& line = state->lines[0]; + GetEvents()->RespondDocumentParagraph_GetCaretBounds(id, Rect(Point(0, line.y), Size(0, line.height))); + return; + } + + // Clamp caret to valid range + if (caret < 0) caret = 0; + if (caret > state->text.Length()) caret = state->text.Length(); + + // Find which line the caret is on + vint lineIdx = 0; + for (vint i = 0; i < state->lines.Count(); i++) + { + if (caret >= state->lines[i].startPos && caret <= state->lines[i].endPos) + { + lineIdx = i; + break; + } + if (i == state->lines.Count() - 1) + { + lineIdx = i; + } + } + + auto& line = state->lines[lineIdx]; + + // Calculate x position + vint x = 0; + if (caret > 0 && caret <= state->characterLayouts.Count()) + { + // Caret is at the end of the previous character + auto& prevChar = state->characterLayouts[caret - 1]; + x = (vint)(prevChar.x + prevChar.width); + } + else if (caret < state->characterLayouts.Count()) + { + // Caret is at the start of this character + x = (vint)state->characterLayouts[caret].x; + } + + // Apply alignment offset + vint alignmentOffset = 0; + if (state->alignment == ElementHorizontalAlignment::Center) + { + alignmentOffset = (state->cachedSize.x - line.width) / 2; + } + else if (state->alignment == ElementHorizontalAlignment::Right) + { + alignmentOffset = state->cachedSize.x - line.width; + } + + Rect bounds(Point(x + alignmentOffset, line.y), Size(0, line.height)); + GetEvents()->RespondDocumentParagraph_GetCaretBounds(id, bounds); +#undef ERROR_MESSAGE_PREFIX + } + + void UnitTestRemoteProtocol_Rendering::Impl_DocumentParagraph_GetCaret(vint id, const GetCaretRequest& arguments) + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::Impl_DocumentParagraph_GetCaret(vint, const GetCaretRequest&)#" + vint index = paragraphStates.Keys().IndexOf(arguments.id); + CHECK_ERROR(index != -1, ERROR_MESSAGE_PREFIX L"No active paragraph."); + auto state = paragraphStates.Values()[index]; + + vint caret = arguments.caret; + auto relPos = arguments.relativePosition; + GetCaretResponse response; + response.preferFrontSide = true; + + vint textLen = state->text.Length(); + + // Clamp caret + if (caret < 0) caret = 0; + if (caret > textLen) caret = textLen; + + // Find current line + vint lineIdx = 0; + for (vint i = 0; i < state->lines.Count(); i++) + { + if (caret >= state->lines[i].startPos && caret <= state->lines[i].endPos) + { + lineIdx = i; + break; + } + } + + using CRP = elements::IGuiGraphicsParagraph::CaretRelativePosition; + + switch (relPos) + { + case CRP::CaretFirst: + response.newCaret = 0; + break; + case CRP::CaretLast: + response.newCaret = textLen; + break; + case CRP::CaretLineFirst: + response.newCaret = state->lines[lineIdx].startPos; + break; + case CRP::CaretLineLast: + response.newCaret = state->lines[lineIdx].endPos; + if (response.newCaret > state->lines[lineIdx].startPos && response.newCaret > 0) + { + // Don't include CR/LF at end of line + while (response.newCaret > state->lines[lineIdx].startPos && response.newCaret > 0) + { + auto ch = state->text[response.newCaret - 1]; + if (ch == L'\r' || ch == L'\n') + { + response.newCaret--; + } + else + { + break; + } + } + } + break; + case CRP::CaretMoveLeft: + response.newCaret = caret > 0 ? caret - 1 : 0; + break; + case CRP::CaretMoveRight: + response.newCaret = caret < textLen ? caret + 1 : textLen; + break; + case CRP::CaretMoveUp: + if (lineIdx > 0) + { + // Calculate x offset in current line + vint xOffset = 0; + if (caret > 0 && caret <= state->characterLayouts.Count()) + { + auto& prevChar = state->characterLayouts[caret - 1]; + xOffset = (vint)(prevChar.x + prevChar.width); + } + // Find corresponding position in previous line + auto& prevLine = state->lines[lineIdx - 1]; + response.newCaret = prevLine.startPos; + for (vint i = prevLine.startPos; i < prevLine.endPos && i < state->characterLayouts.Count(); i++) + { + auto& ch = state->characterLayouts[i]; + if (ch.x + ch.width / 2 > xOffset) + break; + response.newCaret = i + 1; + } + } + else + { + response.newCaret = caret; + } + break; + case CRP::CaretMoveDown: + if (lineIdx < state->lines.Count() - 1) + { + // Calculate x offset in current line + vint xOffset = 0; + if (caret > 0 && caret <= state->characterLayouts.Count()) + { + auto& prevChar = state->characterLayouts[caret - 1]; + xOffset = (vint)(prevChar.x + prevChar.width); + } + // Find corresponding position in next line + auto& nextLine = state->lines[lineIdx + 1]; + response.newCaret = nextLine.startPos; + for (vint i = nextLine.startPos; i < nextLine.endPos && i < state->characterLayouts.Count(); i++) + { + auto& ch = state->characterLayouts[i]; + if (ch.x + ch.width / 2 > xOffset) + break; + response.newCaret = i + 1; + } + } + else + { + response.newCaret = caret; + } + break; + default: + response.newCaret = caret; + break; + } + + GetEvents()->RespondDocumentParagraph_GetCaret(id, response); +#undef ERROR_MESSAGE_PREFIX + } + + void UnitTestRemoteProtocol_Rendering::Impl_DocumentParagraph_GetNearestCaretFromTextPos(vint id, const GetCaretBoundsRequest& arguments) + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::Impl_DocumentParagraph_GetNearestCaretFromTextPos(vint, const GetCaretBoundsRequest&)#" + vint index = paragraphStates.Keys().IndexOf(arguments.id); + CHECK_ERROR(index != -1, ERROR_MESSAGE_PREFIX L"No active paragraph."); + auto state = paragraphStates.Values()[index]; + + vint textPos = arguments.caret; + vint textLen = state->text.Length(); + + // Clamp to valid range + if (textPos < 0) textPos = 0; + if (textPos > textLen) textPos = textLen; + + // For simple implementation, text position equals caret position + GetEvents()->RespondDocumentParagraph_GetNearestCaretFromTextPos(id, textPos); +#undef ERROR_MESSAGE_PREFIX + } + + void UnitTestRemoteProtocol_Rendering::Impl_DocumentParagraph_GetInlineObjectFromPoint(vint id, const GetInlineObjectFromPointRequest& arguments) + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::Impl_DocumentParagraph_GetInlineObjectFromPoint(vint, const GetInlineObjectFromPointRequest&)#" + vint index = paragraphStates.Keys().IndexOf(arguments.id); + CHECK_ERROR(index != -1, ERROR_MESSAGE_PREFIX L"No active paragraph."); + auto state = paragraphStates.Values()[index]; + + Point pt = arguments.point; + Nullable result; + + // Find the line containing the Y coordinate + vint lineIdx = -1; + for (vint i = 0; i < state->lines.Count(); i++) + { + if (pt.y >= state->lines[i].y && pt.y < state->lines[i].y + state->lines[i].height) + { + lineIdx = i; + break; + } + } + + if (lineIdx >= 0) + { + auto& line = state->lines[lineIdx]; + + // Apply alignment offset + vint alignmentOffset = 0; + if (state->alignment == ElementHorizontalAlignment::Center) + { + alignmentOffset = (state->cachedSize.x - line.width) / 2; + } + else if (state->alignment == ElementHorizontalAlignment::Right) + { + alignmentOffset = state->cachedSize.x - line.width; + } + vint relativeX = pt.x - alignmentOffset; + + // Check each character in the line + for (vint i = line.startPos; i < line.endPos && i < state->characterLayouts.Count(); i++) + { + auto& ch = state->characterLayouts[i]; + if (ch.isInlineObject && relativeX >= ch.x && relativeX < ch.x + ch.width) + { + // Found an inline object - look up its properties + for (auto [range, prop] : state->mergedRuns) + { + if (i >= range.caretBegin && i < range.caretEnd) + { + if (auto inlineProp = prop.TryGet()) + { + remoteprotocol::DocumentRun run; + run.caretBegin = range.caretBegin; + run.caretEnd = range.caretEnd; + run.props = *inlineProp; + result = run; + break; + } + } + } + break; + } + } + } + + GetEvents()->RespondDocumentParagraph_GetInlineObjectFromPoint(id, result); +#undef ERROR_MESSAGE_PREFIX + } + + void UnitTestRemoteProtocol_Rendering::Impl_DocumentParagraph_IsValidCaret(vint id, const IsValidCaretRequest& arguments) + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::Impl_DocumentParagraph_IsValidCaret(vint, const IsValidCaretRequest&)#" + vint index = paragraphStates.Keys().IndexOf(arguments.id); + if (index == -1) + { + GetEvents()->RespondDocumentParagraph_IsValidCaret(id, false); + return; + } + auto state = paragraphStates.Values()[index]; + + vint caret = arguments.caret; + + // Check range: valid positions are 0 to text.Length() inclusive + if (caret < 0 || caret > state->text.Length()) + { + GetEvents()->RespondDocumentParagraph_IsValidCaret(id, false); + return; + } + + // Check if position is inside an inline object (not at the beginning) + // Inline objects occupy a range [caretBegin, caretEnd) + // Position at caretBegin is valid (cursor can be placed before the object) + // Positions inside (caretBegin < pos < caretEnd) are invalid + for (auto&& [range, _] : state->inlineObjectRuns) + { + if (caret > range.caretBegin && caret < range.caretEnd) + { + GetEvents()->RespondDocumentParagraph_IsValidCaret(id, false); + return; + } + } + + GetEvents()->RespondDocumentParagraph_IsValidCaret(id, true); +#undef ERROR_MESSAGE_PREFIX + } + + void UnitTestRemoteProtocol_Rendering::Impl_DocumentParagraph_OpenCaret(const OpenCaretRequest& arguments) + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::Impl_DocumentParagraph_OpenCaret(const OpenCaretRequest&)#" + vint index = loggedTrace.createdElements->Keys().IndexOf(arguments.id); + CHECK_ERROR(index != -1, ERROR_MESSAGE_PREFIX L"Renderer with the specified id has not been created."); + + auto rendererType = loggedTrace.createdElements->Values()[index]; + CHECK_ERROR(rendererType == RendererType::DocumentParagraph, ERROR_MESSAGE_PREFIX L"Renderer with the specified id is not of the expected type."); + + index = lastElementDescs.Keys().IndexOf(arguments.id); + ElementDesc_DocumentParagraphFull element; + if (index != -1) + { + auto paragraphRef = lastElementDescs.Values()[index].TryGet(); + CHECK_ERROR(paragraphRef, ERROR_MESSAGE_PREFIX L"Renderer with the specified id is not of the expected type."); + element = *paragraphRef; + } + element.caret = arguments; + lastElementDescs.Set(arguments.id, element); +#undef ERROR_MESSAGE_PREFIX + } + + void UnitTestRemoteProtocol_Rendering::Impl_DocumentParagraph_CloseCaret(const vint& arguments) + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::Impl_DocumentParagraph_CloseCaret(const vint&)#" + vint index = loggedTrace.createdElements->Keys().IndexOf(arguments); + CHECK_ERROR(index != -1, ERROR_MESSAGE_PREFIX L"Renderer with the specified id has not been created."); + + auto rendererType = loggedTrace.createdElements->Values()[index]; + CHECK_ERROR(rendererType == RendererType::DocumentParagraph, ERROR_MESSAGE_PREFIX L"Renderer with the specified id is not of the expected type."); + + index = lastElementDescs.Keys().IndexOf(arguments); + ElementDesc_DocumentParagraphFull element; + if (index != -1) + { + auto paragraphRef = lastElementDescs.Values()[index].TryGet(); + CHECK_ERROR(paragraphRef, ERROR_MESSAGE_PREFIX L"Renderer with the specified id is not of the expected type."); + element = *paragraphRef; + } + element.caret.Reset(); + lastElementDescs.Set(arguments, element); +#undef ERROR_MESSAGE_PREFIX + } +} + + +/*********************************************************************** +.\GUIUNITTESTPROTOCOL_RENDERING.CPP +***********************************************************************/ + +namespace vl::presentation::unittest +{ + using namespace collections; + using namespace remoteprotocol; + +/*********************************************************************** +IGuiRemoteProtocolMessages (Rendering) +***********************************************************************/ + + Ptr UnitTestRemoteProtocol_Rendering::GetLastRenderingFrame() + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::GetLastRenderingCommands()#" + CHECK_ERROR(lastRenderingCommandsOpening, ERROR_MESSAGE_PREFIX L"The latest frame of commands is not accepting new commands."); + return loggedFrames[loggedFrames.Count() - 1]; +#undef ERROR_MESSAGE_PREFIX + } + + Ptr UnitTestRemoteProtocol_Rendering::TryGetLastRenderingFrameAndReset() + { + if (loggedFrames.Count() == 0) return nullptr; + if (!lastRenderingCommandsOpening) return nullptr; + lastRenderingCommandsOpening = false; + return loggedFrames[loggedFrames.Count() - 1]; + } + + void UnitTestRemoteProtocol_Rendering::Impl_RendererBeginRendering(const ElementBeginRendering& arguments) + { + receivedDomDiffMessage = false; + receivedElementMessage = false; + lastRenderingCommandsOpening = true; + auto frame = Ptr(new UnitTestLoggedFrame); + frame->frameId = arguments.frameId; + loggedFrames.Add(frame); + } + + void UnitTestRemoteProtocol_Rendering::Impl_RendererEndRendering(vint id) + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::Impl_RendererEndRendering(vint)#" + CHECK_ERROR(receivedElementMessage || receivedDomDiffMessage, ERROR_MESSAGE_PREFIX L"Either dom-diff or element message should be sent before this message."); + + auto lastFrame = GetLastRenderingFrame(); + if (receivedElementMessage) + { + lastFrame->renderingDom = renderingDomBuilder.RequestRendererEndRendering(); + } + if (receivedDomDiffMessage) + { + // receivedDom will be updated in RequestRendererRenderDomDiff + // store a copy to log + lastFrame->renderingDom = CopyDom(receivedDom); + } + this->GetEvents()->RespondRendererEndRendering(id, measuringForNextRendering); + measuringForNextRendering = {}; +#undef ERROR_MESSAGE_PREFIX + } + +/*********************************************************************** +IGuiRemoteProtocolMessages (Rendering - Element) +***********************************************************************/ + + void UnitTestRemoteProtocol_Rendering::Impl_RendererBeginBoundary(const ElementBoundary& arguments) + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::Impl_RendererBeginBoundary(const ElementBoundary&)#" + CHECK_ERROR(!receivedDomDiffMessage, ERROR_MESSAGE_PREFIX L"This message could not be used with dom-diff messages in the same rendering cycle."); + if (!receivedElementMessage) + { + renderingDomBuilder.RequestRendererBeginRendering(); + receivedElementMessage = true; + } + + renderingDomBuilder.RequestRendererBeginBoundary(arguments); + + glr::json::JsonFormatting formatting; + formatting.spaceAfterColon = true; + formatting.spaceAfterComma = true; + formatting.crlf = false; + formatting.compact = true; + + GetLastRenderingFrame()->renderingCommandsLog.Add(L"RequestRendererBeginBoundary: " + stream::GenerateToStream([&](stream::TextWriter& writer) + { + auto jsonLog = ConvertCustomTypeToJson(arguments); + writer.WriteString(glr::json::JsonToString(jsonLog, formatting)); + })); +#undef ERROR_MESSAGE_PREFIX + } + + void UnitTestRemoteProtocol_Rendering::Impl_RendererEndBoundary() + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::Impl_RendererEndBoundary()#" + CHECK_ERROR(!receivedDomDiffMessage, ERROR_MESSAGE_PREFIX L"This message could not be used with dom-diff messages in the same rendering cycle."); + if (!receivedElementMessage) + { + renderingDomBuilder.RequestRendererBeginRendering(); + receivedElementMessage = true; + } + + renderingDomBuilder.RequestRendererEndBoundary(); + GetLastRenderingFrame()->renderingCommandsLog.Add(L"RequestRendererEndBoundary"); +#undef ERROR_MESSAGE_PREFIX + } + + void UnitTestRemoteProtocol_Rendering::EnsureRenderedElement(vint id, Rect bounds) + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::EnsureRenderedElement(id&)#" + + vint index = loggedTrace.createdElements->Keys().IndexOf(id); + CHECK_ERROR(index != -1, ERROR_MESSAGE_PREFIX L"Renderer with the specified id has not been created."); + auto rendererType = loggedTrace.createdElements->Values()[index]; + if (rendererType == RendererType::FocusRectangle || rendererType == RendererType::Raw) + { + // FocusRectangle or Raw does not have a ElementDesc + return; + } + + index = lastElementDescs.Keys().IndexOf(id); + CHECK_ERROR(index != -1, ERROR_MESSAGE_PREFIX L"Renderer with the specified id has not been updated after created."); + lastElementDescs.Values()[index].Apply(Overloading( + [](RendererType) + { + CHECK_FAIL(ERROR_MESSAGE_PREFIX L"Renderer with the specified id has not been updated after created."); + }, + [&](const ElementDesc_SolidLabel& solidLabel) + { + CalculateSolidLabelSizeIfNecessary(bounds.Width(), bounds.Height(), solidLabel); + }, + [&](const auto& element) + { + })); + +#undef ERROR_MESSAGE_PREFIX + } + + void UnitTestRemoteProtocol_Rendering::Impl_RendererRenderElement(const ElementRendering& arguments) + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::Impl_RendererRenderElement(const ElementRendering&)#" + CHECK_ERROR(!receivedDomDiffMessage, ERROR_MESSAGE_PREFIX L"This message could not be used with dom-diff messages in the same rendering cycle."); + if (!receivedElementMessage) + { + renderingDomBuilder.RequestRendererBeginRendering(); + receivedElementMessage = true; + } + + { + renderingDomBuilder.RequestRendererRenderElement(arguments); + + glr::json::JsonFormatting formatting; + formatting.spaceAfterColon = true; + formatting.spaceAfterComma = true; + formatting.crlf = false; + formatting.compact = true; + GetLastRenderingFrame()->renderingCommandsLog.Add(L"RequestRendererRenderElement: " + stream::GenerateToStream([&](stream::TextWriter& writer) + { + auto jsonLog = ConvertCustomTypeToJson(arguments); + writer.WriteString(glr::json::JsonToString(jsonLog, formatting)); + })); + } + + EnsureRenderedElement(arguments.id, arguments.bounds); +#undef ERROR_MESSAGE_PREFIX + } + +/*********************************************************************** +IGuiRemoteProtocolMessages (Rendering - Dom) +***********************************************************************/ + + void UnitTestRemoteProtocol_Rendering::CalculateSolidLabelSizesIfNecessary(Ptr dom) + { + if (dom->content.element) + { + EnsureRenderedElement(dom->content.element.Value(), dom->content.bounds); + } + if (dom->children) + { + for (auto child : *dom->children.Obj()) + { + CalculateSolidLabelSizesIfNecessary(child); + } + } + } + + void UnitTestRemoteProtocol_Rendering::Impl_RendererRenderDom(const Ptr& arguments) + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::Impl_RendererRenderElement(const RenderingDom&)#" + CHECK_ERROR(!receivedElementMessage, ERROR_MESSAGE_PREFIX L"This message could not be used with element messages in the same rendering cycle."); + if (!receivedDomDiffMessage) + { + receivedDomDiffMessage = true; + } + + receivedDom = arguments; + BuildDomIndex(receivedDom, receivedDomIndex); + CalculateSolidLabelSizesIfNecessary(receivedDom); +#undef ERROR_MESSAGE_PREFIX + } + + void UnitTestRemoteProtocol_Rendering::Impl_RendererRenderDomDiff(const RenderingDom_DiffsInOrder& arguments) + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::Impl_RendererRenderElement(const RenderingDom_DiffsInOrder&)#" + CHECK_ERROR(!receivedElementMessage, ERROR_MESSAGE_PREFIX L"This message could not be used with element messages in the same rendering cycle."); + if (!receivedDomDiffMessage) + { + receivedDomDiffMessage = true; + } + + UpdateDomInplace(receivedDom, receivedDomIndex, arguments); + GetLastRenderingFrame()->renderingDiffs = arguments; + CalculateSolidLabelSizesIfNecessary(receivedDom); +#undef ERROR_MESSAGE_PREFIX + } + +/*********************************************************************** +IGuiRemoteProtocolMessages (Elements) +***********************************************************************/ + + void UnitTestRemoteProtocol_Rendering::Impl_RendererCreated(const Ptr>& arguments) + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::Impl_RendererCreated(const Ptr>&)#" + if (arguments) + { + for (auto creation : *arguments.Obj()) + { + CHECK_ERROR(!loggedTrace.createdElements->Keys().Contains(creation.id), ERROR_MESSAGE_PREFIX L"Renderer with the specified id has been created or used."); + loggedTrace.createdElements->Add(creation.id, creation.type); + + // Create paragraph state for DocumentParagraph elements + if (creation.type == RendererType::DocumentParagraph) + { + auto state = Ptr(new DocumentParagraphState()); + paragraphStates.Add(creation.id, state); + } + } + } +#undef ERROR_MESSAGE_PREFIX + } + + void UnitTestRemoteProtocol_Rendering::Impl_RendererDestroyed(const Ptr>& arguments) + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::Impl_RendererDestroyed(const Ptr>&)#" + if (arguments) + { + for (auto id : *arguments.Obj()) + { + CHECK_ERROR(loggedTrace.createdElements->Keys().Contains(id), ERROR_MESSAGE_PREFIX L"Renderer with the specified id has not been created."); + CHECK_ERROR(!removedElementIds.Contains(id), ERROR_MESSAGE_PREFIX L"Renderer with the specified id has been destroyed."); + removedElementIds.Add(id); + lastElementDescs.Remove(id); + + // Remove paragraph state if this was a DocumentParagraph + paragraphStates.Remove(id); + } + } +#undef ERROR_MESSAGE_PREFIX + } + +#define REQUEST_RENDERER_UPDATE_ELEMENT2(ARGUMENTS, RENDERER_TYPE)\ + RequestRendererUpdateElement(\ + ARGUMENTS,\ + ERROR_MESSAGE_PREFIX L"Renderer with the specified id has not been created.",\ + ERROR_MESSAGE_PREFIX L"Renderer with the specified id is not of the expected type."\ + ) + +#define REQUEST_RENDERER_UPDATE_ELEMENT(RENDERER_TYPE) REQUEST_RENDERER_UPDATE_ELEMENT2(arguments, RENDERER_TYPE) + + void UnitTestRemoteProtocol_Rendering::Impl_RendererUpdateElement_SolidBorder(const ElementDesc_SolidBorder& arguments) + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::Impl_RendererUpdateElement_SolidBorder(const ElementDesc_SolidBorder&)#" + REQUEST_RENDERER_UPDATE_ELEMENT(RendererType::SolidBorder); +#undef ERROR_MESSAGE_PREFIX + } + + void UnitTestRemoteProtocol_Rendering::Impl_RendererUpdateElement_SinkBorder(const ElementDesc_SinkBorder& arguments) + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::Impl_RendererUpdateElement_SinkBorder(const ElementDesc_SinkBorder&)#" + REQUEST_RENDERER_UPDATE_ELEMENT(RendererType::SinkBorder); +#undef ERROR_MESSAGE_PREFIX + } + + void UnitTestRemoteProtocol_Rendering::Impl_RendererUpdateElement_SinkSplitter(const ElementDesc_SinkSplitter& arguments) + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::Impl_RendererUpdateElement_SinkSplitter(const ElementDesc_SinkSplitter&)#" + REQUEST_RENDERER_UPDATE_ELEMENT(RendererType::SinkSplitter); +#undef ERROR_MESSAGE_PREFIX + } + + void UnitTestRemoteProtocol_Rendering::Impl_RendererUpdateElement_SolidBackground(const ElementDesc_SolidBackground& arguments) + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::Impl_RendererUpdateElement_SolidBackground(const ElementDesc_SolidBackground&)#" + REQUEST_RENDERER_UPDATE_ELEMENT(RendererType::SolidBackground); +#undef ERROR_MESSAGE_PREFIX + } + + void UnitTestRemoteProtocol_Rendering::Impl_RendererUpdateElement_GradientBackground(const ElementDesc_GradientBackground& arguments) + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::Impl_RendererUpdateElement_GradientBackground(const ElementDesc_GradientBackground&)#" + REQUEST_RENDERER_UPDATE_ELEMENT(RendererType::GradientBackground); +#undef ERROR_MESSAGE_PREFIX + } + + void UnitTestRemoteProtocol_Rendering::Impl_RendererUpdateElement_InnerShadow(const ElementDesc_InnerShadow& arguments) + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::Impl_RendererUpdateElement_InnerShadow(const ElementDesc_InnerShadow&)#" + REQUEST_RENDERER_UPDATE_ELEMENT(RendererType::InnerShadow); +#undef ERROR_MESSAGE_PREFIX + } + + void UnitTestRemoteProtocol_Rendering::Impl_RendererUpdateElement_Polygon(const ElementDesc_Polygon& arguments) + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::Impl_RendererUpdateElement_Polygon(const ElementDesc_Polygon&)#" + REQUEST_RENDERER_UPDATE_ELEMENT(RendererType::Polygon); +#undef ERROR_MESSAGE_PREFIX + } + +/*********************************************************************** +IGuiRemoteProtocolMessages (Elements - SolidLabel) +***********************************************************************/ + + void UnitTestRemoteProtocol_Rendering::CalculateSolidLabelSizeIfNecessary(vint width, vint height, const ElementDesc_SolidLabel& arguments) + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::CalculateSolidLabelSizeIfNecessary(vint, vint, const ElementDesc_SolidLabel&)#" + + if (arguments.measuringRequest) + { + switch (arguments.measuringRequest.Value()) + { + case ElementSolidLabelMeasuringRequest::FontHeight: + CHECK_ERROR(arguments.font, ERROR_MESSAGE_PREFIX L"Font is missing for calculating font height."); + if (!measuringForNextRendering.fontHeights) + { + measuringForNextRendering.fontHeights = Ptr(new List); + } + { + ElementMeasuring_FontHeight measuring; + measuring.fontFamily = arguments.font.Value().fontFamily; + measuring.fontSize = arguments.font.Value().size; + measuring.height = measuring.fontSize + 4; + measuringForNextRendering.fontHeights->Add(measuring); + } + break; + case ElementSolidLabelMeasuringRequest::TotalSize: + { + // font and text has already been verified exist in RequestRendererUpdateElement_SolidLabel + vint size = arguments.font.Value().size; + auto text = arguments.text.Value(); + vint textWidth = 0; + vint textHeight = 0; + + List lines; + { + List> matches; + regexCrLf.Split(text, true, matches); + + if (matches.Count() == 0) + { + // when there is no text, measure a space + lines.Add(WString::Unmanaged(L" ")); + } + else if (arguments.multiline) + { + // add all lines, and if any line is empty, measure a space + for (auto match : matches) + { + auto line = match->Result().Value(); + lines.Add(line.Length() ? line : WString::Unmanaged(L" ")); + } + } + else + { + lines.Add(stream::GenerateToStream([&](stream::TextWriter& writer) + { + for (auto [match, index] : indexed(matches)) + { + if (index > 0) writer.WriteChar(L' '); + auto line = match->Result().Value(); + writer.WriteString(line); + } + })); + if(lines[0].Length() == 0) + { + // when there is no text, measure a space + lines[0] = WString::Unmanaged(L" "); + } + } + } + + if (arguments.wrapLine) + { + // width of the text is 0 + // insert a line break when there is no space horizontally + vint totalLines = 0; + for (auto&& line : lines) + { + if (line.Length() == 0) + { + totalLines++; + continue; + } + + double accumulatedWidth = 0; + for (vint i = 0; i < line.Length(); i++) + { + auto c = line[i]; + auto w = (c < 128 ? 0.6 : 1) * size; + if (accumulatedWidth + w > width) + { + if (accumulatedWidth == 0) + { + totalLines++; + } + else + { + totalLines++; + accumulatedWidth = w; + } + } + else + { + accumulatedWidth += w; + } + } + if (accumulatedWidth > 0) + { + totalLines++; + } + } + textHeight = 4 + size * totalLines; + } + else + { + // width of the text is width of the longest line + textWidth = (vint)(size * From(lines) + .Select([](const WString& line) + { + double sum = 0; + for (vint i = 0; i < line.Length(); i++) + { + auto c = line[i]; + sum += (c < 128 ? 0.6 : 1); + } + return sum; + }) + .Max()); + textHeight = 4 + size * lines.Count(); + } + + if (!measuringForNextRendering.minSizes) + { + measuringForNextRendering.minSizes = Ptr(new List); + } + { + ElementMeasuring_ElementMinSize measuring; + measuring.id = arguments.id; + measuring.minSize = { textWidth,textHeight }; + measuringForNextRendering.minSizes->Add(measuring); + } + } + break; + default: + CHECK_FAIL(L"Unknown value of ElementSolidLabelMeasuringRequest."); + } + } +#undef ERROR_MESSAGE_PREFIX + } + + void UnitTestRemoteProtocol_Rendering::Impl_RendererUpdateElement_SolidLabel(const ElementDesc_SolidLabel& arguments) + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::Impl_RendererUpdateElement_SolidLabel(const ElementDesc_SolidLabel&)#" + auto element = arguments; + if (!element.font || !element.text) + { + vint index = loggedTrace.createdElements->Keys().IndexOf(element.id); + CHECK_ERROR(index != -1, ERROR_MESSAGE_PREFIX L"Renderer with the specified id has not been created."); + + auto rendererType = loggedTrace.createdElements->Values()[index]; + CHECK_ERROR(rendererType == RendererType::SolidLabel, ERROR_MESSAGE_PREFIX L"Renderer with the specified id is not of the expected type."); + + index = lastElementDescs.Keys().IndexOf(arguments.id); + if (index != -1) + { + auto solidLabel = lastElementDescs.Values()[index].TryGet(); + CHECK_ERROR(solidLabel, ERROR_MESSAGE_PREFIX L"Renderer with the specified id is not of the expected type."); + if (!element.font) element.font = solidLabel->font; + if (!element.text) element.text = solidLabel->text; + } + else + { + if (!element.font) element.font = FontProperties(); + if (!element.text) element.text = WString::Empty; + } + } + REQUEST_RENDERER_UPDATE_ELEMENT2(element, RendererType::SolidLabel); +#undef ERROR_MESSAGE_PREFIX + } + +/*********************************************************************** +IGuiRemoteProtocolMessages (Elements - Image) +***********************************************************************/ + + WString UnitTestRemoteProtocol_Rendering::GetBinaryKeyFromBinary(stream::IStream& binary) + { + stream::MemoryStream base64WStringStream; + { + stream::UtfGeneralEncoder utf8ToWCharEncoder; + stream::EncoderStream utf8ToWCharStream(base64WStringStream, utf8ToWCharEncoder); + stream::Utf8Base64Encoder binaryToBase64Utf8Encoder; + stream::EncoderStream binaryToBase64Utf8Stream(utf8ToWCharStream, binaryToBase64Utf8Encoder); + binary.SeekFromBegin(0); + stream::CopyStream(binary, binaryToBase64Utf8Stream); + } + { + base64WStringStream.SeekFromBegin(0); + stream::StreamReader reader(base64WStringStream); + return reader.ReadToEnd(); + } + } + + WString UnitTestRemoteProtocol_Rendering::GetBinaryKeyFromImage(Ptr image) + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::GetBinaryKeyFromImage(Ptr)#" + auto remoteImage = image.Cast(); + CHECK_ERROR(remoteImage, ERROR_MESSAGE_PREFIX L"The image object must be GuiRemoteGraphicsImage."); + return GetBinaryKeyFromBinary(remoteImage->GetBinaryData()); +#undef ERROR_MESSAGE_PREFIX + } + + ImageMetadata UnitTestRemoteProtocol_Rendering::MakeImageMetadata(const ImageCreation& arguments) + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::MakeImageMetadata(const remoteprotocol::ImageCreation)#" + if (!cachedImageMetadatas) + { + cachedImageMetadatas = Ptr(new Base64ToImageMetadataMap); + for (auto resource : GetResourceManager()->GetLoadedResources()) + { + if (auto xmlImageData = resource->GetValueByPath(WString::Unmanaged(L"UnitTestConfig/ImageData")).Cast()) + { + for (auto elementImage : glr::xml::XmlGetElements(xmlImageData->rootElement, WString::Unmanaged(L"Image"))) + { + WString path, format, frames = WString::Unmanaged(L"1"), width, height; + + auto attPath = glr::xml::XmlGetAttribute(elementImage.Obj(), WString::Unmanaged(L"Path")); + auto attFormat = glr::xml::XmlGetAttribute(elementImage.Obj(), WString::Unmanaged(L"Format")); + auto attFrames = glr::xml::XmlGetAttribute(elementImage.Obj(), WString::Unmanaged(L"Frames")); + auto attWidth = glr::xml::XmlGetAttribute(elementImage.Obj(), WString::Unmanaged(L"Width")); + auto attHeight = glr::xml::XmlGetAttribute(elementImage.Obj(), WString::Unmanaged(L"Height")); + + CHECK_ERROR(attPath, ERROR_MESSAGE_PREFIX L"Missing Path attribute in Image element in an UnitTestConfig/ImageData."); + CHECK_ERROR(attFormat, ERROR_MESSAGE_PREFIX L"Missing Format attribute in Image element in an UnitTestConfig/ImageData."); + CHECK_ERROR(attWidth, ERROR_MESSAGE_PREFIX L"Missing Width attribute in Image element in an UnitTestConfig/ImageData."); + CHECK_ERROR(attHeight, ERROR_MESSAGE_PREFIX L"Missing Height attribute in Image element in an UnitTestConfig/ImageData."); + + path = attPath->value.value; + format = attFormat->value.value; + width = attWidth->value.value; + height = attHeight->value.value; + if (attFrames) frames = attFrames->value.value; + + vint valueFrames = wtoi(frames); + vint valueWidth = wtoi(width); + vint valueHeight = wtoi(height); + + CHECK_ERROR(itow(valueFrames) == frames, ERROR_MESSAGE_PREFIX L"Frames attribute must be an integer in Image element in an UnitTestConfig/ImageData."); + CHECK_ERROR(itow(valueWidth) == width, ERROR_MESSAGE_PREFIX L"Width attribute must be an integer in Image element in an UnitTestConfig/ImageData."); + CHECK_ERROR(itow(valueHeight) == height, ERROR_MESSAGE_PREFIX L"Height attribute must be an integer in Image element in an UnitTestConfig/ImageData."); + + auto imageData = resource->GetImageByPath(path); + WString binaryKey = GetBinaryKeyFromImage(imageData->GetImage()); + + if (!cachedImageMetadatas->Keys().Contains(binaryKey)) + { + ImageMetadata imageMetadata; + imageMetadata.id = -1; + imageMetadata.frames = Ptr(new List); + { + auto node = Ptr(new glr::json::JsonString); + node->content.value = format; + ConvertJsonToCustomType(node, imageMetadata.format); + } + for (vint frame = 0; frame < valueFrames; frame++) + { + imageMetadata.frames->Add({ {valueWidth,valueHeight} }); + } + + cachedImageMetadatas->Add(binaryKey, imageMetadata); + } + } + } + } + } + + auto binaryKey = GetBinaryKeyFromBinary(*arguments.imageData.Obj()); + vint binaryIndex = cachedImageMetadatas->Keys().IndexOf(binaryKey); + CHECK_ERROR(binaryIndex != -1, ERROR_MESSAGE_PREFIX L"The image is not registered in any UnitTestConfig/ImageData."); + auto metadata = cachedImageMetadatas->Values()[binaryIndex]; + metadata.id = arguments.id; + + loggedTrace.imageCreations->Add(arguments); + loggedTrace.imageMetadatas->Add(metadata); + return metadata; +#undef ERROR_MESSAGE_PREFIX + } + + void UnitTestRemoteProtocol_Rendering::Impl_ImageCreated(vint id, const ImageCreation& arguments) + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::Impl_ImageCreated(vint, const vint&)#" + CHECK_ERROR(!loggedTrace.imageMetadatas->Keys().Contains(arguments.id), ERROR_MESSAGE_PREFIX L"Image with the specified id has been created or used."); + this->GetEvents()->RespondImageCreated(id, MakeImageMetadata(arguments)); +#undef ERROR_MESSAGE_PREFIX + } + + void UnitTestRemoteProtocol_Rendering::Impl_ImageDestroyed(const vint& arguments) + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::Impl_ImageDestroyed(const vint&)#" + CHECK_ERROR(loggedTrace.imageMetadatas->Keys().Contains(arguments), ERROR_MESSAGE_PREFIX L"Image with the specified id has not been created."); + CHECK_ERROR(!removedImageIds.Contains(arguments), ERROR_MESSAGE_PREFIX L"Image with the specified id has been destroyed."); + removedImageIds.Add(arguments); +#undef ERROR_MESSAGE_PREFIX + } + + void UnitTestRemoteProtocol_Rendering::Impl_RendererUpdateElement_ImageFrame(const ElementDesc_ImageFrame& arguments) + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::Impl_RendererUpdateElement_ImageFrame(const ElementDesc_ImageFrame&)#" + if (arguments.imageCreation) + { + auto&& imageCreation = arguments.imageCreation.Value(); + if (!imageCreation.imageDataOmitted) + { + CHECK_ERROR(arguments.imageId && arguments.imageId.Value() != !imageCreation.id, ERROR_MESSAGE_PREFIX L"It should satisfy that (arguments.imageId.Value()id == imageCreation.id)."); + CHECK_ERROR(!loggedTrace.imageMetadatas->Keys().Contains(imageCreation.id), ERROR_MESSAGE_PREFIX L"Image with the specified id has been created."); + CHECK_ERROR(imageCreation.imageData, ERROR_MESSAGE_PREFIX L"When imageDataOmitted == false, imageData should not be null."); + if (!measuringForNextRendering.createdImages) + { + measuringForNextRendering.createdImages = Ptr(new List); + } + measuringForNextRendering.createdImages->Add(MakeImageMetadata(imageCreation)); + } + else + { + CHECK_ERROR(!imageCreation.imageData, ERROR_MESSAGE_PREFIX L"When imageDataOmitted == true, imageData should be null."); + } + } + else if (arguments.imageId) + { + CHECK_ERROR(loggedTrace.imageMetadatas->Keys().Contains(arguments.imageId.Value()), ERROR_MESSAGE_PREFIX L"Image with the specified id has not been created."); + } + + auto element = arguments; + element.imageCreation.Reset(); + REQUEST_RENDERER_UPDATE_ELEMENT2(element, RendererType::ImageFrame); +#undef ERROR_MESSAGE_PREFIX + } + +#undef REQUEST_RENDERER_UPDATE_ELEMENT +#undef REQUEST_RENDERER_UPDATE_ELEMENT2 +} + + /*********************************************************************** .\GUIUNITTESTPROTOCOL_SHARED.CPP ***********************************************************************/ diff --git a/Import/GacUI.UnitTest.h b/Import/GacUI.UnitTest.h index 436b0549..8fa555ed 100644 --- a/Import/GacUI.UnitTest.h +++ b/Import/GacUI.UnitTest.h @@ -76,7 +76,7 @@ namespace vl::presentation::unittest UnitTestScreenConfig globalConfig; public: - UnitTestRemoteProtocolBase(UnitTestScreenConfig _globalConfig) + UnitTestRemoteProtocolBase(const UnitTestScreenConfig& _globalConfig) : globalConfig(_globalConfig) { } @@ -98,6 +98,18 @@ namespace vl::presentation::unittest protected: +#define MESSAGE_NOREQ_NORES(NAME, REQUEST, RESPONSE) void Impl_ ## NAME() { CHECK_FAIL(L"Not Implemented!"); } +#define MESSAGE_NOREQ_RES(NAME, REQUEST, RESPONSE) void Impl_ ## NAME(vint id) { CHECK_FAIL(L"Not Implemented!"); } +#define MESSAGE_REQ_NORES(NAME, REQUEST, RESPONSE) void Impl_ ## NAME(const REQUEST& arguments) { CHECK_FAIL(L"Not Implemented!"); } +#define MESSAGE_REQ_RES(NAME, REQUEST, RESPONSE) void Impl_ ## NAME(vint id, const REQUEST& arguments) { CHECK_FAIL(L"Not Implemented!"); } +#define MESSAGE_HANDLER(NAME, REQUEST, RESPONSE, REQTAG, RESTAG, ...) MESSAGE_ ## REQTAG ## _ ## RESTAG(NAME, REQUEST, RESPONSE) + GACUI_REMOTEPROTOCOL_MESSAGES(MESSAGE_HANDLER) +#undef MESSAGE_HANDLER +#undef MESSAGE_REQ_RES +#undef MESSAGE_REQ_NORES +#undef MESSAGE_NOREQ_RES +#undef MESSAGE_NOREQ_NORES + /*********************************************************************** IGuiRemoteProtocol ***********************************************************************/ @@ -131,8 +143,7 @@ Unit Test Snapsnot and other Utilities namespace vl::presentation::unittest { - template - class UnitTestRemoteProtocol_IO : public TProtocol + class UnitTestRemoteProtocol_IO : public virtual UnitTestRemoteProtocolBase { using GlobalShortcutKey = remoteprotocol::GlobalShortcutKey; using GlobalShortcutKeyList = collections::List; @@ -140,9 +151,8 @@ namespace vl::presentation::unittest bool capturing = false; GlobalShortcutKeyList globalShortcutKeys; - template - UnitTestRemoteProtocol_IO(TArgs&& ...args) - : TProtocol(std::forward(args)...) + UnitTestRemoteProtocol_IO(const UnitTestScreenConfig& _globalConfig) + : UnitTestRemoteProtocolBase(_globalConfig) { } @@ -152,7 +162,7 @@ namespace vl::presentation::unittest IGuiRemoteProtocolMessages (IO) ***********************************************************************/ - void RequestIOUpdateGlobalShortcutKey(const Ptr& arguments) override + void Impl_IOUpdateGlobalShortcutKey(const Ptr& arguments) { if (arguments) { @@ -164,22 +174,22 @@ IGuiRemoteProtocolMessages (IO) } } - void RequestIORequireCapture() override + void Impl_IORequireCapture() { capturing = true; } - void RequestIOReleaseCapture() override + void Impl_IOReleaseCapture() { capturing = false; } - void RequestIOIsKeyPressing(vint id, const VKEY& arguments) override + void Impl_IOIsKeyPressing(vint id, const VKEY& arguments) { CHECK_FAIL(L"Not Implemented!"); } - void RequestIOIsKeyToggled(vint id, const VKEY& arguments) override + void Impl_IOIsKeyToggled(vint id, const VKEY& arguments) { CHECK_FAIL(L"Not Implemented!"); } @@ -208,8 +218,7 @@ namespace vl::presentation::unittest UnitTestRemoteProtocol ***********************************************************************/ - template - class UnitTestRemoteProtocol_IOCommands : public TProtocol + class UnitTestRemoteProtocol_IOCommands : public virtual UnitTestRemoteProtocolBase { protected: Nullable mousePosition; @@ -256,11 +265,21 @@ UnitTestRemoteProtocol return info; } + NativeWindowCharInfo MakeCharInfo(wchar_t ch) + { + NativeWindowCharInfo info; + info.code = ch; + info.ctrl = IsPressing(VKEY::KEY_CONTROL) || IsPressing(VKEY::KEY_LCONTROL) || IsPressing(VKEY::KEY_RCONTROL); + info.shift = IsPressing(VKEY::KEY_SHIFT) || IsPressing(VKEY::KEY_LSHIFT) || IsPressing(VKEY::KEY_RSHIFT); + info.alt = IsPressing(VKEY::KEY_MENU) || IsPressing(VKEY::KEY_LMENU) || IsPressing(VKEY::KEY_RMENU); + info.capslock = capslockToggled; + return info; + } + public: - template - UnitTestRemoteProtocol_IOCommands(TArgs&& ...args) - : TProtocol(std::forward(args)...) + UnitTestRemoteProtocol_IOCommands(const UnitTestScreenConfig& _globalConfig) + : UnitTestRemoteProtocolBase(_globalConfig) { } @@ -284,7 +303,7 @@ Helper Functions return LocationOf(control->GetBoundsComposition(), ratioX, ratioY, offsetX, offsetY); } -#define CLASS_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_IOCommands::" +#define CLASS_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_IOCommands::" /*********************************************************************** Keys @@ -337,6 +356,16 @@ Keys if (ctrl) _KeyUp(VKEY::KEY_CONTROL); } + // Emits plain IOChar events without synthesizing key presses; expand in future iterations when modifiers are required. + void TypeString(const WString& text) + { + if (text.Length() == 0) return; + for (vint i = 0; i < text.Length(); i++) + { + UseEvents().OnIOChar(MakeCharInfo(text[i])); + } + } + /*********************************************************************** Mouse Move Events ***********************************************************************/ @@ -532,8 +561,7 @@ Unit Test Snapsnot and other Utilities namespace vl::presentation::unittest { - template - class UnitTestRemoteProtocol_MainWindow : public TProtocol + class UnitTestRemoteProtocol_MainWindow : public virtual UnitTestRemoteProtocolBase { using WindowSizingConfig = remoteprotocol::WindowSizingConfig; using WindowShowing = remoteprotocol::WindowShowing; @@ -542,9 +570,8 @@ namespace vl::presentation::unittest WindowStyleConfig styleConfig; NativeRect lastRestoredSize; - template - UnitTestRemoteProtocol_MainWindow(TArgs&& ...args) - : TProtocol(std::forward(args)...) + UnitTestRemoteProtocol_MainWindow(const UnitTestScreenConfig& _globalConfig) + : UnitTestRemoteProtocolBase(_globalConfig) { sizingConfig.bounds = { 0,0,0,0 }; sizingConfig.clientBounds = { 0,0,0,0 }; @@ -558,12 +585,12 @@ namespace vl::presentation::unittest IGuiRemoteProtocolMessages (Controller) ***********************************************************************/ - void RequestControllerGetFontConfig(vint id) override + void Impl_ControllerGetFontConfig(vint id) { this->GetEvents()->RespondControllerGetFontConfig(id, this->GetGlobalConfig().fontConfig); } - void RequestControllerGetScreenConfig(vint id) override + void Impl_ControllerGetScreenConfig(vint id) { this->GetEvents()->RespondControllerGetScreenConfig(id, this->GetGlobalConfig().screenConfig); } @@ -572,27 +599,27 @@ IGuiRemoteProtocolMessages (Controller) IGuiRemoteProtocolMessages (Window) ***********************************************************************/ - void RequestWindowGetBounds(vint id) override + void Impl_WindowGetBounds(vint id) { this->GetEvents()->RespondWindowGetBounds(id, sizingConfig); } - void RequestWindowNotifySetTitle(const ::vl::WString& arguments) override + void Impl_WindowNotifySetTitle(const ::vl::WString& arguments) { styleConfig.title = arguments; } - void RequestWindowNotifySetEnabled(const bool& arguments) override + void Impl_WindowNotifySetEnabled(const bool& arguments) { styleConfig.enabled = arguments; } - void RequestWindowNotifySetTopMost(const bool& arguments) override + void Impl_WindowNotifySetTopMost(const bool& arguments) { styleConfig.topMost = arguments; } - void RequestWindowNotifySetShowInTaskBar(const bool& arguments) override + void Impl_WindowNotifySetShowInTaskBar(const bool& arguments) { styleConfig.showInTaskBar = arguments; } @@ -607,29 +634,29 @@ IGuiRemoteProtocolMessages (Window) this->GetEvents()->OnWindowBoundsUpdated(sizingConfig); } - void RequestWindowNotifySetBounds(const NativeRect& arguments) override + void Impl_WindowNotifySetBounds(const NativeRect& arguments) { sizingConfig.bounds = arguments; OnBoundsUpdated(); } - void RequestWindowNotifySetClientSize(const NativeSize& arguments) override + void Impl_WindowNotifySetClientSize(const NativeSize& arguments) { sizingConfig.bounds = { sizingConfig.bounds.LeftTop(), arguments }; OnBoundsUpdated(); } - void RequestWindowNotifySetCustomFrameMode(const bool& arguments) override { styleConfig.customFrameMode = arguments; this->GetEvents()->OnWindowBoundsUpdated(sizingConfig); } - void RequestWindowNotifySetMaximizedBox(const bool& arguments) override { styleConfig.maximizedBox = arguments; this->GetEvents()->OnWindowBoundsUpdated(sizingConfig); } - void RequestWindowNotifySetMinimizedBox(const bool& arguments) override { styleConfig.minimizedBox = arguments; this->GetEvents()->OnWindowBoundsUpdated(sizingConfig); } - void RequestWindowNotifySetBorder(const bool& arguments) override { styleConfig.border = arguments; this->GetEvents()->OnWindowBoundsUpdated(sizingConfig); } - void RequestWindowNotifySetSizeBox(const bool& arguments) override { styleConfig.sizeBox = arguments; this->GetEvents()->OnWindowBoundsUpdated(sizingConfig); } - void RequestWindowNotifySetIconVisible(const bool& arguments) override { styleConfig.iconVisible = arguments; this->GetEvents()->OnWindowBoundsUpdated(sizingConfig); } - void RequestWindowNotifySetTitleBar(const bool& arguments) override { styleConfig.titleBar = arguments; this->GetEvents()->OnWindowBoundsUpdated(sizingConfig); } - void RequestWindowNotifyActivate() override { styleConfig.activated = true; } - void RequestWindowNotifyMinSize(const NativeSize& arguments) override {} + void Impl_WindowNotifySetCustomFrameMode(const bool& arguments) { styleConfig.customFrameMode = arguments; this->GetEvents()->OnWindowBoundsUpdated(sizingConfig); } + void Impl_WindowNotifySetMaximizedBox(const bool& arguments) { styleConfig.maximizedBox = arguments; this->GetEvents()->OnWindowBoundsUpdated(sizingConfig); } + void Impl_WindowNotifySetMinimizedBox(const bool& arguments) { styleConfig.minimizedBox = arguments; this->GetEvents()->OnWindowBoundsUpdated(sizingConfig); } + void Impl_WindowNotifySetBorder(const bool& arguments) { styleConfig.border = arguments; this->GetEvents()->OnWindowBoundsUpdated(sizingConfig); } + void Impl_WindowNotifySetSizeBox(const bool& arguments) { styleConfig.sizeBox = arguments; this->GetEvents()->OnWindowBoundsUpdated(sizingConfig); } + void Impl_WindowNotifySetIconVisible(const bool& arguments) { styleConfig.iconVisible = arguments; this->GetEvents()->OnWindowBoundsUpdated(sizingConfig); } + void Impl_WindowNotifySetTitleBar(const bool& arguments) { styleConfig.titleBar = arguments; this->GetEvents()->OnWindowBoundsUpdated(sizingConfig); } + void Impl_WindowNotifyActivate() { styleConfig.activated = true; } + void Impl_WindowNotifyMinSize(const NativeSize& arguments) {} - void RequestWindowNotifyShow(const WindowShowing& arguments) override + void Impl_WindowNotifyShow(const WindowShowing& arguments) { styleConfig.activated = arguments.activate; if (sizingConfig.sizeState != arguments.sizeState) @@ -686,6 +713,47 @@ Unit Test Snapsnot and other Utilities namespace vl::presentation::unittest { +/*********************************************************************** +DocumentParagraphState +***********************************************************************/ + + struct DocumentParagraphCharLayout + { + double x; // X position of character start + double width; // Character width + vint lineIndex; // Which line this character belongs to + vint height; // Character height (font size or inline object height) + vint baseline; // Distance from top to baseline (for alignment) + bool isInlineObject; // True if this position is part of an inline object + }; + + struct DocumentParagraphLineInfo + { + vint startPos; // Text position of line start (inclusive) + vint endPos; // Text position of line end (exclusive) + vint y; // Y coordinate of line top + vint height; // Line height (computed from baseline alignment) + vint baseline; // Line baseline position from line top + vint width; // Line width (for alignment calculation) + }; + + struct DocumentParagraphState + { + WString text; + bool wrapLine = false; + vint maxWidth = -1; + remoteprotocol::ElementHorizontalAlignment alignment = remoteprotocol::ElementHorizontalAlignment::Left; + + elements::DocumentTextRunPropertyMap textRuns; + elements::DocumentInlineObjectRunPropertyMap inlineObjectRuns; + elements::DocumentRunPropertyMap mergedRuns; + + collections::List characterLayouts; + collections::List lines; + Size cachedSize; + collections::Dictionary cachedInlineObjectBounds; + }; + /*********************************************************************** UnitTestRemoteProtocol ***********************************************************************/ @@ -703,8 +771,7 @@ UnitTestRemoteProtocol using UnitTestLoggedFrameList = collections::List>; - template - class UnitTestRemoteProtocol_Rendering : public TProtocol + class UnitTestRemoteProtocol_Rendering : public virtual UnitTestRemoteProtocolBase { using IdSet = collections::SortedList; using Base64ToImageMetadataMap = collections::Dictionary; @@ -730,6 +797,8 @@ UnitTestRemoteProtocol remoteprotocol::ElementMeasurings measuringForNextRendering; regex::Regex regexCrLf{ L"/n|/r(/n)?" }; + collections::Dictionary> paragraphStates; + void ResetCreatedObjects() { loggedTrace.createdElements = Ptr(new collections::Dictionary); @@ -739,9 +808,8 @@ UnitTestRemoteProtocol } public: - template - UnitTestRemoteProtocol_Rendering(TArgs&& ...args) - : TProtocol(std::forward(args)...) + UnitTestRemoteProtocol_Rendering(const UnitTestScreenConfig& _globalConfig) + : UnitTestRemoteProtocolBase(_globalConfig) { ResetCreatedObjects(); loggedTrace.frames = Ptr(new collections::List); @@ -753,240 +821,34 @@ UnitTestRemoteProtocol IGuiRemoteProtocolMessages (Rendering) ***********************************************************************/ - Ptr GetLastRenderingFrame() - { -#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::GetLastRenderingCommands()#" - CHECK_ERROR(lastRenderingCommandsOpening, ERROR_MESSAGE_PREFIX L"The latest frame of commands is not accepting new commands."); - return loggedFrames[loggedFrames.Count() - 1]; -#undef ERROR_MESSAGE_PREFIX - } - - Ptr TryGetLastRenderingFrameAndReset() - { - if (loggedFrames.Count() == 0) return nullptr; - if (!lastRenderingCommandsOpening) return nullptr; - lastRenderingCommandsOpening = false; - return loggedFrames[loggedFrames.Count() - 1]; - } - - void RequestRendererBeginRendering(const remoteprotocol::ElementBeginRendering& arguments) override - { - receivedDomDiffMessage = false; - receivedElementMessage = false; - lastRenderingCommandsOpening = true; - auto frame = Ptr(new UnitTestLoggedFrame); - frame->frameId = arguments.frameId; - loggedFrames.Add(frame); - } - - void RequestRendererEndRendering(vint id) override - { -#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::RequestRendererEndRendering(vint)#" - CHECK_ERROR(receivedElementMessage || receivedDomDiffMessage, ERROR_MESSAGE_PREFIX L"Either dom-diff or element message should be sent before this message."); - - auto lastFrame = GetLastRenderingFrame(); - if (receivedElementMessage) - { - lastFrame->renderingDom = renderingDomBuilder.RequestRendererEndRendering(); - } - if (receivedDomDiffMessage) - { - // receivedDom will be updated in RequestRendererRenderDomDiff - // store a copy to log - lastFrame->renderingDom = CopyDom(receivedDom); - } - this->GetEvents()->RespondRendererEndRendering(id, measuringForNextRendering); - measuringForNextRendering = {}; -#undef ERROR_MESSAGE_PREFIX - } + Ptr GetLastRenderingFrame(); + Ptr TryGetLastRenderingFrameAndReset(); + void Impl_RendererBeginRendering(const remoteprotocol::ElementBeginRendering& arguments); + void Impl_RendererEndRendering(vint id); /*********************************************************************** IGuiRemoteProtocolMessages (Rendering - Element) ***********************************************************************/ - void RequestRendererBeginBoundary(const remoteprotocol::ElementBoundary& arguments) override - { -#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::RequestRendererBeginBoundary(const ElementBoundary&)#" - CHECK_ERROR(!receivedDomDiffMessage, ERROR_MESSAGE_PREFIX L"This message could not be used with dom-diff messages in the same rendering cycle."); - if (!receivedElementMessage) - { - renderingDomBuilder.RequestRendererBeginRendering(); - receivedElementMessage = true; - } - - renderingDomBuilder.RequestRendererBeginBoundary(arguments); - - glr::json::JsonFormatting formatting; - formatting.spaceAfterColon = true; - formatting.spaceAfterComma = true; - formatting.crlf = false; - formatting.compact = true; - - GetLastRenderingFrame()->renderingCommandsLog.Add(L"RequestRendererBeginBoundary: " + stream::GenerateToStream([&](stream::TextWriter& writer) - { - auto jsonLog = remoteprotocol::ConvertCustomTypeToJson(arguments); - writer.WriteString(glr::json::JsonToString(jsonLog, formatting)); - })); -#undef ERROR_MESSAGE_PREFIX - } - - void RequestRendererEndBoundary() override - { -#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::RequestRendererEndBoundary()#" - CHECK_ERROR(!receivedDomDiffMessage, ERROR_MESSAGE_PREFIX L"This message could not be used with dom-diff messages in the same rendering cycle."); - if (!receivedElementMessage) - { - renderingDomBuilder.RequestRendererBeginRendering(); - receivedElementMessage = true; - } - - renderingDomBuilder.RequestRendererEndBoundary(); - GetLastRenderingFrame()->renderingCommandsLog.Add(L"RequestRendererEndBoundary"); -#undef ERROR_MESSAGE_PREFIX - } - - void EnsureRenderedElement(vint id, Rect bounds) - { -#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::EnsureRenderedElement(id&)#" - - vint index = loggedTrace.createdElements->Keys().IndexOf(id); - CHECK_ERROR(index != -1, ERROR_MESSAGE_PREFIX L"Renderer with the specified id has not been created."); - auto rendererType = loggedTrace.createdElements->Values()[index]; - if (rendererType == remoteprotocol::RendererType::FocusRectangle || rendererType == remoteprotocol::RendererType::Raw) - { - // FocusRectangle or Raw does not have a ElementDesc - return; - } - - index = lastElementDescs.Keys().IndexOf(id); - CHECK_ERROR(index != -1, ERROR_MESSAGE_PREFIX L"Renderer with the specified id has not been updated after created."); - lastElementDescs.Values()[index].Apply(Overloading( - [](remoteprotocol::RendererType) - { - CHECK_FAIL(ERROR_MESSAGE_PREFIX L"Renderer with the specified id has not been updated after created."); - }, - [&](const remoteprotocol::ElementDesc_SolidLabel& solidLabel) - { - CalculateSolidLabelSizeIfNecessary(bounds.Width(), bounds.Height(), solidLabel); - }, - [&](const auto& element) - { - })); - -#undef ERROR_MESSAGE_PREFIX - } - - void RequestRendererRenderElement(const remoteprotocol::ElementRendering& arguments) override - { -#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::RequestRendererRenderElement(const ElementRendering&)#" - CHECK_ERROR(!receivedDomDiffMessage, ERROR_MESSAGE_PREFIX L"This message could not be used with dom-diff messages in the same rendering cycle."); - if (!receivedElementMessage) - { - renderingDomBuilder.RequestRendererBeginRendering(); - receivedElementMessage = true; - } - - { - renderingDomBuilder.RequestRendererRenderElement(arguments); - - glr::json::JsonFormatting formatting; - formatting.spaceAfterColon = true; - formatting.spaceAfterComma = true; - formatting.crlf = false; - formatting.compact = true; - GetLastRenderingFrame()->renderingCommandsLog.Add(L"RequestRendererRenderElement: " + stream::GenerateToStream([&](stream::TextWriter& writer) - { - auto jsonLog = remoteprotocol::ConvertCustomTypeToJson(arguments); - writer.WriteString(glr::json::JsonToString(jsonLog, formatting)); - })); - } - - EnsureRenderedElement(arguments.id, arguments.bounds); -#undef ERROR_MESSAGE_PREFIX - } + void Impl_RendererBeginBoundary(const remoteprotocol::ElementBoundary& arguments); + void Impl_RendererEndBoundary(); + void EnsureRenderedElement(vint id, Rect bounds); + void Impl_RendererRenderElement(const remoteprotocol::ElementRendering& arguments); /*********************************************************************** IGuiRemoteProtocolMessages (Rendering - Dom) ***********************************************************************/ - void CalculateSolidLabelSizesIfNecessary(Ptr dom) - { - if (dom->content.element) - { - EnsureRenderedElement(dom->content.element.Value(), dom->content.bounds); - } - if (dom->children) - { - for (auto child : *dom->children.Obj()) - { - CalculateSolidLabelSizesIfNecessary(child); - } - } - } - - void RequestRendererRenderDom(const Ptr& arguments) override - { -#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::RequestRendererRenderElement(const RenderingDom&)#" - CHECK_ERROR(!receivedElementMessage, ERROR_MESSAGE_PREFIX L"This message could not be used with element messages in the same rendering cycle."); - if (!receivedDomDiffMessage) - { - receivedDomDiffMessage = true; - } - - receivedDom = arguments; - remoteprotocol::BuildDomIndex(receivedDom, receivedDomIndex); - CalculateSolidLabelSizesIfNecessary(receivedDom); -#undef ERROR_MESSAGE_PREFIX - } - - void RequestRendererRenderDomDiff(const remoteprotocol::RenderingDom_DiffsInOrder& arguments) override - { -#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::RequestRendererRenderElement(const RenderingDom_DiffsInOrder&)#" - CHECK_ERROR(!receivedElementMessage, ERROR_MESSAGE_PREFIX L"This message could not be used with element messages in the same rendering cycle."); - if (!receivedDomDiffMessage) - { - receivedDomDiffMessage = true; - } - - remoteprotocol::UpdateDomInplace(receivedDom, receivedDomIndex, arguments); - GetLastRenderingFrame()->renderingDiffs = arguments; - CalculateSolidLabelSizesIfNecessary(receivedDom); -#undef ERROR_MESSAGE_PREFIX - } + void CalculateSolidLabelSizesIfNecessary(Ptr dom); + void Impl_RendererRenderDom(const Ptr& arguments); + void Impl_RendererRenderDomDiff(const remoteprotocol::RenderingDom_DiffsInOrder& arguments); /*********************************************************************** IGuiRemoteProtocolMessages (Elements) ***********************************************************************/ - void RequestRendererCreated(const Ptr>& arguments) override - { -#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::RequestRendererCreated(const Ptr>&)#" - if (arguments) - { - for (auto creation : *arguments.Obj()) - { - CHECK_ERROR(!loggedTrace.createdElements->Keys().Contains(creation.id), ERROR_MESSAGE_PREFIX L"Renderer with the specified id has been created or used."); - loggedTrace.createdElements->Add(creation.id, creation.type); - } - } -#undef ERROR_MESSAGE_PREFIX - } - - void RequestRendererDestroyed(const Ptr>& arguments) override - { -#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::RequestRendererDestroyed(const Ptr>&)#" - if (arguments) - { - for (auto id : *arguments.Obj()) - { - CHECK_ERROR(loggedTrace.createdElements->Keys().Contains(id), ERROR_MESSAGE_PREFIX L"Renderer with the specified id has not been created."); - CHECK_ERROR(!removedElementIds.Contains(id), ERROR_MESSAGE_PREFIX L"Renderer with the specified id has been destroyed."); - removedElementIds.Add(id); - lastElementDescs.Remove(id); - } - } -#undef ERROR_MESSAGE_PREFIX - } + void Impl_RendererCreated(const Ptr>& arguments); + void Impl_RendererDestroyed(const Ptr>& arguments); template void RequestRendererUpdateElement(const TElementDesc& arguments, const wchar_t* emWrongId, const wchar_t* emWrongType) @@ -997,455 +859,51 @@ IGuiRemoteProtocolMessages (Elements) lastElementDescs.Set(arguments.id, arguments); } -#define REQUEST_RENDERER_UPDATE_ELEMENT2(ARGUMENTS, RENDERER_TYPE)\ - RequestRendererUpdateElement(\ - ARGUMENTS,\ - ERROR_MESSAGE_PREFIX L"Renderer with the specified id has not been created.",\ - ERROR_MESSAGE_PREFIX L"Renderer with the specified id is not of the expected type."\ - ) - -#define REQUEST_RENDERER_UPDATE_ELEMENT(RENDERER_TYPE) REQUEST_RENDERER_UPDATE_ELEMENT2(arguments, RENDERER_TYPE) - - void RequestRendererUpdateElement_SolidBorder(const remoteprotocol::ElementDesc_SolidBorder& arguments) override - { -#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::RequestRendererUpdateElement_SolidBorder::RequestRendererCreated(const ElementDesc_SolidBorder&)#" - REQUEST_RENDERER_UPDATE_ELEMENT(remoteprotocol::RendererType::SolidBorder); -#undef ERROR_MESSAGE_PREFIX - } - - void RequestRendererUpdateElement_SinkBorder(const remoteprotocol::ElementDesc_SinkBorder& arguments) override - { -#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::RequestRendererUpdateElement_SinkBorder::RequestRendererCreated(const ElementDesc_SinkBorder&)#" - REQUEST_RENDERER_UPDATE_ELEMENT(remoteprotocol::RendererType::SinkBorder); -#undef ERROR_MESSAGE_PREFIX - } - - void RequestRendererUpdateElement_SinkSplitter(const remoteprotocol::ElementDesc_SinkSplitter& arguments) override - { -#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::RequestRendererUpdateElement_SinkSplitter::RequestRendererCreated(const ElementDesc_SinkSplitter&)#" - REQUEST_RENDERER_UPDATE_ELEMENT(remoteprotocol::RendererType::SinkSplitter); -#undef ERROR_MESSAGE_PREFIX - } - - void RequestRendererUpdateElement_SolidBackground(const remoteprotocol::ElementDesc_SolidBackground& arguments) override - { -#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::RequestRendererUpdateElement_SolidBackground::RequestRendererCreated(const ElementDesc_SolidBackground&)#" - REQUEST_RENDERER_UPDATE_ELEMENT(remoteprotocol::RendererType::SolidBackground); -#undef ERROR_MESSAGE_PREFIX - } - - void RequestRendererUpdateElement_GradientBackground(const remoteprotocol::ElementDesc_GradientBackground& arguments) override - { -#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::RequestRendererUpdateElement_GradientBackground::RequestRendererCreated(const ElementDesc_GradientBackground&)#" - REQUEST_RENDERER_UPDATE_ELEMENT(remoteprotocol::RendererType::GradientBackground); -#undef ERROR_MESSAGE_PREFIX - } - - void RequestRendererUpdateElement_InnerShadow(const remoteprotocol::ElementDesc_InnerShadow& arguments) override - { -#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::RequestRendererUpdateElement_InnerShadow::RequestRendererCreated(const ElementDesc_InnerShadow&)#" - REQUEST_RENDERER_UPDATE_ELEMENT(remoteprotocol::RendererType::InnerShadow); -#undef ERROR_MESSAGE_PREFIX - } - - void RequestRendererUpdateElement_Polygon(const remoteprotocol::ElementDesc_Polygon& arguments) override - { -#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::RequestRendererUpdateElement_Polygon::RequestRendererCreated(const ElementDesc_Polygon&)#" - REQUEST_RENDERER_UPDATE_ELEMENT(remoteprotocol::RendererType::Polygon); -#undef ERROR_MESSAGE_PREFIX - } + void Impl_RendererUpdateElement_SolidBorder(const remoteprotocol::ElementDesc_SolidBorder& arguments); + void Impl_RendererUpdateElement_SinkBorder(const remoteprotocol::ElementDesc_SinkBorder& arguments); + void Impl_RendererUpdateElement_SinkSplitter(const remoteprotocol::ElementDesc_SinkSplitter& arguments); + void Impl_RendererUpdateElement_SolidBackground(const remoteprotocol::ElementDesc_SolidBackground& arguments); + void Impl_RendererUpdateElement_GradientBackground(const remoteprotocol::ElementDesc_GradientBackground& arguments); + void Impl_RendererUpdateElement_InnerShadow(const remoteprotocol::ElementDesc_InnerShadow& arguments); + void Impl_RendererUpdateElement_Polygon(const remoteprotocol::ElementDesc_Polygon& arguments); /*********************************************************************** IGuiRemoteProtocolMessages (Elements - SolidLabel) ***********************************************************************/ - void CalculateSolidLabelSizeIfNecessary(vint width, vint height, const remoteprotocol::ElementDesc_SolidLabel& arguments) - { -#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::RequestRendererUpdateElement_SolidLabel::CalculateSolidLabelSizeIfNecessary(vint, vint, const ElementDesc_SolidLabel&)#" - - if (arguments.measuringRequest) - { - switch (arguments.measuringRequest.Value()) - { - case remoteprotocol::ElementSolidLabelMeasuringRequest::FontHeight: - CHECK_ERROR(arguments.font, ERROR_MESSAGE_PREFIX L"Font is missing for calculating font height."); - if (!measuringForNextRendering.fontHeights) - { - measuringForNextRendering.fontHeights = Ptr(new collections::List); - } - { - remoteprotocol::ElementMeasuring_FontHeight measuring; - measuring.fontFamily = arguments.font.Value().fontFamily; - measuring.fontSize = arguments.font.Value().size; - measuring.height = measuring.fontSize + 4; - measuringForNextRendering.fontHeights->Add(measuring); - } - break; - case remoteprotocol::ElementSolidLabelMeasuringRequest::TotalSize: - { - // font and text has already been verified exist in RequestRendererUpdateElement_SolidLabel - vint size = arguments.font.Value().size; - auto text = arguments.text.Value(); - vint textWidth = 0; - vint textHeight = 0; - - collections::List lines; - { - collections::List> matches; - regexCrLf.Split(text, true, matches); - - if (matches.Count() == 0) - { - // when there is no text, measure a space - lines.Add(WString::Unmanaged(L" ")); - } - else if (arguments.multiline) - { - // add all lines, and if any line is empty, measure a space - for (auto match : matches) - { - auto line = match->Result().Value(); - lines.Add(line.Length() ? line : WString::Unmanaged(L" ")); - } - } - else - { - lines.Add(stream::GenerateToStream([&](stream::TextWriter& writer) - { - for (auto [match, index] : indexed(matches)) - { - if (index > 0) writer.WriteChar(L' '); - auto line = match->Result().Value(); - writer.WriteString(line); - } - })); - if(lines[0].Length() == 0) - { - // when there is no text, measure a space - lines[0] = WString::Unmanaged(L" "); - } - } - } - - if (arguments.wrapLine) - { - // width of the text is 0 - // insert a line break when there is no space horizontally - vint totalLines = 0; - for (auto&& line : lines) - { - if (line.Length() == 0) - { - totalLines++; - continue; - } - - double accumulatedWidth = 0; - for (vint i = 0; i < line.Length(); i++) - { - auto c = line[i]; - auto w = (c < 128 ? 0.6 : 1) * size; - if (accumulatedWidth + w > width) - { - if (accumulatedWidth == 0) - { - totalLines++; - } - else - { - totalLines++; - accumulatedWidth = w; - } - } - else - { - accumulatedWidth += w; - } - } - if (accumulatedWidth > 0) - { - totalLines++; - } - } - textHeight = 4 + size * totalLines; - } - else - { - // width of the text is width of the longest line - textWidth = (vint)(size * From(lines) - .Select([](const WString& line) - { - double sum = 0; - for (vint i = 0; i < line.Length(); i++) - { - auto c = line[i]; - sum += (c < 128 ? 0.6 : 1); - } - return sum; - }) - .Max()); - textHeight = 4 + size * lines.Count(); - } - - if (!measuringForNextRendering.minSizes) - { - measuringForNextRendering.minSizes = Ptr(new collections::List); - } - { - remoteprotocol::ElementMeasuring_ElementMinSize measuring; - measuring.id = arguments.id; - measuring.minSize = { textWidth,textHeight }; - measuringForNextRendering.minSizes->Add(measuring); - } - } - break; - default: - CHECK_FAIL(L"Unknown value of ElementSolidLabelMeasuringRequest."); - } - } -#undef ERROR_MESSAGE_PREFIX - } - - void RequestRendererUpdateElement_SolidLabel(const remoteprotocol::ElementDesc_SolidLabel& arguments) override - { -#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::RequestRendererUpdateElement_SolidLabel::RequestRendererCreated(const ElementDesc_SolidLabel&)#" - auto element = arguments; - if (!element.font || !element.text) - { - vint index = loggedTrace.createdElements->Keys().IndexOf(element.id); - CHECK_ERROR(index != -1, ERROR_MESSAGE_PREFIX L"Renderer with the specified id has not been created."); - - auto rendererType = loggedTrace.createdElements->Values()[index]; - CHECK_ERROR(rendererType == remoteprotocol::RendererType::SolidLabel, ERROR_MESSAGE_PREFIX L"Renderer with the specified id is not of the expected type."); - - index = lastElementDescs.Keys().IndexOf(arguments.id); - if (index != -1) - { - auto solidLabel = lastElementDescs.Values()[index].TryGet(); - CHECK_ERROR(solidLabel, ERROR_MESSAGE_PREFIX L"Renderer with the specified id is not of the expected type."); - if (!element.font) element.font = solidLabel->font; - if (!element.text) element.text = solidLabel->text; - } - else - { - if (!element.font) element.font = FontProperties(); - if (!element.text) element.text = WString::Empty; - } - } - REQUEST_RENDERER_UPDATE_ELEMENT2(element, remoteprotocol::RendererType::SolidLabel); -#undef ERROR_MESSAGE_PREFIX - } + void CalculateSolidLabelSizeIfNecessary(vint width, vint height, const remoteprotocol::ElementDesc_SolidLabel& arguments); + void Impl_RendererUpdateElement_SolidLabel(const remoteprotocol::ElementDesc_SolidLabel& arguments); /*********************************************************************** IGuiRemoteProtocolMessages (Elements - Image) ***********************************************************************/ - WString GetBinaryKeyFromBinary(stream::IStream& binary) - { - stream::MemoryStream base64WStringStream; - { - stream::UtfGeneralEncoder utf8ToWCharEncoder; - stream::EncoderStream utf8ToWCharStream(base64WStringStream, utf8ToWCharEncoder); - stream::Utf8Base64Encoder binaryToBase64Utf8Encoder; - stream::EncoderStream binaryToBase64Utf8Stream(utf8ToWCharStream, binaryToBase64Utf8Encoder); - binary.SeekFromBegin(0); - stream::CopyStream(binary, binaryToBase64Utf8Stream); - } - { - base64WStringStream.SeekFromBegin(0); - stream::StreamReader reader(base64WStringStream); - return reader.ReadToEnd(); - } - } - - WString GetBinaryKeyFromImage(Ptr image) - { -#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::GetBinaryKeyFromImage(Ptr)#" - auto remoteImage = image.Cast(); - CHECK_ERROR(remoteImage, ERROR_MESSAGE_PREFIX L"The image object must be GuiRemoteGraphicsImage."); - return GetBinaryKeyFromBinary(remoteImage->GetBinaryData()); -#undef ERROR_MESSAGE_PREFIX - } - - remoteprotocol::ImageMetadata MakeImageMetadata(const remoteprotocol::ImageCreation& arguments) - { -#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::MakeImageMetadata(const remoteprotocol::ImageCreation)#" - if (!cachedImageMetadatas) - { - cachedImageMetadatas = Ptr(new Base64ToImageMetadataMap); - for (auto resource : GetResourceManager()->GetLoadedResources()) - { - if (auto xmlImageData = resource->GetValueByPath(WString::Unmanaged(L"UnitTestConfig/ImageData")).Cast()) - { - for (auto elementImage : glr::xml::XmlGetElements(xmlImageData->rootElement, WString::Unmanaged(L"Image"))) - { - WString path, format, frames = WString::Unmanaged(L"1"), width, height; - - auto attPath = glr::xml::XmlGetAttribute(elementImage.Obj(), WString::Unmanaged(L"Path")); - auto attFormat = glr::xml::XmlGetAttribute(elementImage.Obj(), WString::Unmanaged(L"Format")); - auto attFrames = glr::xml::XmlGetAttribute(elementImage.Obj(), WString::Unmanaged(L"Frames")); - auto attWidth = glr::xml::XmlGetAttribute(elementImage.Obj(), WString::Unmanaged(L"Width")); - auto attHeight = glr::xml::XmlGetAttribute(elementImage.Obj(), WString::Unmanaged(L"Height")); - - CHECK_ERROR(attPath, ERROR_MESSAGE_PREFIX L"Missing Path attribute in Image element in an UnitTestConfig/ImageData."); - CHECK_ERROR(attFormat, ERROR_MESSAGE_PREFIX L"Missing Format attribute in Image element in an UnitTestConfig/ImageData."); - CHECK_ERROR(attWidth, ERROR_MESSAGE_PREFIX L"Missing Width attribute in Image element in an UnitTestConfig/ImageData."); - CHECK_ERROR(attHeight, ERROR_MESSAGE_PREFIX L"Missing Height attribute in Image element in an UnitTestConfig/ImageData."); - - path = attPath->value.value; - format = attFormat->value.value; - width = attWidth->value.value; - height = attHeight->value.value; - if (attFrames) frames = attFrames->value.value; - - vint valueFrames = wtoi(frames); - vint valueWidth = wtoi(width); - vint valueHeight = wtoi(height); - - CHECK_ERROR(itow(valueFrames) == frames, ERROR_MESSAGE_PREFIX L"Frames attribute must be an integer in Image element in an UnitTestConfig/ImageData."); - CHECK_ERROR(itow(valueWidth) == width, ERROR_MESSAGE_PREFIX L"Width attribute must be an integer in Image element in an UnitTestConfig/ImageData."); - CHECK_ERROR(itow(valueHeight) == height, ERROR_MESSAGE_PREFIX L"Height attribute must be an integer in Image element in an UnitTestConfig/ImageData."); - - auto imageData = resource->GetImageByPath(path); - WString binaryKey = GetBinaryKeyFromImage(imageData->GetImage()); - - if (!cachedImageMetadatas->Keys().Contains(binaryKey)) - { - remoteprotocol::ImageMetadata imageMetadata; - imageMetadata.id = -1; - imageMetadata.frames = Ptr(new collections::List); - { - auto node = Ptr(new glr::json::JsonString); - node->content.value = format; - remoteprotocol::ConvertJsonToCustomType(node, imageMetadata.format); - } - for (vint frame = 0; frame < valueFrames; frame++) - { - imageMetadata.frames->Add({ {valueWidth,valueHeight} }); - } - - cachedImageMetadatas->Add(binaryKey, imageMetadata); - } - } - } - } - } - - auto binaryKey = GetBinaryKeyFromBinary(*arguments.imageData.Obj()); - vint binaryIndex = cachedImageMetadatas->Keys().IndexOf(binaryKey); - CHECK_ERROR(binaryIndex != -1, ERROR_MESSAGE_PREFIX L"The image is not registered in any UnitTestConfig/ImageData."); - auto metadata = cachedImageMetadatas->Values()[binaryIndex]; - metadata.id = arguments.id; - - loggedTrace.imageCreations->Add(arguments); - loggedTrace.imageMetadatas->Add(metadata); - return metadata; -#undef ERROR_MESSAGE_PREFIX - } - - void RequestImageCreated(vint id, const remoteprotocol::ImageCreation& arguments) override - { -#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::RequestImageCreated(vint, const vint&)#" - CHECK_ERROR(!loggedTrace.imageMetadatas->Keys().Contains(arguments.id), ERROR_MESSAGE_PREFIX L"Image with the specified id has been created or used."); - this->GetEvents()->RespondImageCreated(id, MakeImageMetadata(arguments)); -#undef ERROR_MESSAGE_PREFIX - } - - void RequestImageDestroyed(const vint& arguments) override - { -#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Rendering::RequestImageDestroyed(const vint&)#" - CHECK_ERROR(loggedTrace.imageMetadatas->Keys().Contains(arguments), ERROR_MESSAGE_PREFIX L"Image with the specified id has not been created."); - CHECK_ERROR(!removedImageIds.Contains(arguments), ERROR_MESSAGE_PREFIX L"Image with the specified id has been destroyed."); - removedImageIds.Add(arguments); -#undef ERROR_MESSAGE_PREFIX - } - - void RequestRendererUpdateElement_ImageFrame(const remoteprotocol::ElementDesc_ImageFrame& arguments) override - { -#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::RequestRendererUpdateElement_ImageFrame::RequestRendererCreated(const ElementDesc_ImageFrame&)#" - if (arguments.imageCreation) - { - auto&& imageCreation = arguments.imageCreation.Value(); - if (!imageCreation.imageDataOmitted) - { - CHECK_ERROR(arguments.imageId && arguments.imageId.Value() != !imageCreation.id, ERROR_MESSAGE_PREFIX L"It should satisfy that (arguments.imageId.Value()id == imageCreation.id)."); - CHECK_ERROR(!loggedTrace.imageMetadatas->Keys().Contains(imageCreation.id), ERROR_MESSAGE_PREFIX L"Image with the specified id has been created."); - CHECK_ERROR(imageCreation.imageData, ERROR_MESSAGE_PREFIX L"When imageDataOmitted == false, imageData should not be null."); - if (!measuringForNextRendering.createdImages) - { - measuringForNextRendering.createdImages = Ptr(new collections::List); - } - measuringForNextRendering.createdImages->Add(MakeImageMetadata(imageCreation)); - } - else - { - CHECK_ERROR(!imageCreation.imageData, ERROR_MESSAGE_PREFIX L"When imageDataOmitted == true, imageData should be null."); - } - } - else if (arguments.imageId) - { - CHECK_ERROR(loggedTrace.imageMetadatas->Keys().Contains(arguments.imageId.Value()), ERROR_MESSAGE_PREFIX L"Image with the specified id has not been created."); - } - - auto element = arguments; - element.imageCreation.Reset(); - REQUEST_RENDERER_UPDATE_ELEMENT2(element, remoteprotocol::RendererType::ImageFrame); -#undef ERROR_MESSAGE_PREFIX - } + WString GetBinaryKeyFromBinary(stream::IStream& binary); + WString GetBinaryKeyFromImage(Ptr image); + remoteprotocol::ImageMetadata MakeImageMetadata(const remoteprotocol::ImageCreation& arguments); + void Impl_ImageCreated(vint id, const remoteprotocol::ImageCreation& arguments); + void Impl_ImageDestroyed(const vint& arguments); + void Impl_RendererUpdateElement_ImageFrame(const remoteprotocol::ElementDesc_ImageFrame& arguments); /*********************************************************************** IGuiRemoteProtocolMessages (Elements - Document) ***********************************************************************/ - void RequestRendererUpdateElement_DocumentParagraph(vint id, const remoteprotocol::ElementDesc_DocumentParagraph& arguments) override - { - CHECK_FAIL(L"Not implemented."); - } - - void RequestDocumentParagraph_GetCaret(vint id, const remoteprotocol::GetCaretRequest& arguments) override - { - CHECK_FAIL(L"Not implemented."); - } - - void RequestDocumentParagraph_GetCaretBounds(vint id, const remoteprotocol::GetCaretBoundsRequest& arguments) override - { - CHECK_FAIL(L"Not implemented."); - } - - void RequestDocumentParagraph_GetInlineObjectFromPoint(vint id, const Point& arguments) override - { - CHECK_FAIL(L"Not implemented."); - } - - void RequestDocumentParagraph_GetNearestCaretFromTextPos(vint id, const remoteprotocol::GetCaretBoundsRequest& arguments) override - { - CHECK_FAIL(L"Not implemented."); - } - - void RequestDocumentParagraph_IsValidCaret(vint id, const vint& arguments) override - { - CHECK_FAIL(L"Not implemented."); - } - - void RequestDocumentParagraph_OpenCaret(const remoteprotocol::OpenCaretRequest& arguments) override - { - CHECK_FAIL(L"Not implemented."); - } - - void RequestDocumentParagraph_CloseCaret() override - { - CHECK_FAIL(L"Not implemented."); - } - -#undef REQUEST_RENDERER_UPDATE_ELEMENT -#undef REQUEST_RENDERER_UPDATE_ELEMENT2 + void Impl_RendererUpdateElement_DocumentParagraph(vint id, const remoteprotocol::ElementDesc_DocumentParagraph& arguments); + void Impl_DocumentParagraph_GetCaret(vint id, const remoteprotocol::GetCaretRequest& arguments); + void Impl_DocumentParagraph_GetCaretBounds(vint id, const remoteprotocol::GetCaretBoundsRequest& arguments); + void Impl_DocumentParagraph_GetInlineObjectFromPoint(vint id, const remoteprotocol::GetInlineObjectFromPointRequest & arguments); + void Impl_DocumentParagraph_GetNearestCaretFromTextPos(vint id, const remoteprotocol::GetCaretBoundsRequest& arguments); + void Impl_DocumentParagraph_IsValidCaret(vint id, const remoteprotocol::IsValidCaretRequest& arguments); + void Impl_DocumentParagraph_OpenCaret(const remoteprotocol::OpenCaretRequest& arguments); + void Impl_DocumentParagraph_CloseCaret(const vint& arguments); }; } #endif /*********************************************************************** -.\GUIUNITTESTPROTOCOL_LOGGING.H +.\GUIUNITTESTPROTOCOL.H ***********************************************************************/ /*********************************************************************** Vczh Library++ 3.0 @@ -1453,28 +911,44 @@ Developer: Zihan Chen(vczh) Unit Test Snapsnot and other Utilities ***********************************************************************/ -#ifndef VCZH_PRESENTATION_GUIUNITTESTPROTOCOL_LOGGING -#define VCZH_PRESENTATION_GUIUNITTESTPROTOCOL_LOGGING +#ifndef VCZH_PRESENTATION_GUIUNITTESTPROTOCOL +#define VCZH_PRESENTATION_GUIUNITTESTPROTOCOL namespace vl::presentation::unittest { +/*********************************************************************** +UnitTestFrameworkConfig +***********************************************************************/ + + struct UnitTestFrameworkConfig + { + filesystem::FilePath snapshotFolder; + filesystem::FilePath resourceFolder; + }; + + extern const UnitTestFrameworkConfig& GetUnitTestFrameworkConfig(); + /*********************************************************************** UnitTestRemoteProtocol ***********************************************************************/ - - template - class UnitTestRemoteProtocol_Logging : public TProtocol + + class UnitTestRemoteProtocolFeatures : + public UnitTestRemoteProtocol_MainWindow, + public UnitTestRemoteProtocol_IO, + public UnitTestRemoteProtocol_Rendering, + public UnitTestRemoteProtocol_IOCommands { protected: + bool stopped = false; bool everRendered = false; Ptr candidateFrame; vint idlingCounter = 0; bool LogRenderingResult() { -#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol_Logging::ProcessRemoteEvents()#" +#define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocolFeatures::LogRenderingResult()#" if (auto lastFrame = this->TryGetLastRenderingFrameAndReset()) { candidateFrame = lastFrame; @@ -1514,10 +988,11 @@ UnitTestRemoteProtocol } public: - - template - UnitTestRemoteProtocol_Logging(TArgs&& ...args) - : TProtocol(std::forward(args)...) + UnitTestRemoteProtocolFeatures(const UnitTestScreenConfig& _globalConfig) + : UnitTestRemoteProtocol_MainWindow(_globalConfig) + , UnitTestRemoteProtocol_IO(_globalConfig) + , UnitTestRemoteProtocol_Rendering(_globalConfig) + , UnitTestRemoteProtocol_IOCommands(_globalConfig) { } @@ -1530,67 +1005,24 @@ UnitTestRemoteProtocol { return this->loggedFrames; } - }; -} - -#endif /*********************************************************************** -.\GUIUNITTESTPROTOCOL.H -***********************************************************************/ -/*********************************************************************** -Vczh Library++ 3.0 -Developer: Zihan Chen(vczh) -Unit Test Snapsnot and other Utilities +IGuiRemoteProtocolMessages (Initialization) ***********************************************************************/ -#ifndef VCZH_PRESENTATION_GUIUNITTESTPROTOCOL -#define VCZH_PRESENTATION_GUIUNITTESTPROTOCOL + protected: + void Impl_ControllerConnectionEstablished() + { + ResetCreatedObjects(); + } -namespace vl::presentation::unittest -{ - -/*********************************************************************** -UnitTestFrameworkConfig -***********************************************************************/ - - struct UnitTestFrameworkConfig - { - filesystem::FilePath snapshotFolder; - filesystem::FilePath resourceFolder; + void Impl_ControllerConnectionStopped() + { + stopped = true; + } }; - extern const UnitTestFrameworkConfig& GetUnitTestFrameworkConfig(); - -/*********************************************************************** -UnitTestRemoteProtocol -***********************************************************************/ - - template class ...TMixins> - struct Mixin; - - template - struct Mixin - { - using Type = TBase; - }; - - template class TMixin, template class ...TOtherMixins> - struct Mixin - { - using Type = typename Mixin, TOtherMixins...>::Type; - }; - - using UnitTestRemoteProtocolFeatures = Mixin< - UnitTestRemoteProtocolBase, - UnitTestRemoteProtocol_MainWindow, - UnitTestRemoteProtocol_IO, - UnitTestRemoteProtocol_Rendering, - UnitTestRemoteProtocol_Logging, - UnitTestRemoteProtocol_IOCommands - >::Type; - class UnitTestRemoteProtocol : public UnitTestRemoteProtocolFeatures , protected virtual IGuiRemoteEventProcessor @@ -1602,12 +1034,13 @@ UnitTestRemoteProtocol collections::List processRemoteEvents; vint lastFrameIndex = -1; vint nextEventIndex = 0; - bool stopped = false; + bool frameExecuting = false; public: UnitTestRemoteProtocol(const WString& _appName, UnitTestScreenConfig _globalConfig) - : UnitTestRemoteProtocolFeatures(_globalConfig) + : UnitTestRemoteProtocolBase(_globalConfig) + , UnitTestRemoteProtocolFeatures(_globalConfig) , frameworkConfig(GetUnitTestFrameworkConfig()) , appName(_appName) { @@ -1625,21 +1058,21 @@ UnitTestRemoteProtocol processRemoteEvents.Add({ name,std::forward(callback) }); } - protected: - /*********************************************************************** -IGuiRemoteProtocolMessages (Initialization) +IGuiRemoteProtocolMessages ***********************************************************************/ - void RequestControllerConnectionEstablished() override - { - ResetCreatedObjects(); - } - - void RequestControllerConnectionStopped() override - { - stopped = true; - } +#define MESSAGE_NOREQ_NORES(NAME, REQUEST, RESPONSE) void Request ## NAME() override { UnitTestRemoteProtocolFeatures::Impl_ ## NAME(); } +#define MESSAGE_NOREQ_RES(NAME, REQUEST, RESPONSE) void Request ## NAME(vint id) override { UnitTestRemoteProtocolFeatures::Impl_ ## NAME(id); } +#define MESSAGE_REQ_NORES(NAME, REQUEST, RESPONSE) void Request ## NAME(const REQUEST& arguments) override { UnitTestRemoteProtocolFeatures::Impl_ ## NAME(arguments); } +#define MESSAGE_REQ_RES(NAME, REQUEST, RESPONSE) void Request ## NAME(vint id, const REQUEST& arguments) override { UnitTestRemoteProtocolFeatures::Impl_ ## NAME(id, arguments); } +#define MESSAGE_HANDLER(NAME, REQUEST, RESPONSE, REQTAG, RESTAG, ...) MESSAGE_ ## REQTAG ## _ ## RESTAG(NAME, REQUEST, RESPONSE) + GACUI_REMOTEPROTOCOL_MESSAGES(MESSAGE_HANDLER) +#undef MESSAGE_HANDLER +#undef MESSAGE_REQ_RES +#undef MESSAGE_REQ_NORES +#undef MESSAGE_NOREQ_RES +#undef MESSAGE_NOREQ_NORES /*********************************************************************** IGuiRemoteProtocol @@ -1650,10 +1083,6 @@ IGuiRemoteProtocol // TODO: Failure injection to disconnected } - protected: - - bool frameExecuting = false; - void ProcessRemoteEvents() override { #define ERROR_MESSAGE_PREFIX L"vl::presentation::unittest::UnitTestRemoteProtocol::ProcessRemoteEvents()#" @@ -1681,8 +1110,6 @@ IGuiRemoteProtocol #undef ERROR_MESSAGE_PREFIX } - public: - IGuiRemoteEventProcessor* GetRemoteEventProcessor() override { return this; @@ -1727,12 +1154,20 @@ extern vl::Ptr GacUIUnitTest_CompileAndLoad(const #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA +struct GacUIUnitTest_Installer +{ + vl::Func initialize; + vl::Func finalize; + vl::Func installWindow; + vl::Nullable config; +}; + template void GacUIUnitTest_StartFast_WithResourceAsText( const vl::WString& appName, const vl::WString& windowTypeFullName, - const vl::WString& resourceText, vl::Func installWindow, - vl::Nullable config + const vl::WString& resourceText, + GacUIUnitTest_Installer installer = {} ) { GacUIUnitTest_LinkGuiMainProxy([=]( @@ -1753,55 +1188,31 @@ void GacUIUnitTest_StartFast_WithResourceAsText( auto theme = vl::Ptr(new TTheme); vl::presentation::theme::RegisterTheme(theme); { + if(installer.initialize) + { + installer.initialize(); + } auto windowValue = vl::reflection::description::Value::Create(windowTypeFullName); TEST_ASSERT(windowValue.GetRawPtr()); auto window = vl::Ptr(windowValue.GetRawPtr()->SafeAggregationCast()); TEST_ASSERT(window); - if (installWindow) + if (installer.installWindow) { - installWindow(window.Obj()); + installer.installWindow(window.Obj()); } window->MoveToScreenCenter(); previousMainProxy(protocol, context); vl::presentation::controls::GetApplication()->Run(window.Obj()); + if (installer.finalize) + { + installer.finalize(); + } } vl::presentation::theme::UnregisterTheme(theme->Name); }); - GacUIUnitTest_Start_WithResourceAsText(appName, config, resourceText); -} - -template -void GacUIUnitTest_StartFast_WithResourceAsText( - const vl::WString& appName, - const vl::WString& windowTypeFullName, - const vl::WString& resourceText, - vl::Nullable config -) -{ - GacUIUnitTest_StartFast_WithResourceAsText(appName, windowTypeFullName, resourceText, {}, config); -} - -template -void GacUIUnitTest_StartFast_WithResourceAsText( - const vl::WString& appName, - const vl::WString& windowTypeFullName, - const vl::WString& resourceText, - vl::Func installWindow -) -{ - GacUIUnitTest_StartFast_WithResourceAsText(appName, windowTypeFullName, resourceText, installWindow, {}); -} - -template -void GacUIUnitTest_StartFast_WithResourceAsText( - const vl::WString& appName, - const vl::WString& windowTypeFullName, - const vl::WString& resourceText -) -{ - GacUIUnitTest_StartFast_WithResourceAsText(appName, windowTypeFullName, resourceText, {}, {}); + GacUIUnitTest_Start_WithResourceAsText(appName, installer.config, resourceText); } #endif diff --git a/Import/GacUI.cpp b/Import/GacUI.cpp index cb79e8d7..278df89c 100644 --- a/Import/GacUI.cpp +++ b/Import/GacUI.cpp @@ -18176,30 +18176,63 @@ GuiDocumentCommonInterface break; case VKEY::KEY_HOME: { + if (ctrl) + { + Move(TextPos(0, 0), shift, true); + break; + } + TextPos newCaret = documentElement->CalculateCaret(currentCaret, IGuiGraphicsParagraph::CaretLineFirst, frontSide); if (newCaret == currentCaret) { newCaret = documentElement->CalculateCaret(currentCaret, IGuiGraphicsParagraph::CaretFirst, frontSide); } + if (newCaret == currentCaret) + { + newCaret = TextPos(0, 0); + } Move(newCaret, shift, frontSide); } break; case VKEY::KEY_END: { + if (ctrl) + { + vint lastIndex = documentElement->GetDocument()->paragraphs.Count() - 1; + auto lastParagraph = documentElement->GetDocument()->paragraphs[lastIndex]; + Move(TextPos(lastIndex, lastParagraph->GetTextForCaret().Length()), shift, false); + break; + } + TextPos newCaret = documentElement->CalculateCaret(currentCaret, IGuiGraphicsParagraph::CaretLineLast, frontSide); if (newCaret == currentCaret) { newCaret = documentElement->CalculateCaret(currentCaret, IGuiGraphicsParagraph::CaretLast, frontSide); } + if (newCaret == currentCaret) + { + vint lastIndex = documentElement->GetDocument()->paragraphs.Count() - 1; + auto lastParagraph = documentElement->GetDocument()->paragraphs[lastIndex]; + newCaret = TextPos(lastIndex, lastParagraph->GetTextForCaret().Length()); + } Move(newCaret, shift, frontSide); } - break; - case VKEY::KEY_PRIOR: - { - } break; + case VKEY::KEY_PRIOR: case VKEY::KEY_NEXT: { + if (config.paragraphMode == GuiDocumentParagraphMode::Singleline) break; + if (!documentMouseArea) break; + vint page = documentMouseArea->GetCachedBounds().Height(); + if (page <= 0) break; + + Rect caretBounds = documentElement->GetCaretBounds(currentCaret, frontSide); + vint x = caretBounds.x1; + vint y = (caretBounds.y1 + caretBounds.y2) / 2; + y += (code == VKEY::KEY_PRIOR ? -page : page); + + TextPos newCaret = documentElement->CalculateCaretFromPoint(Point(x, y)); + Move(newCaret, shift, frontSide); } break; case VKEY::KEY_BACK: @@ -18229,7 +18262,13 @@ GuiDocumentCommonInterface case VKEY::KEY_RETURN: if (editMode == GuiDocumentEditMode::Editable) { - if (ctrl) + if (config.paragraphMode == GuiDocumentParagraphMode::Singleline) + { + // Singleline text boxes should ignore Enter entirely. + // In particular, Enter must not delete selection. + return true; + } + else if (ctrl && config.paragraphMode == GuiDocumentParagraphMode::Paragraph) { Array text(1); text[0] = L"\r\n"; @@ -18315,11 +18354,19 @@ GuiDocumentCommonInterface void GuiDocumentCommonInterface::SetActiveHyperlink(Ptr package) { - ActivateActiveHyperlink(false); - activeHyperlinks = + auto normalizedPackage = !package ? nullptr : package->hyperlinks.Count() == 0 ? nullptr : package; + + if (!activeHyperlinks && !normalizedPackage) return; + if (activeHyperlinks && normalizedPackage) + { + if (CompareEnumerable(activeHyperlinks->hyperlinks, normalizedPackage->hyperlinks) == 0) return; + } + + ActivateActiveHyperlink(false); + activeHyperlinks = normalizedPackage; ActivateActiveHyperlink(true); ActiveHyperlinkChanged.Execute(documentControl->GetNotifyEventArguments()); } @@ -29754,7 +29801,7 @@ SetPropertiesVisitor element->SetStretch(true); IGuiGraphicsParagraph::InlineObjectProperties properties; - properties.size = run->size; + properties.size = run->GetSize(); properties.baseline = run->baseline; properties.breakCondition = IGuiGraphicsParagraph::Alone; properties.backgroundImage = element; @@ -35071,7 +35118,8 @@ GuiRemoteController (INativeController) INativeClipboardService* GuiRemoteController::ClipboardService() { - CHECK_FAIL(L"Not Implemented!"); + // Use FakeClipboardService + return nullptr; } INativeImageService* GuiRemoteController::ImageService() @@ -35402,14 +35450,6 @@ GuiRemoteEvents (events) { for (auto l : remote->remoteWindow.listeners) l->Char(arguments); } - - void GuiRemoteEvents::OnDocumentParagraph_RenderInlineObjects(const Ptr>& arguments) - { - if (arguments) - { - remote->resourceManager->OnDocumentParagraph_RenderInlineObjects(*arguments.Obj()); - } - } } /*********************************************************************** @@ -35474,30 +35514,7 @@ GuiRemoteGraphicsRenderTarget canvasSize = remote->remoteWindow.GetClientSize(); clipperValidArea = GetClipper(); renderingBatchId++; - - if (destroyedRenderers.Count() > 0) - { - auto ids = Ptr(new List); - CopyFrom(*ids.Obj(), destroyedRenderers); - destroyedRenderers.Clear(); - remote->remoteMessages.RequestRendererDestroyed(ids); - } - - if (createdRenderers.Count() > 0 || pendingParagraphCreations.Count() > 0) - { - auto ids = Ptr(new List); - for (auto id : createdRenderers) - { - ids->Add({ id,renderers[id]->GetRendererType() }); - } - for (auto&& creation : pendingParagraphCreations) - { - ids->Add(creation); - } - createdRenderers.Clear(); - pendingParagraphCreations.Clear(); - remote->remoteMessages.RequestRendererCreated(ids); - } + EnsureRequestedRenderersCreated(); for (auto [id, renderer] : renderers) { @@ -35697,33 +35714,66 @@ GuiRemoteGraphicsRenderTarget { } + void GuiRemoteGraphicsRenderTarget::EnsureRequestedRenderersCreated() + { + if (destroyedRenderers.Count() > 0) + { + auto ids = Ptr(new List); + CopyFrom(*ids.Obj(), destroyedRenderers); + destroyedRenderers.Clear(); + remote->remoteMessages.RequestRendererDestroyed(ids); + } + + if (createdRenderers.Count() > 0 || pendingParagraphCreations.Count() > 0) + { + auto ids = Ptr(new List); + for (auto id : createdRenderers) + { + ids->Add({ id,renderers[id]->GetRendererType() }); + } + CopyFrom(*ids.Obj(), pendingParagraphCreations, true); + createdRenderers.Clear(); + pendingParagraphCreations.Clear(); + remote->remoteMessages.RequestRendererCreated(ids); + } + } + void GuiRemoteGraphicsRenderTarget::OnControllerConnect() { fontHeights.Clear(); renderersAskingForCache.Clear(); - if (renderers.Count() > 0) + if (renderers.Count() > 0 || paragraphs.Count() > 0) { - { - auto ids = Ptr(new List); - for (auto renderer : renderers.Values()) - { - ids->Add({ renderer->GetID(),renderer->GetRendererType() }); - renderer->NotifyMinSizeCacheInvalidated(); - } - createdRenderers.Clear(); - remote->remoteMessages.RequestRendererCreated(ids); - } - + auto ids = Ptr(new List); for (auto renderer : renderers.Values()) { - renderer->SendUpdateElementMessages(true); - if (renderer->NeedUpdateMinSizeFromCache()) - { - renderersAskingForCache.Add(renderer); - } - renderer->ResetUpdated(); + ids->Add({ renderer->GetID(),renderer->GetRendererType() }); + renderer->NotifyMinSizeCacheInvalidated(); } + for (auto paragraph : paragraphs.Values()) + { + ids->Add({ paragraph->GetParagraphId(),remoteprotocol::RendererType::DocumentParagraph }); + } + createdRenderers.Clear(); + pendingParagraphCreations.Clear(); + remote->remoteMessages.RequestRendererCreated(ids); + } + + for (auto renderer : renderers.Values()) + { + renderer->SendUpdateElementMessages(true); + if (renderer->NeedUpdateMinSizeFromCache()) + { + renderersAskingForCache.Add(renderer); + } + renderer->ResetUpdated(); + } + + for (auto paragraph : paragraphs.Values()) + { + paragraph->MarkParagraphDirty(false); + paragraph->EnsureRemoteParagraphSynced(); } } @@ -35756,20 +35806,19 @@ GuiRemoteGraphicsRenderTarget vint id = renderer->GetID(); renderers.Remove(id); renderersAskingForCache.Remove(renderer); + + vint index = createdRenderers.IndexOf(id); + if (index == -1) { - vint index = createdRenderers.IndexOf(id); - if (index == -1) + if (!destroyedRenderers.Contains(id)) { - if (!destroyedRenderers.Contains(id)) - { - destroyedRenderers.Add(id); - } - } - else - { - createdRenderers.RemoveAt(index); + destroyedRenderers.Add(id); } } + else + { + createdRenderers.RemoveAt(index); + } } Rect GuiRemoteGraphicsRenderTarget::GetClipperValidArea() @@ -35785,12 +35834,12 @@ GuiRemoteGraphicsRenderTarget void GuiRemoteGraphicsRenderTarget::RegisterParagraph(GuiRemoteGraphicsParagraph* paragraph) { -#define ERROR_MESSAGE_PREFIX L"vl::presentation::elements::GuiRemoteGraphicsRenderTarget::RegisterParagraph(GuiRemoteGraphicsParagraph*)#" - auto paragraphId = paragraph->GetParagraphId(); - CHECK_ERROR(!paragraphs.Keys().Contains(paragraphId), ERROR_MESSAGE_PREFIX L"Duplicated paragraph id."); - paragraphs.Add(paragraphId, paragraph); - pendingParagraphCreations.Add({ paragraphId,remoteprotocol::RendererType::DocumentParagraph }); -#undef ERROR_MESSAGE_PREFIX + auto id = paragraph->GetParagraphId(); + if (!paragraphs.Keys().Contains(id)) + { + paragraphs.Add(id, paragraph); + pendingParagraphCreations.Add({ id,remoteprotocol::RendererType::DocumentParagraph }); + } } void GuiRemoteGraphicsRenderTarget::UnregisterParagraph(vint id) @@ -35802,12 +35851,14 @@ GuiRemoteGraphicsRenderTarget } paragraphs.Remove(id); - for (vint i = pendingParagraphCreations.Count() - 1; i >= 0; i--) { - if (pendingParagraphCreations[i].id == id) + for (vint i = pendingParagraphCreations.Count() - 1; i >= 0; i--) { - pendingParagraphCreations.RemoveAt(i); - return; + if (pendingParagraphCreations[i].id == id) + { + pendingParagraphCreations.RemoveAt(i); + return; + } } } if (!destroyedRenderers.Contains(id)) @@ -35871,11 +35922,6 @@ GuiRemoteGraphicsResourceManager renderTarget.OnControllerDisconnect(); } - void GuiRemoteGraphicsResourceManager::OnDocumentParagraph_RenderInlineObjects(collections::List& arguments) - { - CHECK_FAIL(L"Not Implemented!"); - } - IGuiGraphicsRenderTarget* GuiRemoteGraphicsResourceManager::GetRenderTarget(INativeWindow* window) { CHECK_ERROR(window == &remote->remoteWindow, L"vl::presentation::elements::GuiRemoteGraphicsResourceManager::GetRenderTarget(INativeWindow*)#GuiHostedController should call this function with the native window."); @@ -35901,6 +35947,7 @@ GuiRemoteGraphicsResourceManager } } + /*********************************************************************** .\PLATFORMPROVIDERS\REMOTE\GUIREMOTEGRAPHICS_BASICELEMENTS.CPP ***********************************************************************/ @@ -36746,7 +36793,11 @@ DiffRuns vint firstOverlap = BinarySearchLambda(&map.Keys()[0], map.Keys().Count(), range, index, comparer); if (firstOverlap != -1) - return false; + { + if (map.Keys()[firstOverlap] != range) return false; + const_cast(map.Values()[firstOverlap]) = property; + return true; + } } map.Add(range, property); @@ -37100,6 +37151,8 @@ GuiRemoteGraphicsParagraph return false; } + renderTarget->EnsureRequestedRenderersCreated(); + stagedRuns.Clear(); MergeRuns(textRuns, inlineObjectRuns, stagedRuns); @@ -37136,7 +37189,11 @@ GuiRemoteGraphicsParagraph return false; } - cachedSize = messages.RetrieveRendererUpdateElement_DocumentParagraph(requestId); + { + auto response = messages.RetrieveRendererUpdateElement_DocumentParagraph(requestId); + cachedSize = response.documentSize; + cachedInlineObjectBounds = response.inlineObjectBounds; + } committedRuns = std::move(stagedRuns); needUpdate = false; return true; @@ -37344,10 +37401,7 @@ GuiRemoteGraphicsParagraph Size GuiRemoteGraphicsParagraph::GetSize() { - if (!EnsureRemoteParagraphSynced()) - { - return cachedSize; - } + EnsureRemoteParagraphSynced(); return cachedSize; } @@ -37359,6 +37413,7 @@ GuiRemoteGraphicsParagraph } remoteprotocol::OpenCaretRequest request; + request.id = id; request.caret = NativeTextPosToRemoteTextPos(caret); request.caretColor = color; request.frontSide = frontSide; @@ -37378,7 +37433,7 @@ GuiRemoteGraphicsParagraph } auto& messages = renderTarget->GetRemoteMessages(); - messages.RequestDocumentParagraph_CloseCaret(); + messages.RequestDocumentParagraph_CloseCaret(id); bool disconnected = false; messages.Submit(disconnected); return !disconnected; @@ -37396,6 +37451,27 @@ GuiRemoteGraphicsParagraph return; } + if (callback && cachedInlineObjectBounds) + { + for (auto [callbackId, location] : *cachedInlineObjectBounds.Obj()) + { + auto newSize = callback->OnRenderInlineObject(callbackId, location); + if (newSize != location.GetSize()) + { + MarkParagraphDirty(false); + for (auto&& inlineObjectRun : inlineObjectRuns.Values()) + { + if (inlineObjectRun.callbackId == callbackId) + { + auto& editable = const_cast(inlineObjectRun); + editable.size = newSize; + break; + } + } + } + } + } + remoteprotocol::ElementRendering rendering; rendering.id = id; rendering.bounds = bounds; @@ -37416,6 +37492,7 @@ GuiRemoteGraphicsParagraph auto& messages = renderTarget->GetRemoteMessages(); remoteprotocol::GetCaretRequest request; + request.id = id; request.caret = NativeTextPosToRemoteTextPos(comparingCaret); request.relativePosition = position; @@ -37441,6 +37518,7 @@ GuiRemoteGraphicsParagraph } remoteprotocol::GetCaretBoundsRequest request; + request.id = id; request.caret = NativeTextPosToRemoteTextPos(caret); request.frontSide = frontSide; @@ -37470,6 +37548,7 @@ GuiRemoteGraphicsParagraph for (vint caret = 0; caret <= text.Length(); caret++) { remoteprotocol::GetCaretBoundsRequest request; + request.id = id; request.caret = NativeTextPosToRemoteTextPos(caret); request.frontSide = true; @@ -37516,8 +37595,12 @@ GuiRemoteGraphicsParagraph return {}; } + remoteprotocol::GetInlineObjectFromPointRequest request; + request.id = id; + request.point = point; + auto& messages = renderTarget->GetRemoteMessages(); - vint requestId = messages.RequestDocumentParagraph_GetInlineObjectFromPoint(point); + vint requestId = messages.RequestDocumentParagraph_GetInlineObjectFromPoint(request); bool disconnected = false; messages.Submit(disconnected); if (disconnected) @@ -37554,6 +37637,7 @@ GuiRemoteGraphicsParagraph } remoteprotocol::GetCaretBoundsRequest request; + request.id = id; request.caret = NativeTextPosToRemoteTextPos(textPos); request.frontSide = frontSide; @@ -37577,8 +37661,12 @@ GuiRemoteGraphicsParagraph return false; } + remoteprotocol::IsValidCaretRequest request; + request.id = id; + request.caret = NativeTextPosToRemoteTextPos(caret); + auto& messages = renderTarget->GetRemoteMessages(); - vint requestId = messages.RequestDocumentParagraph_IsValidCaret(NativeTextPosToRemoteTextPos(caret)); + vint requestId = messages.RequestDocumentParagraph_IsValidCaret(request); bool disconnected = false; messages.Submit(disconnected); if (disconnected) @@ -37595,6 +37683,7 @@ GuiRemoteGraphicsParagraph } } + /*********************************************************************** .\PLATFORMPROVIDERS\REMOTE\GUIREMOTEGRAPHICS_IMAGESERVICE.CPP ***********************************************************************/ @@ -41129,9 +41218,18 @@ namespace vl::presentation::remoteprotocol return node; } + template<> vl::Ptr ConvertCustomTypeToJson<::vl::presentation::remoteprotocol::UpdateElement_DocumentParagraphResponse>(const ::vl::presentation::remoteprotocol::UpdateElement_DocumentParagraphResponse & value) + { + auto node = Ptr(new glr::json::JsonObject); + ConvertCustomTypeToJsonField(node, L"documentSize", value.documentSize); + ConvertCustomTypeToJsonField(node, L"inlineObjectBounds", value.inlineObjectBounds); + return node; + } + template<> vl::Ptr ConvertCustomTypeToJson<::vl::presentation::remoteprotocol::GetCaretRequest>(const ::vl::presentation::remoteprotocol::GetCaretRequest & value) { auto node = Ptr(new glr::json::JsonObject); + ConvertCustomTypeToJsonField(node, L"id", value.id); ConvertCustomTypeToJsonField(node, L"caret", value.caret); ConvertCustomTypeToJsonField(node, L"relativePosition", value.relativePosition); return node; @@ -41148,14 +41246,32 @@ namespace vl::presentation::remoteprotocol template<> vl::Ptr ConvertCustomTypeToJson<::vl::presentation::remoteprotocol::GetCaretBoundsRequest>(const ::vl::presentation::remoteprotocol::GetCaretBoundsRequest & value) { auto node = Ptr(new glr::json::JsonObject); + ConvertCustomTypeToJsonField(node, L"id", value.id); ConvertCustomTypeToJsonField(node, L"caret", value.caret); ConvertCustomTypeToJsonField(node, L"frontSide", value.frontSide); return node; } + template<> vl::Ptr ConvertCustomTypeToJson<::vl::presentation::remoteprotocol::GetInlineObjectFromPointRequest>(const ::vl::presentation::remoteprotocol::GetInlineObjectFromPointRequest & value) + { + auto node = Ptr(new glr::json::JsonObject); + ConvertCustomTypeToJsonField(node, L"id", value.id); + ConvertCustomTypeToJsonField(node, L"point", value.point); + return node; + } + + template<> vl::Ptr ConvertCustomTypeToJson<::vl::presentation::remoteprotocol::IsValidCaretRequest>(const ::vl::presentation::remoteprotocol::IsValidCaretRequest & value) + { + auto node = Ptr(new glr::json::JsonObject); + ConvertCustomTypeToJsonField(node, L"id", value.id); + ConvertCustomTypeToJsonField(node, L"caret", value.caret); + return node; + } + template<> vl::Ptr ConvertCustomTypeToJson<::vl::presentation::remoteprotocol::OpenCaretRequest>(const ::vl::presentation::remoteprotocol::OpenCaretRequest & value) { auto node = Ptr(new glr::json::JsonObject); + ConvertCustomTypeToJsonField(node, L"id", value.id); ConvertCustomTypeToJsonField(node, L"caret", value.caret); ConvertCustomTypeToJsonField(node, L"caretColor", value.caretColor); ConvertCustomTypeToJsonField(node, L"frontSide", value.frontSide); @@ -41268,6 +41384,14 @@ namespace vl::presentation::remoteprotocol return node; } + template<> vl::Ptr ConvertCustomTypeToJson<::vl::presentation::remoteprotocol::ElementDesc_DocumentParagraphFull>(const ::vl::presentation::remoteprotocol::ElementDesc_DocumentParagraphFull & value) + { + auto node = Ptr(new glr::json::JsonObject); + ConvertCustomTypeToJsonField(node, L"paragraph", value.paragraph); + ConvertCustomTypeToJsonField(node, L"caret", value.caret); + return node; + } + template<> vl::Ptr ConvertCustomTypeToJson<::vl::presentation::remoteprotocol::UnitTest_RenderingFrame>(const ::vl::presentation::remoteprotocol::UnitTest_RenderingFrame & value) { auto node = Ptr(new glr::json::JsonObject); @@ -42096,6 +42220,20 @@ namespace vl::presentation::remoteprotocol #undef ERROR_MESSAGE_PREFIX } + template<> void ConvertJsonToCustomType<::vl::presentation::remoteprotocol::UpdateElement_DocumentParagraphResponse>(vl::Ptr node, ::vl::presentation::remoteprotocol::UpdateElement_DocumentParagraphResponse& value) + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::remoteprotocol::ConvertJsonToCustomType<::vl::presentation::remoteprotocol::UpdateElement_DocumentParagraphResponse>(Ptr, ::vl::presentation::remoteprotocol::UpdateElement_DocumentParagraphResponse&)#" + auto jsonNode = node.Cast(); + CHECK_ERROR(jsonNode, ERROR_MESSAGE_PREFIX L"Json node does not match the expected type."); + for (auto field : jsonNode->fields) + { + if (field->name.value == L"documentSize") ConvertJsonToCustomType(field->value, value.documentSize); else + if (field->name.value == L"inlineObjectBounds") ConvertJsonToCustomType(field->value, value.inlineObjectBounds); else + CHECK_FAIL(ERROR_MESSAGE_PREFIX L"Unsupported struct member."); + } +#undef ERROR_MESSAGE_PREFIX + } + template<> void ConvertJsonToCustomType<::vl::presentation::remoteprotocol::GetCaretRequest>(vl::Ptr node, ::vl::presentation::remoteprotocol::GetCaretRequest& value) { #define ERROR_MESSAGE_PREFIX L"vl::presentation::remoteprotocol::ConvertJsonToCustomType<::vl::presentation::remoteprotocol::GetCaretRequest>(Ptr, ::vl::presentation::remoteprotocol::GetCaretRequest&)#" @@ -42103,6 +42241,7 @@ namespace vl::presentation::remoteprotocol CHECK_ERROR(jsonNode, ERROR_MESSAGE_PREFIX L"Json node does not match the expected type."); for (auto field : jsonNode->fields) { + if (field->name.value == L"id") ConvertJsonToCustomType(field->value, value.id); else if (field->name.value == L"caret") ConvertJsonToCustomType(field->value, value.caret); else if (field->name.value == L"relativePosition") ConvertJsonToCustomType(field->value, value.relativePosition); else CHECK_FAIL(ERROR_MESSAGE_PREFIX L"Unsupported struct member."); @@ -42131,6 +42270,7 @@ namespace vl::presentation::remoteprotocol CHECK_ERROR(jsonNode, ERROR_MESSAGE_PREFIX L"Json node does not match the expected type."); for (auto field : jsonNode->fields) { + if (field->name.value == L"id") ConvertJsonToCustomType(field->value, value.id); else if (field->name.value == L"caret") ConvertJsonToCustomType(field->value, value.caret); else if (field->name.value == L"frontSide") ConvertJsonToCustomType(field->value, value.frontSide); else CHECK_FAIL(ERROR_MESSAGE_PREFIX L"Unsupported struct member."); @@ -42138,6 +42278,34 @@ namespace vl::presentation::remoteprotocol #undef ERROR_MESSAGE_PREFIX } + template<> void ConvertJsonToCustomType<::vl::presentation::remoteprotocol::GetInlineObjectFromPointRequest>(vl::Ptr node, ::vl::presentation::remoteprotocol::GetInlineObjectFromPointRequest& value) + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::remoteprotocol::ConvertJsonToCustomType<::vl::presentation::remoteprotocol::GetInlineObjectFromPointRequest>(Ptr, ::vl::presentation::remoteprotocol::GetInlineObjectFromPointRequest&)#" + auto jsonNode = node.Cast(); + CHECK_ERROR(jsonNode, ERROR_MESSAGE_PREFIX L"Json node does not match the expected type."); + for (auto field : jsonNode->fields) + { + if (field->name.value == L"id") ConvertJsonToCustomType(field->value, value.id); else + if (field->name.value == L"point") ConvertJsonToCustomType(field->value, value.point); else + CHECK_FAIL(ERROR_MESSAGE_PREFIX L"Unsupported struct member."); + } +#undef ERROR_MESSAGE_PREFIX + } + + template<> void ConvertJsonToCustomType<::vl::presentation::remoteprotocol::IsValidCaretRequest>(vl::Ptr node, ::vl::presentation::remoteprotocol::IsValidCaretRequest& value) + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::remoteprotocol::ConvertJsonToCustomType<::vl::presentation::remoteprotocol::IsValidCaretRequest>(Ptr, ::vl::presentation::remoteprotocol::IsValidCaretRequest&)#" + auto jsonNode = node.Cast(); + CHECK_ERROR(jsonNode, ERROR_MESSAGE_PREFIX L"Json node does not match the expected type."); + for (auto field : jsonNode->fields) + { + if (field->name.value == L"id") ConvertJsonToCustomType(field->value, value.id); else + if (field->name.value == L"caret") ConvertJsonToCustomType(field->value, value.caret); else + CHECK_FAIL(ERROR_MESSAGE_PREFIX L"Unsupported struct member."); + } +#undef ERROR_MESSAGE_PREFIX + } + template<> void ConvertJsonToCustomType<::vl::presentation::remoteprotocol::OpenCaretRequest>(vl::Ptr node, ::vl::presentation::remoteprotocol::OpenCaretRequest& value) { #define ERROR_MESSAGE_PREFIX L"vl::presentation::remoteprotocol::ConvertJsonToCustomType<::vl::presentation::remoteprotocol::OpenCaretRequest>(Ptr, ::vl::presentation::remoteprotocol::OpenCaretRequest&)#" @@ -42145,6 +42313,7 @@ namespace vl::presentation::remoteprotocol CHECK_ERROR(jsonNode, ERROR_MESSAGE_PREFIX L"Json node does not match the expected type."); for (auto field : jsonNode->fields) { + if (field->name.value == L"id") ConvertJsonToCustomType(field->value, value.id); else if (field->name.value == L"caret") ConvertJsonToCustomType(field->value, value.caret); else if (field->name.value == L"caretColor") ConvertJsonToCustomType(field->value, value.caretColor); else if (field->name.value == L"frontSide") ConvertJsonToCustomType(field->value, value.frontSide); else @@ -42331,6 +42500,20 @@ namespace vl::presentation::remoteprotocol #undef ERROR_MESSAGE_PREFIX } + template<> void ConvertJsonToCustomType<::vl::presentation::remoteprotocol::ElementDesc_DocumentParagraphFull>(vl::Ptr node, ::vl::presentation::remoteprotocol::ElementDesc_DocumentParagraphFull& value) + { +#define ERROR_MESSAGE_PREFIX L"vl::presentation::remoteprotocol::ConvertJsonToCustomType<::vl::presentation::remoteprotocol::ElementDesc_DocumentParagraphFull>(Ptr, ::vl::presentation::remoteprotocol::ElementDesc_DocumentParagraphFull&)#" + auto jsonNode = node.Cast(); + CHECK_ERROR(jsonNode, ERROR_MESSAGE_PREFIX L"Json node does not match the expected type."); + for (auto field : jsonNode->fields) + { + if (field->name.value == L"paragraph") ConvertJsonToCustomType(field->value, value.paragraph); else + if (field->name.value == L"caret") ConvertJsonToCustomType(field->value, value.caret); else + CHECK_FAIL(ERROR_MESSAGE_PREFIX L"Unsupported struct member."); + } +#undef ERROR_MESSAGE_PREFIX + } + template<> void ConvertJsonToCustomType<::vl::presentation::remoteprotocol::UnitTest_RenderingFrame>(vl::Ptr node, ::vl::presentation::remoteprotocol::UnitTest_RenderingFrame& value) { #define ERROR_MESSAGE_PREFIX L"vl::presentation::remoteprotocol::ConvertJsonToCustomType<::vl::presentation::remoteprotocol::UnitTest_RenderingFrame>(Ptr, ::vl::presentation::remoteprotocol::UnitTest_RenderingFrame&)#" @@ -43382,7 +43565,7 @@ namespace vl::presentation::remote_renderer CHECK_FAIL(L"Not implemented."); } - void GuiRemoteRendererSingle::RequestDocumentParagraph_GetInlineObjectFromPoint(vint id, const Point& arguments) + void GuiRemoteRendererSingle::RequestDocumentParagraph_GetInlineObjectFromPoint(vint id, const remoteprotocol::GetInlineObjectFromPointRequest& arguments) { CHECK_FAIL(L"Not implemented."); } @@ -43392,7 +43575,7 @@ namespace vl::presentation::remote_renderer CHECK_FAIL(L"Not implemented."); } - void GuiRemoteRendererSingle::RequestDocumentParagraph_IsValidCaret(vint id, const vint& arguments) + void GuiRemoteRendererSingle::RequestDocumentParagraph_IsValidCaret(vint id, const remoteprotocol::IsValidCaretRequest& arguments) { CHECK_FAIL(L"Not implemented."); } @@ -43402,7 +43585,7 @@ namespace vl::presentation::remote_renderer CHECK_FAIL(L"Not implemented."); } - void GuiRemoteRendererSingle::RequestDocumentParagraph_CloseCaret() + void GuiRemoteRendererSingle::RequestDocumentParagraph_CloseCaret(const vint& arguments) { CHECK_FAIL(L"Not implemented."); } @@ -44382,7 +44565,8 @@ namespace vl { if (run->image) { - writer.WriteString(L"size.x) + L"\" height=\"" + itow(run->size.y) + L"\" src=\"data:image/"); + auto imageSize = run->GetSize(); + writer.WriteString(L"image->GetFormat(); if (format == INativeImage::Gif) { @@ -44685,8 +44869,9 @@ namespace vl if (run->image) { writer.WriteString(L"{\\pict\\pngblip"); - writer.WriteString(L"\\picw" + itow(run->size.x) + L"\\pich" + itow(run->size.y)); - writer.WriteString(L"\\picwgoal" + itow(run->size.x * 15) + L"\\pichgoal" + itow(run->size.y * 15) + L" "); + auto imageSize = run->GetSize(); + writer.WriteString(L"\\picw" + itow(imageSize.x) + L"\\pich" + itow(imageSize.y)); + writer.WriteString(L"\\picwgoal" + itow(imageSize.x * 15) + L"\\pichgoal" + itow(imageSize.y * 15) + L" "); MemoryStream memoryStream; run->image->SaveToStream(memoryStream, INativeImage::Png); @@ -45472,7 +45657,7 @@ If clonedRun field is assigned then it will be added to the cloned container run void Visit(DocumentImageRun* run)override { auto cloned = Ptr(new DocumentImageRun); - cloned->size = run->size; + cloned->sizeOverride = run->sizeOverride; cloned->baseline = run->baseline; cloned->image = run->image; cloned->frameIndex = run->frameIndex; @@ -47471,8 +47656,6 @@ DocumentModel::EditImage Ptr DocumentModel::EditImage(TextPos begin, TextPos end, Ptr image) { auto imageRun = Ptr(new DocumentImageRun); - imageRun->size=image->GetImage()->GetFrame(image->GetFrameIndex())->GetSize(); - imageRun->baseline=imageRun->size.y; imageRun->image=image->GetImage(); imageRun->frameIndex=image->GetFrameIndex(); @@ -47865,22 +48048,17 @@ document_operation_visitors::DeserializeNodeVisitor { run->image = imageData->GetImage(); } - if (run->image && run->image->GetFrameCount() > 0) - { - run->size = run->image->GetFrame(0)->GetSize(); - run->frameIndex = 0; - } } for (auto att : node->attributes) { if (att->name.value == L"width") { - run->size.x = wtoi(att->value.value); + run->sizeOverride = { wtoi(att->value.value),run->sizeOverride ? run->sizeOverride.Value().y : 0 }; } else if (att->name.value == L"height") { - run->size.y = wtoi(att->value.value); + run->sizeOverride = { run->sizeOverride ? run->sizeOverride.Value().x : 0,wtoi(att->value.value) }; } else if (att->name.value == L"baseline") { @@ -48502,14 +48680,22 @@ document_operation_visitors::SerializeRunVisitor void Visit(DocumentImageRun* run)override { XmlElementWriter writer(parent); - writer + auto elementWriter = writer .Element(L"img") - .Attribute(L"width", itow(run->size.x)) - .Attribute(L"height", itow(run->size.y)) - .Attribute(L"baseline", itow(run->baseline)) .Attribute(L"frameIndex", itow(run->frameIndex)) .Attribute(L"source", run->source) ; + if(run->sizeOverride) + { + elementWriter + .Attribute(L"width", itow(run->sizeOverride.Value().x)) + .Attribute(L"height", itow(run->sizeOverride.Value().y)) + ; + } + if (run->baseline != -1) + { + elementWriter.Attribute(L"baseline", itow(run->baseline)); + } } void Visit(DocumentEmbeddedObjectRun* run)override @@ -51549,6 +51735,7 @@ FakeClipboardWriter FakeClipboardWriter(FakeClipboardService* _service) : service(_service) { + reader = Ptr(new FakeClipboardReader); } void SetText(const WString& value) override @@ -51951,6 +52138,8 @@ View Model (IFileDialogViewModel) Regex regexDisplayString{ L";" }; public: + FakeDialogServiceBase* dialogService = nullptr; + bool selectToSave = false; bool confirmed = false; ConfirmedSelection confirmedSelection; @@ -52188,50 +52377,94 @@ View Model (IFileDialogViewModel) bool TryConfirm(controls::GuiWindow* owner, Selection selectedPaths) override { + CHECK_ERROR(dialogService, L"vl::presentation::FileDialogViewModel::TryConfirm()#dialogService is not initialized."); auto wd = selectedFolder->folder.GetFilePath(); - List paths; + List rawPaths; CopyFrom( - paths, + rawPaths, selectedPaths.Select([this, wd](auto path) { return wd / path; }) ); - if (paths.Count() == 0) + if (rawPaths.Count() == 0) { - GetCurrentController()->DialogService()->ShowMessageBox( - owner->GetNativeWindow(), + dialogService->ShowMessageBox( + owner ? owner->GetNativeWindow() : nullptr, dialogErrorEmptySelection, owner->GetText(), INativeDialogService::DisplayOK, INativeDialogService::DefaultFirst, - INativeDialogService::IconError + INativeDialogService::IconError, + INativeDialogService::ModalWindow ); return false; } - else if (paths.Count() == 1) + + // folder navigation must use the raw selection (no extension append) + if (rawPaths.Count() == 1) { - auto path = paths[0]; + auto path = rawPaths[0]; if (filesystem::Folder(path).Exists()) { SetSelectedFolderInternal(path, true); return false; } } - else + else if (!enabledMultipleSelection) { - if (!enabledMultipleSelection) - { - GetCurrentController()->DialogService()->ShowMessageBox( - owner->GetNativeWindow(), - dialogErrorMultipleSelectionNotEnabled, - owner->GetText(), - INativeDialogService::DisplayOK, - INativeDialogService::DefaultFirst, - INativeDialogService::IconError - ); - return false; - } + dialogService->ShowMessageBox( + owner ? owner->GetNativeWindow() : nullptr, + dialogErrorMultipleSelectionNotEnabled, + owner->GetText(), + INativeDialogService::DisplayOK, + INativeDialogService::DefaultFirst, + INativeDialogService::IconError, + INativeDialogService::ModalWindow + ); + return false; } + Nullable extension; + bool extensionFromFilter = false; + if (selectedFilter) + { + extension = selectedFilter->GetDefaultExtension(); + extensionFromFilter = extension; + } + + if (!extensionFromFilter && defaultExtension != WString::Empty) + { + extension = defaultExtension; + } + + auto normalized = [&](filesystem::FilePath path) + { + if (!extension) return path; + + auto&& sExt = WString::Unmanaged(L".") + extension.Value(); + vint lExt = sExt.Length(); + auto full = path.GetFullPath(); + + if (extensionFromFilter) + { + if (full.Length() >= lExt && full.Right(lExt) == sExt) + { + return path; + } + } + else + { + auto selectedFileName = path.GetName(); + if (INVLOC.FindFirst(selectedFileName, WString::Unmanaged(L"."), Locale::None).key != -1) + { + return path; + } + } + return filesystem::FilePath(full + sExt); + }; + + List paths; + CopyFrom(paths, From(rawPaths).Select([&](auto path) { return normalized(path); })); + List files, folders, unexistings; for (auto [path, index] : indexed(paths)) { @@ -52261,13 +52494,14 @@ View Model (IFileDialogViewModel) writer.WriteString(wd.GetRelativePathFor(paths[index])); } }); - GetCurrentController()->DialogService()->ShowMessageBox( - owner->GetNativeWindow(), + dialogService->ShowMessageBox( + owner ? owner->GetNativeWindow() : nullptr, message, owner->GetText(), INativeDialogService::DisplayOK, INativeDialogService::DefaultFirst, - INativeDialogService::IconError + INativeDialogService::IconError, + INativeDialogService::ModalWindow ); return false; } @@ -52286,13 +52520,14 @@ View Model (IFileDialogViewModel) writer.WriteString(wd.GetRelativePathFor(paths[index])); } }); - GetCurrentController()->DialogService()->ShowMessageBox( - owner->GetNativeWindow(), + dialogService->ShowMessageBox( + owner ? owner->GetNativeWindow() : nullptr, message, owner->GetText(), INativeDialogService::DisplayOK, INativeDialogService::DefaultFirst, - INativeDialogService::IconError + INativeDialogService::IconError, + INativeDialogService::ModalWindow ); return false; } @@ -52330,57 +52565,59 @@ View Model (IFileDialogViewModel) writer.WriteString(wd.GetRelativePathFor(path)); } }); - GetCurrentController()->DialogService()->ShowMessageBox( - owner->GetNativeWindow(), + dialogService->ShowMessageBox( + owner ? owner->GetNativeWindow() : nullptr, message, owner->GetText(), INativeDialogService::DisplayOK, INativeDialogService::DefaultFirst, - INativeDialogService::IconError + INativeDialogService::IconError, + INativeDialogService::ModalWindow ); return false; } } + } - WString questionMessage; - List* questionFiles = nullptr; - if (selectToSave && promptOverriteFile) - { - questionMessage = dialogAskOverrideFile; - questionFiles = &files; - } - if (!selectToSave && promptCreateFile) - { - questionMessage = dialogAskCreateFile; - questionFiles = &unexistings; - } + WString questionMessage; + List* questionFiles = nullptr; + if (selectToSave && promptOverriteFile) + { + questionMessage = dialogAskOverrideFile; + questionFiles = &files; + } + if (!selectToSave && promptCreateFile && unexistings.Count() > 0) + { + questionMessage = dialogAskCreateFile; + questionFiles = &unexistings; + } - if (questionFiles && questionFiles->Count() > 0) + if (questionFiles && questionFiles->Count() > 0) + { + auto message = stream::GenerateToStream([&](stream::TextWriter& writer) { - auto message = stream::GenerateToStream([&](stream::TextWriter& writer) + writer.WriteString(questionMessage); + for (vint index : *questionFiles) { - writer.WriteString(questionMessage); - for (vint index : *questionFiles) - { - writer.WriteLine(WString::Empty); - writer.WriteString(L" "); - writer.WriteString(wd.GetRelativePathFor(paths[index])); - } - }); - - auto result = GetCurrentController()->DialogService()->ShowMessageBox( - owner->GetNativeWindow(), - message, - owner->GetText(), - INativeDialogService::DisplayOKCancel, - INativeDialogService::DefaultThird, - INativeDialogService::IconQuestion - ); - - if (result == INativeDialogService::SelectCancel) - { - return false; + writer.WriteLine(WString::Empty); + writer.WriteString(L" "); + writer.WriteString(wd.GetRelativePathFor(paths[index])); } + }); + + auto result = dialogService->ShowMessageBox( + owner ? owner->GetNativeWindow() : nullptr, + message, + owner->GetText(), + INativeDialogService::DisplayOKCancel, + INativeDialogService::DefaultThird, + INativeDialogService::IconQuestion, + INativeDialogService::ModalWindow + ); + + if (result == INativeDialogService::SelectCancel) + { + return false; } } @@ -52389,47 +52626,6 @@ View Model (IFileDialogViewModel) From(paths).Select([](auto path) { return path.GetFullPath(); }) ); - Nullable extension; - bool extensionFromFilter = false; - if (selectedFilter) - { - extension = selectedFilter->GetDefaultExtension(); - extensionFromFilter = extension; - } - - if (!extensionFromFilter && defaultExtension != WString::Empty) - { - extension = defaultExtension; - } - - if (extension) - { - auto&& sExt = WString::Unmanaged(L".") + extension.Value(); - vint lExt = sExt.Length(); - - // TODO: (enumerable) foreach - for (vint i = 0; i < confirmedSelection.Count(); i++) - { - WString& selection = confirmedSelection[i]; - if (extensionFromFilter) - { - if (selection.Length() >= lExt && selection.Right(lExt) == sExt) - { - continue; - } - } - else - { - auto selectedFileName = filesystem::FilePath(selection).GetName(); - if (INVLOC.FindFirst(selectedFileName, WString::Unmanaged(L"."), Locale::None).key != -1) - { - continue; - } - } - selection += sExt; - } - } - confirmed = true; return true; } @@ -52490,6 +52686,7 @@ FakeDialogServiceBase ) { auto vm = Ptr(new FileDialogViewModel); + vm->dialogService = this; vm->title = title; vm->enabledMultipleSelection = (options & INativeDialogService::FileDialogAllowMultipleSelection) != 0; vm->fileMustExist = (options & INativeDialogService::FileDialogFileMustExist) != 0; diff --git a/Import/GacUI.h b/Import/GacUI.h index 59d801d9..ff7fc36c 100644 --- a/Import/GacUI.h +++ b/Import/GacUI.h @@ -10069,6 +10069,13 @@ Helper Functions #undef ERROR_MESSAGE_PREFIX } + template + T* FindObjectByName(GuiInstanceRootObject* rootObject, const WString& firstName, TArgs&& ...remains) + { + auto firstObject = FindObjectByName(rootObject, firstName); + return FindObjectByName(firstObject, std::forward(remains)...); + } + template requires(std::is_base_of_v) T* TryFindControlByText(GuiControl* rootObject, const WString& text) @@ -11089,7 +11096,7 @@ Dialogs class GuiFileDialogBase abstract : public GuiDialogBase, public Description { protected: - WString filter = L"All Files (*.*)|*.*"; + WString filter = L"All Files (*.*)|*"; vint filterIndex = 0; bool enabledPreview = false; WString title; @@ -11630,12 +11637,17 @@ Rich Content Document (run) class DocumentInlineObjectRun : public DocumentContentRun, public Description { public: - /// Size of the inline object. - Size size; - /// Baseline of the inline object. - vint baseline; + /// Size of the inline object. When it is empty, it either becomes the size of the image, or (1,1) if there is no image. + Nullable sizeOverride; + /// Baseline of the inline object. When it is -1, it becomes sizeOverride.Value().y + vint baseline = -1; - DocumentInlineObjectRun():baseline(-1){} + DocumentInlineObjectRun(){} + + virtual Size GetSize() + { + return sizeOverride ? sizeOverride.Value() : Size(1, 1); + } }; /// Pepresents a image run. @@ -11647,11 +11659,20 @@ Rich Content Document (run) /// The image. Ptr image; /// The frame index. - vint frameIndex; + vint frameIndex = 0; /// The image source string. WString source; - DocumentImageRun():frameIndex(0){} + DocumentImageRun(){} + + Size GetSize() override + { + if (image && !sizeOverride && 0 <= frameIndex && frameIndex < image->GetFrameCount()) + { + return image->GetFrame(frameIndex)->GetSize(); + } + return DocumentInlineObjectRun::GetSize(); + } WString GetRepresentationText()override{return RepresentationText;} void Accept(IVisitor* visitor)override{visitor->Visit(this);} @@ -20835,9 +20856,12 @@ namespace vl::presentation::remoteprotocol struct DocumentInlineObjectRunProperty; struct DocumentRun; struct ElementDesc_DocumentParagraph; + struct UpdateElement_DocumentParagraphResponse; struct GetCaretRequest; struct GetCaretResponse; struct GetCaretBoundsRequest; + struct GetInlineObjectFromPointRequest; + struct IsValidCaretRequest; struct OpenCaretRequest; struct RenderInlineObjectRequest; struct RendererCreation; @@ -20851,6 +20875,7 @@ namespace vl::presentation::remoteprotocol struct RenderingDom; struct RenderingDom_Diff; struct RenderingDom_DiffsInOrder; + struct ElementDesc_DocumentParagraphFull; struct UnitTest_RenderingFrame; struct UnitTest_RenderingTrace; } @@ -20892,9 +20917,12 @@ namespace vl::presentation::remoteprotocol template<> struct JsonNameHelper<::vl::presentation::remoteprotocol::DocumentInlineObjectRunProperty> { static constexpr const wchar_t* Name = L"DocumentInlineObjectRunProperty"; }; template<> struct JsonNameHelper<::vl::presentation::remoteprotocol::DocumentRun> { static constexpr const wchar_t* Name = L"DocumentRun"; }; template<> struct JsonNameHelper<::vl::presentation::remoteprotocol::ElementDesc_DocumentParagraph> { static constexpr const wchar_t* Name = L"ElementDesc_DocumentParagraph"; }; + template<> struct JsonNameHelper<::vl::presentation::remoteprotocol::UpdateElement_DocumentParagraphResponse> { static constexpr const wchar_t* Name = L"UpdateElement_DocumentParagraphResponse"; }; template<> struct JsonNameHelper<::vl::presentation::remoteprotocol::GetCaretRequest> { static constexpr const wchar_t* Name = L"GetCaretRequest"; }; template<> struct JsonNameHelper<::vl::presentation::remoteprotocol::GetCaretResponse> { static constexpr const wchar_t* Name = L"GetCaretResponse"; }; template<> struct JsonNameHelper<::vl::presentation::remoteprotocol::GetCaretBoundsRequest> { static constexpr const wchar_t* Name = L"GetCaretBoundsRequest"; }; + template<> struct JsonNameHelper<::vl::presentation::remoteprotocol::GetInlineObjectFromPointRequest> { static constexpr const wchar_t* Name = L"GetInlineObjectFromPointRequest"; }; + template<> struct JsonNameHelper<::vl::presentation::remoteprotocol::IsValidCaretRequest> { static constexpr const wchar_t* Name = L"IsValidCaretRequest"; }; template<> struct JsonNameHelper<::vl::presentation::remoteprotocol::OpenCaretRequest> { static constexpr const wchar_t* Name = L"OpenCaretRequest"; }; template<> struct JsonNameHelper<::vl::presentation::remoteprotocol::RenderInlineObjectRequest> { static constexpr const wchar_t* Name = L"RenderInlineObjectRequest"; }; template<> struct JsonNameHelper<::vl::presentation::remoteprotocol::RendererCreation> { static constexpr const wchar_t* Name = L"RendererCreation"; }; @@ -20908,6 +20936,7 @@ namespace vl::presentation::remoteprotocol template<> struct JsonNameHelper<::vl::Ptr<::vl::presentation::remoteprotocol::RenderingDom>> { static constexpr const wchar_t* Name = L"RenderingDom"; }; template<> struct JsonNameHelper<::vl::presentation::remoteprotocol::RenderingDom_Diff> { static constexpr const wchar_t* Name = L"RenderingDom_Diff"; }; template<> struct JsonNameHelper<::vl::presentation::remoteprotocol::RenderingDom_DiffsInOrder> { static constexpr const wchar_t* Name = L"RenderingDom_DiffsInOrder"; }; + template<> struct JsonNameHelper<::vl::presentation::remoteprotocol::ElementDesc_DocumentParagraphFull> { static constexpr const wchar_t* Name = L"ElementDesc_DocumentParagraphFull"; }; template<> struct JsonNameHelper<::vl::presentation::remoteprotocol::UnitTest_RenderingFrame> { static constexpr const wchar_t* Name = L"UnitTest_RenderingFrame"; }; template<> struct JsonNameHelper<::vl::presentation::remoteprotocol::UnitTest_RenderingTrace> { static constexpr const wchar_t* Name = L"UnitTest_RenderingTrace"; }; } @@ -20985,7 +21014,7 @@ namespace vl::presentation::remoteprotocol ::vl::presentation::remoteprotocol::ElementDesc_Polygon, ::vl::presentation::remoteprotocol::ElementDesc_SolidLabel, ::vl::presentation::remoteprotocol::ElementDesc_ImageFrame, - ::vl::presentation::remoteprotocol::ElementDesc_DocumentParagraph + ::vl::presentation::remoteprotocol::ElementDesc_DocumentParagraphFull >; struct FontConfig @@ -21171,8 +21200,15 @@ namespace vl::presentation::remoteprotocol ::vl::Ptr<::vl::collections::List<::vl::vint>> removedInlineObjects; }; + struct UpdateElement_DocumentParagraphResponse + { + ::vl::presentation::Size documentSize; + ::vl::Ptr<::vl::collections::Dictionary<::vl::vint, ::vl::presentation::Rect>> inlineObjectBounds; + }; + struct GetCaretRequest { + ::vl::vint id; ::vl::vint caret; ::vl::presentation::elements::IGuiGraphicsParagraph::CaretRelativePosition relativePosition; }; @@ -21185,12 +21221,26 @@ namespace vl::presentation::remoteprotocol struct GetCaretBoundsRequest { + ::vl::vint id; ::vl::vint caret; bool frontSide; }; + struct GetInlineObjectFromPointRequest + { + ::vl::vint id; + ::vl::presentation::Point point; + }; + + struct IsValidCaretRequest + { + ::vl::vint id; + ::vl::vint caret; + }; + struct OpenCaretRequest { + ::vl::vint id; ::vl::vint caret; ::vl::presentation::Color caretColor; bool frontSide; @@ -21278,6 +21328,12 @@ namespace vl::presentation::remoteprotocol ::vl::Ptr<::vl::collections::List<::vl::presentation::remoteprotocol::RenderingDom_Diff>> diffsInOrder; }; + struct ElementDesc_DocumentParagraphFull + { + ::vl::presentation::remoteprotocol::ElementDesc_DocumentParagraph paragraph; + ::vl::Nullable<::vl::presentation::remoteprotocol::OpenCaretRequest> caret; + }; + struct UnitTest_RenderingFrame { ::vl::vint frameId; @@ -21347,9 +21403,12 @@ namespace vl::presentation::remoteprotocol template<> vl::Ptr ConvertCustomTypeToJson<::vl::presentation::remoteprotocol::DocumentInlineObjectRunProperty>(const ::vl::presentation::remoteprotocol::DocumentInlineObjectRunProperty & value); template<> vl::Ptr ConvertCustomTypeToJson<::vl::presentation::remoteprotocol::DocumentRun>(const ::vl::presentation::remoteprotocol::DocumentRun & value); template<> vl::Ptr ConvertCustomTypeToJson<::vl::presentation::remoteprotocol::ElementDesc_DocumentParagraph>(const ::vl::presentation::remoteprotocol::ElementDesc_DocumentParagraph & value); + template<> vl::Ptr ConvertCustomTypeToJson<::vl::presentation::remoteprotocol::UpdateElement_DocumentParagraphResponse>(const ::vl::presentation::remoteprotocol::UpdateElement_DocumentParagraphResponse & value); template<> vl::Ptr ConvertCustomTypeToJson<::vl::presentation::remoteprotocol::GetCaretRequest>(const ::vl::presentation::remoteprotocol::GetCaretRequest & value); template<> vl::Ptr ConvertCustomTypeToJson<::vl::presentation::remoteprotocol::GetCaretResponse>(const ::vl::presentation::remoteprotocol::GetCaretResponse & value); template<> vl::Ptr ConvertCustomTypeToJson<::vl::presentation::remoteprotocol::GetCaretBoundsRequest>(const ::vl::presentation::remoteprotocol::GetCaretBoundsRequest & value); + template<> vl::Ptr ConvertCustomTypeToJson<::vl::presentation::remoteprotocol::GetInlineObjectFromPointRequest>(const ::vl::presentation::remoteprotocol::GetInlineObjectFromPointRequest & value); + template<> vl::Ptr ConvertCustomTypeToJson<::vl::presentation::remoteprotocol::IsValidCaretRequest>(const ::vl::presentation::remoteprotocol::IsValidCaretRequest & value); template<> vl::Ptr ConvertCustomTypeToJson<::vl::presentation::remoteprotocol::OpenCaretRequest>(const ::vl::presentation::remoteprotocol::OpenCaretRequest & value); template<> vl::Ptr ConvertCustomTypeToJson<::vl::presentation::remoteprotocol::RenderInlineObjectRequest>(const ::vl::presentation::remoteprotocol::RenderInlineObjectRequest & value); template<> vl::Ptr ConvertCustomTypeToJson<::vl::presentation::remoteprotocol::RendererCreation>(const ::vl::presentation::remoteprotocol::RendererCreation & value); @@ -21363,6 +21422,7 @@ namespace vl::presentation::remoteprotocol template<> vl::Ptr ConvertCustomTypeToJson<::vl::presentation::remoteprotocol::RenderingDom>(const ::vl::presentation::remoteprotocol::RenderingDom & value); template<> vl::Ptr ConvertCustomTypeToJson<::vl::presentation::remoteprotocol::RenderingDom_Diff>(const ::vl::presentation::remoteprotocol::RenderingDom_Diff & value); template<> vl::Ptr ConvertCustomTypeToJson<::vl::presentation::remoteprotocol::RenderingDom_DiffsInOrder>(const ::vl::presentation::remoteprotocol::RenderingDom_DiffsInOrder & value); + template<> vl::Ptr ConvertCustomTypeToJson<::vl::presentation::remoteprotocol::ElementDesc_DocumentParagraphFull>(const ::vl::presentation::remoteprotocol::ElementDesc_DocumentParagraphFull & value); template<> vl::Ptr ConvertCustomTypeToJson<::vl::presentation::remoteprotocol::UnitTest_RenderingFrame>(const ::vl::presentation::remoteprotocol::UnitTest_RenderingFrame & value); template<> vl::Ptr ConvertCustomTypeToJson<::vl::presentation::remoteprotocol::UnitTest_RenderingTrace>(const ::vl::presentation::remoteprotocol::UnitTest_RenderingTrace & value); @@ -21418,9 +21478,12 @@ namespace vl::presentation::remoteprotocol template<> void ConvertJsonToCustomType<::vl::presentation::remoteprotocol::DocumentInlineObjectRunProperty>(vl::Ptr node, ::vl::presentation::remoteprotocol::DocumentInlineObjectRunProperty& value); template<> void ConvertJsonToCustomType<::vl::presentation::remoteprotocol::DocumentRun>(vl::Ptr node, ::vl::presentation::remoteprotocol::DocumentRun& value); template<> void ConvertJsonToCustomType<::vl::presentation::remoteprotocol::ElementDesc_DocumentParagraph>(vl::Ptr node, ::vl::presentation::remoteprotocol::ElementDesc_DocumentParagraph& value); + template<> void ConvertJsonToCustomType<::vl::presentation::remoteprotocol::UpdateElement_DocumentParagraphResponse>(vl::Ptr node, ::vl::presentation::remoteprotocol::UpdateElement_DocumentParagraphResponse& value); template<> void ConvertJsonToCustomType<::vl::presentation::remoteprotocol::GetCaretRequest>(vl::Ptr node, ::vl::presentation::remoteprotocol::GetCaretRequest& value); template<> void ConvertJsonToCustomType<::vl::presentation::remoteprotocol::GetCaretResponse>(vl::Ptr node, ::vl::presentation::remoteprotocol::GetCaretResponse& value); template<> void ConvertJsonToCustomType<::vl::presentation::remoteprotocol::GetCaretBoundsRequest>(vl::Ptr node, ::vl::presentation::remoteprotocol::GetCaretBoundsRequest& value); + template<> void ConvertJsonToCustomType<::vl::presentation::remoteprotocol::GetInlineObjectFromPointRequest>(vl::Ptr node, ::vl::presentation::remoteprotocol::GetInlineObjectFromPointRequest& value); + template<> void ConvertJsonToCustomType<::vl::presentation::remoteprotocol::IsValidCaretRequest>(vl::Ptr node, ::vl::presentation::remoteprotocol::IsValidCaretRequest& value); template<> void ConvertJsonToCustomType<::vl::presentation::remoteprotocol::OpenCaretRequest>(vl::Ptr node, ::vl::presentation::remoteprotocol::OpenCaretRequest& value); template<> void ConvertJsonToCustomType<::vl::presentation::remoteprotocol::RenderInlineObjectRequest>(vl::Ptr node, ::vl::presentation::remoteprotocol::RenderInlineObjectRequest& value); template<> void ConvertJsonToCustomType<::vl::presentation::remoteprotocol::RendererCreation>(vl::Ptr node, ::vl::presentation::remoteprotocol::RendererCreation& value); @@ -21434,6 +21497,7 @@ namespace vl::presentation::remoteprotocol template<> void ConvertJsonToCustomType<::vl::presentation::remoteprotocol::RenderingDom>(vl::Ptr node, ::vl::presentation::remoteprotocol::RenderingDom& value); template<> void ConvertJsonToCustomType<::vl::presentation::remoteprotocol::RenderingDom_Diff>(vl::Ptr node, ::vl::presentation::remoteprotocol::RenderingDom_Diff& value); template<> void ConvertJsonToCustomType<::vl::presentation::remoteprotocol::RenderingDom_DiffsInOrder>(vl::Ptr node, ::vl::presentation::remoteprotocol::RenderingDom_DiffsInOrder& value); + template<> void ConvertJsonToCustomType<::vl::presentation::remoteprotocol::ElementDesc_DocumentParagraphFull>(vl::Ptr node, ::vl::presentation::remoteprotocol::ElementDesc_DocumentParagraphFull& value); template<> void ConvertJsonToCustomType<::vl::presentation::remoteprotocol::UnitTest_RenderingFrame>(vl::Ptr node, ::vl::presentation::remoteprotocol::UnitTest_RenderingFrame& value); template<> void ConvertJsonToCustomType<::vl::presentation::remoteprotocol::UnitTest_RenderingTrace>(vl::Ptr node, ::vl::presentation::remoteprotocol::UnitTest_RenderingTrace& value); @@ -21475,14 +21539,14 @@ namespace vl::presentation::remoteprotocol HANDLER(ImageCreated, ::vl::presentation::remoteprotocol::ImageCreation, ::vl::presentation::remoteprotocol::ImageMetadata, REQ, RES, NODROP)\ HANDLER(ImageDestroyed, ::vl::vint, void, REQ, NORES, NODROP)\ HANDLER(RendererUpdateElement_ImageFrame, ::vl::presentation::remoteprotocol::ElementDesc_ImageFrame, void, REQ, NORES, NODROP)\ - HANDLER(RendererUpdateElement_DocumentParagraph, ::vl::presentation::remoteprotocol::ElementDesc_DocumentParagraph, ::vl::presentation::Size, REQ, RES, NODROP)\ + HANDLER(RendererUpdateElement_DocumentParagraph, ::vl::presentation::remoteprotocol::ElementDesc_DocumentParagraph, ::vl::presentation::remoteprotocol::UpdateElement_DocumentParagraphResponse, REQ, RES, NODROP)\ HANDLER(DocumentParagraph_GetCaret, ::vl::presentation::remoteprotocol::GetCaretRequest, ::vl::presentation::remoteprotocol::GetCaretResponse, REQ, RES, NODROP)\ HANDLER(DocumentParagraph_GetCaretBounds, ::vl::presentation::remoteprotocol::GetCaretBoundsRequest, ::vl::presentation::Rect, REQ, RES, NODROP)\ - HANDLER(DocumentParagraph_GetInlineObjectFromPoint, ::vl::presentation::Point, ::vl::Nullable<::vl::presentation::remoteprotocol::DocumentRun>, REQ, RES, NODROP)\ + HANDLER(DocumentParagraph_GetInlineObjectFromPoint, ::vl::presentation::remoteprotocol::GetInlineObjectFromPointRequest, ::vl::Nullable<::vl::presentation::remoteprotocol::DocumentRun>, REQ, RES, NODROP)\ HANDLER(DocumentParagraph_GetNearestCaretFromTextPos, ::vl::presentation::remoteprotocol::GetCaretBoundsRequest, ::vl::vint, REQ, RES, NODROP)\ - HANDLER(DocumentParagraph_IsValidCaret, ::vl::vint, bool, REQ, RES, NODROP)\ + HANDLER(DocumentParagraph_IsValidCaret, ::vl::presentation::remoteprotocol::IsValidCaretRequest, bool, REQ, RES, NODROP)\ HANDLER(DocumentParagraph_OpenCaret, ::vl::presentation::remoteprotocol::OpenCaretRequest, void, REQ, NORES, NODROP)\ - HANDLER(DocumentParagraph_CloseCaret, void, void, NOREQ, NORES, NODROP)\ + HANDLER(DocumentParagraph_CloseCaret, ::vl::vint, void, REQ, NORES, NODROP)\ HANDLER(RendererCreated, ::vl::Ptr<::vl::collections::List<::vl::presentation::remoteprotocol::RendererCreation>>, void, REQ, NORES, NODROP)\ HANDLER(RendererDestroyed, ::vl::Ptr<::vl::collections::List<::vl::vint>>, void, REQ, NORES, NODROP)\ HANDLER(RendererBeginRendering, ::vl::presentation::remoteprotocol::ElementBeginRendering, void, REQ, NORES, NODROP)\ @@ -21513,7 +21577,6 @@ namespace vl::presentation::remoteprotocol HANDLER(IOKeyDown, ::vl::presentation::NativeWindowKeyInfo, REQ, NODROP)\ HANDLER(IOKeyUp, ::vl::presentation::NativeWindowKeyInfo, REQ, NODROP)\ HANDLER(IOChar, ::vl::presentation::NativeWindowCharInfo, REQ, NODROP)\ - HANDLER(DocumentParagraph_RenderInlineObjects, ::vl::Ptr<::vl::collections::List<::vl::presentation::remoteprotocol::RenderInlineObjectRequest>>, REQ, NODROP)\ #define GACUI_REMOTEPROTOCOL_MESSAGE_REQUEST_TYPES(HANDLER)\ HANDLER(::vl::Ptr<::vl::collections::List<::vl::presentation::remoteprotocol::GlobalShortcutKey>>)\ @@ -21523,7 +21586,6 @@ namespace vl::presentation::remoteprotocol HANDLER(::vl::WString)\ HANDLER(::vl::presentation::NativeRect)\ HANDLER(::vl::presentation::NativeSize)\ - HANDLER(::vl::presentation::Point)\ HANDLER(::vl::presentation::VKEY)\ HANDLER(::vl::presentation::remoteprotocol::ElementBeginRendering)\ HANDLER(::vl::presentation::remoteprotocol::ElementBoundary)\ @@ -21540,7 +21602,9 @@ namespace vl::presentation::remoteprotocol HANDLER(::vl::presentation::remoteprotocol::ElementRendering)\ HANDLER(::vl::presentation::remoteprotocol::GetCaretBoundsRequest)\ HANDLER(::vl::presentation::remoteprotocol::GetCaretRequest)\ + HANDLER(::vl::presentation::remoteprotocol::GetInlineObjectFromPointRequest)\ HANDLER(::vl::presentation::remoteprotocol::ImageCreation)\ + HANDLER(::vl::presentation::remoteprotocol::IsValidCaretRequest)\ HANDLER(::vl::presentation::remoteprotocol::OpenCaretRequest)\ HANDLER(::vl::presentation::remoteprotocol::RenderingDom_DiffsInOrder)\ HANDLER(::vl::presentation::remoteprotocol::WindowShowing)\ @@ -21550,18 +21614,17 @@ namespace vl::presentation::remoteprotocol #define GACUI_REMOTEPROTOCOL_MESSAGE_RESPONSE_TYPES(HANDLER)\ HANDLER(::vl::Nullable<::vl::presentation::remoteprotocol::DocumentRun>)\ HANDLER(::vl::presentation::Rect)\ - HANDLER(::vl::presentation::Size)\ HANDLER(::vl::presentation::remoteprotocol::ElementMeasurings)\ HANDLER(::vl::presentation::remoteprotocol::FontConfig)\ HANDLER(::vl::presentation::remoteprotocol::GetCaretResponse)\ HANDLER(::vl::presentation::remoteprotocol::ImageMetadata)\ HANDLER(::vl::presentation::remoteprotocol::ScreenConfig)\ + HANDLER(::vl::presentation::remoteprotocol::UpdateElement_DocumentParagraphResponse)\ HANDLER(::vl::presentation::remoteprotocol::WindowSizingConfig)\ HANDLER(::vl::vint)\ HANDLER(bool)\ #define GACUI_REMOTEPROTOCOL_EVENT_REQUEST_TYPES(HANDLER)\ - HANDLER(::vl::Ptr<::vl::collections::List<::vl::presentation::remoteprotocol::RenderInlineObjectRequest>>)\ HANDLER(::vl::presentation::NativeWindowCharInfo)\ HANDLER(::vl::presentation::NativeWindowKeyInfo)\ HANDLER(::vl::presentation::NativeWindowMouseInfo)\ @@ -21675,6 +21738,7 @@ GuiRemoteGraphicsParagraph vint maxWidth = -1; Alignment paragraphAlignment = Alignment::Left; Size cachedSize = Size(0, 0); + Ptr> cachedInlineObjectBounds; bool needUpdate = true; vint id = -1; vuint64_t lastRenderedBatchId = 0; @@ -21689,10 +21753,11 @@ GuiRemoteGraphicsParagraph vint NativeTextPosToRemoteTextPos(vint textPos); vint RemoteTextPosToNativeTextPos(vint textPos); bool TryBuildCaretRange(vint start, vint length, CaretRange& range); + + public: bool EnsureRemoteParagraphSynced(); void MarkParagraphDirty(bool invalidateSize); - public: // ============================================================= // IGuiGraphicsParagraph // ============================================================= @@ -21731,6 +21796,7 @@ GuiRemoteGraphicsParagraph #endif + /*********************************************************************** .\PLATFORMPROVIDERS\REMOTE\GUIREMOTEGRAPHICS_IMAGESERVICE.H ***********************************************************************/ @@ -21932,6 +21998,7 @@ GuiRemoteGraphicsRenderTarget GuiRemoteGraphicsRenderTarget(GuiRemoteController* _remote, GuiHostedController* _hostedController); ~GuiRemoteGraphicsRenderTarget(); + void EnsureRequestedRenderersCreated(); void OnControllerConnect(); void OnControllerDisconnect(); @@ -21975,7 +22042,6 @@ GuiRemoteGraphicsResourceManager void OnControllerConnect(); void OnControllerDisconnect(); - void OnDocumentParagraph_RenderInlineObjects(collections::List& arguments); // ============================================================= // IGuiGraphicsResourceManager @@ -21992,6 +22058,7 @@ GuiRemoteGraphicsResourceManager #endif + /*********************************************************************** .\PLATFORMPROVIDERS\REMOTE\GUIREMOTEGRAPHICS_BASICELEMENTS.H ***********************************************************************/ diff --git a/Import/GacUICompiler.cpp b/Import/GacUICompiler.cpp index ac29ab91..c2dcaff9 100644 --- a/Import/GacUICompiler.cpp +++ b/Import/GacUICompiler.cpp @@ -11810,31 +11810,31 @@ namespace vl::presentation::remoteprotocol::json_visitor { void AstVisitor::PrintFields(GuiRpArrayMapType* node) { - BeginField(L"element"); + BeginField(vl::WString::Unmanaged(L"element")); WriteToken(node->element); EndField(); - BeginField(L"keyField"); + BeginField(vl::WString::Unmanaged(L"keyField")); WriteToken(node->keyField); EndField(); } void AstVisitor::PrintFields(GuiRpArrayType* node) { - BeginField(L"element"); + BeginField(vl::WString::Unmanaged(L"element")); Print(node->element.Obj()); EndField(); } void AstVisitor::PrintFields(GuiRpAttribute* node) { - BeginField(L"cppType"); + BeginField(vl::WString::Unmanaged(L"cppType")); WriteToken(node->cppType); EndField(); - BeginField(L"name"); + BeginField(vl::WString::Unmanaged(L"name")); WriteToken(node->name); EndField(); } void AstVisitor::PrintFields(GuiRpDeclaration* node) { - BeginField(L"attributes"); + BeginField(vl::WString::Unmanaged(L"attributes")); BeginArray(); for (auto&& listItem : node->attributes) { @@ -11844,13 +11844,13 @@ namespace vl::presentation::remoteprotocol::json_visitor } EndArray(); EndField(); - BeginField(L"name"); + BeginField(vl::WString::Unmanaged(L"name")); WriteToken(node->name); EndField(); } void AstVisitor::PrintFields(GuiRpEnumDecl* node) { - BeginField(L"members"); + BeginField(vl::WString::Unmanaged(L"members")); BeginArray(); for (auto&& listItem : node->members) { @@ -11863,89 +11863,89 @@ namespace vl::presentation::remoteprotocol::json_visitor } void AstVisitor::PrintFields(GuiRpEnumMember* node) { - BeginField(L"name"); + BeginField(vl::WString::Unmanaged(L"name")); WriteToken(node->name); EndField(); } void AstVisitor::PrintFields(GuiRpEventDecl* node) { - BeginField(L"request"); + BeginField(vl::WString::Unmanaged(L"request")); Print(node->request.Obj()); EndField(); } void AstVisitor::PrintFields(GuiRpEventRequest* node) { - BeginField(L"type"); + BeginField(vl::WString::Unmanaged(L"type")); Print(node->type.Obj()); EndField(); } void AstVisitor::PrintFields(GuiRpMapType* node) { - BeginField(L"element"); + BeginField(vl::WString::Unmanaged(L"element")); Print(node->element.Obj()); EndField(); - BeginField(L"keyType"); + BeginField(vl::WString::Unmanaged(L"keyType")); Print(node->keyType.Obj()); EndField(); } void AstVisitor::PrintFields(GuiRpMessageDecl* node) { - BeginField(L"request"); + BeginField(vl::WString::Unmanaged(L"request")); Print(node->request.Obj()); EndField(); - BeginField(L"response"); + BeginField(vl::WString::Unmanaged(L"response")); Print(node->response.Obj()); EndField(); } void AstVisitor::PrintFields(GuiRpMessageRequest* node) { - BeginField(L"type"); + BeginField(vl::WString::Unmanaged(L"type")); Print(node->type.Obj()); EndField(); } void AstVisitor::PrintFields(GuiRpMessageResponse* node) { - BeginField(L"type"); + BeginField(vl::WString::Unmanaged(L"type")); Print(node->type.Obj()); EndField(); } void AstVisitor::PrintFields(GuiRpOptionalType* node) { - BeginField(L"element"); + BeginField(vl::WString::Unmanaged(L"element")); Print(node->element.Obj()); EndField(); } void AstVisitor::PrintFields(GuiRpPrimitiveType* node) { - BeginField(L"type"); + BeginField(vl::WString::Unmanaged(L"type")); switch (node->type) { case vl::presentation::remoteprotocol::GuiRpPrimitiveTypes::Binary: - WriteString(L"Binary"); + WriteString(vl::WString::Unmanaged(L"Binary")); break; case vl::presentation::remoteprotocol::GuiRpPrimitiveTypes::Boolean: - WriteString(L"Boolean"); + WriteString(vl::WString::Unmanaged(L"Boolean")); break; case vl::presentation::remoteprotocol::GuiRpPrimitiveTypes::Char: - WriteString(L"Char"); + WriteString(vl::WString::Unmanaged(L"Char")); break; case vl::presentation::remoteprotocol::GuiRpPrimitiveTypes::Color: - WriteString(L"Color"); + WriteString(vl::WString::Unmanaged(L"Color")); break; case vl::presentation::remoteprotocol::GuiRpPrimitiveTypes::Double: - WriteString(L"Double"); + WriteString(vl::WString::Unmanaged(L"Double")); break; case vl::presentation::remoteprotocol::GuiRpPrimitiveTypes::Float: - WriteString(L"Float"); + WriteString(vl::WString::Unmanaged(L"Float")); break; case vl::presentation::remoteprotocol::GuiRpPrimitiveTypes::Integer: - WriteString(L"Integer"); + WriteString(vl::WString::Unmanaged(L"Integer")); break; case vl::presentation::remoteprotocol::GuiRpPrimitiveTypes::Key: - WriteString(L"Key"); + WriteString(vl::WString::Unmanaged(L"Key")); break; case vl::presentation::remoteprotocol::GuiRpPrimitiveTypes::String: - WriteString(L"String"); + WriteString(vl::WString::Unmanaged(L"String")); break; default: WriteNull(); @@ -11954,13 +11954,13 @@ namespace vl::presentation::remoteprotocol::json_visitor } void AstVisitor::PrintFields(GuiRpReferenceType* node) { - BeginField(L"name"); + BeginField(vl::WString::Unmanaged(L"name")); WriteToken(node->name); EndField(); } void AstVisitor::PrintFields(GuiRpSchema* node) { - BeginField(L"declarations"); + BeginField(vl::WString::Unmanaged(L"declarations")); BeginArray(); for (auto&& listItem : node->declarations) { @@ -11973,7 +11973,7 @@ namespace vl::presentation::remoteprotocol::json_visitor } void AstVisitor::PrintFields(GuiRpStructDecl* node) { - BeginField(L"members"); + BeginField(vl::WString::Unmanaged(L"members")); BeginArray(); for (auto&& listItem : node->members) { @@ -11983,14 +11983,14 @@ namespace vl::presentation::remoteprotocol::json_visitor } EndArray(); EndField(); - BeginField(L"type"); + BeginField(vl::WString::Unmanaged(L"type")); switch (node->type) { case vl::presentation::remoteprotocol::GuiRpStructType::Class: - WriteString(L"Class"); + WriteString(vl::WString::Unmanaged(L"Class")); break; case vl::presentation::remoteprotocol::GuiRpStructType::Struct: - WriteString(L"Struct"); + WriteString(vl::WString::Unmanaged(L"Struct")); break; default: WriteNull(); @@ -11999,10 +11999,10 @@ namespace vl::presentation::remoteprotocol::json_visitor } void AstVisitor::PrintFields(GuiRpStructMember* node) { - BeginField(L"name"); + BeginField(vl::WString::Unmanaged(L"name")); WriteToken(node->name); EndField(); - BeginField(L"type"); + BeginField(vl::WString::Unmanaged(L"type")); Print(node->type.Obj()); EndField(); } @@ -12011,7 +12011,7 @@ namespace vl::presentation::remoteprotocol::json_visitor } void AstVisitor::PrintFields(GuiRpUnionDecl* node) { - BeginField(L"members"); + BeginField(vl::WString::Unmanaged(L"members")); BeginArray(); for (auto&& listItem : node->members) { @@ -12024,7 +12024,7 @@ namespace vl::presentation::remoteprotocol::json_visitor } void AstVisitor::PrintFields(GuiRpUnionMember* node) { - BeginField(L"name"); + BeginField(vl::WString::Unmanaged(L"name")); WriteToken(node->name); EndField(); } @@ -12037,7 +12037,7 @@ namespace vl::presentation::remoteprotocol::json_visitor return; } BeginObject(); - WriteType(L"PrimitiveType", node); + WriteType(vl::WString::Unmanaged(L"PrimitiveType"), node); PrintFields(static_cast(node)); PrintFields(static_cast(node)); EndObject(); @@ -12051,7 +12051,7 @@ namespace vl::presentation::remoteprotocol::json_visitor return; } BeginObject(); - WriteType(L"ReferenceType", node); + WriteType(vl::WString::Unmanaged(L"ReferenceType"), node); PrintFields(static_cast(node)); PrintFields(static_cast(node)); EndObject(); @@ -12065,7 +12065,7 @@ namespace vl::presentation::remoteprotocol::json_visitor return; } BeginObject(); - WriteType(L"OptionalType", node); + WriteType(vl::WString::Unmanaged(L"OptionalType"), node); PrintFields(static_cast(node)); PrintFields(static_cast(node)); EndObject(); @@ -12079,7 +12079,7 @@ namespace vl::presentation::remoteprotocol::json_visitor return; } BeginObject(); - WriteType(L"ArrayType", node); + WriteType(vl::WString::Unmanaged(L"ArrayType"), node); PrintFields(static_cast(node)); PrintFields(static_cast(node)); EndObject(); @@ -12093,7 +12093,7 @@ namespace vl::presentation::remoteprotocol::json_visitor return; } BeginObject(); - WriteType(L"ArrayMapType", node); + WriteType(vl::WString::Unmanaged(L"ArrayMapType"), node); PrintFields(static_cast(node)); PrintFields(static_cast(node)); EndObject(); @@ -12107,7 +12107,7 @@ namespace vl::presentation::remoteprotocol::json_visitor return; } BeginObject(); - WriteType(L"MapType", node); + WriteType(vl::WString::Unmanaged(L"MapType"), node); PrintFields(static_cast(node)); PrintFields(static_cast(node)); EndObject(); @@ -12121,7 +12121,7 @@ namespace vl::presentation::remoteprotocol::json_visitor return; } BeginObject(); - WriteType(L"EnumDecl", node); + WriteType(vl::WString::Unmanaged(L"EnumDecl"), node); PrintFields(static_cast(node)); PrintFields(static_cast(node)); EndObject(); @@ -12135,7 +12135,7 @@ namespace vl::presentation::remoteprotocol::json_visitor return; } BeginObject(); - WriteType(L"UnionDecl", node); + WriteType(vl::WString::Unmanaged(L"UnionDecl"), node); PrintFields(static_cast(node)); PrintFields(static_cast(node)); EndObject(); @@ -12149,7 +12149,7 @@ namespace vl::presentation::remoteprotocol::json_visitor return; } BeginObject(); - WriteType(L"StructDecl", node); + WriteType(vl::WString::Unmanaged(L"StructDecl"), node); PrintFields(static_cast(node)); PrintFields(static_cast(node)); EndObject(); @@ -12163,7 +12163,7 @@ namespace vl::presentation::remoteprotocol::json_visitor return; } BeginObject(); - WriteType(L"MessageDecl", node); + WriteType(vl::WString::Unmanaged(L"MessageDecl"), node); PrintFields(static_cast(node)); PrintFields(static_cast(node)); EndObject(); @@ -12177,7 +12177,7 @@ namespace vl::presentation::remoteprotocol::json_visitor return; } BeginObject(); - WriteType(L"EventDecl", node); + WriteType(vl::WString::Unmanaged(L"EventDecl"), node); PrintFields(static_cast(node)); PrintFields(static_cast(node)); EndObject(); @@ -12216,7 +12216,7 @@ namespace vl::presentation::remoteprotocol::json_visitor return; } BeginObject(); - WriteType(L"Attribute", node); + WriteType(vl::WString::Unmanaged(L"Attribute"), node); PrintFields(static_cast(node)); EndObject(); } @@ -12229,7 +12229,7 @@ namespace vl::presentation::remoteprotocol::json_visitor return; } BeginObject(); - WriteType(L"EnumMember", node); + WriteType(vl::WString::Unmanaged(L"EnumMember"), node); PrintFields(static_cast(node)); EndObject(); } @@ -12242,7 +12242,7 @@ namespace vl::presentation::remoteprotocol::json_visitor return; } BeginObject(); - WriteType(L"UnionMember", node); + WriteType(vl::WString::Unmanaged(L"UnionMember"), node); PrintFields(static_cast(node)); EndObject(); } @@ -12255,7 +12255,7 @@ namespace vl::presentation::remoteprotocol::json_visitor return; } BeginObject(); - WriteType(L"StructMember", node); + WriteType(vl::WString::Unmanaged(L"StructMember"), node); PrintFields(static_cast(node)); EndObject(); } @@ -12268,7 +12268,7 @@ namespace vl::presentation::remoteprotocol::json_visitor return; } BeginObject(); - WriteType(L"MessageRequest", node); + WriteType(vl::WString::Unmanaged(L"MessageRequest"), node); PrintFields(static_cast(node)); EndObject(); } @@ -12281,7 +12281,7 @@ namespace vl::presentation::remoteprotocol::json_visitor return; } BeginObject(); - WriteType(L"MessageResponse", node); + WriteType(vl::WString::Unmanaged(L"MessageResponse"), node); PrintFields(static_cast(node)); EndObject(); } @@ -12294,7 +12294,7 @@ namespace vl::presentation::remoteprotocol::json_visitor return; } BeginObject(); - WriteType(L"EventRequest", node); + WriteType(vl::WString::Unmanaged(L"EventRequest"), node); PrintFields(static_cast(node)); EndObject(); } @@ -12307,7 +12307,7 @@ namespace vl::presentation::remoteprotocol::json_visitor return; } BeginObject(); - WriteType(L"Schema", node); + WriteType(vl::WString::Unmanaged(L"Schema"), node); PrintFields(static_cast(node)); EndObject(); } @@ -12329,45 +12329,42 @@ namespace vl::presentation::remoteprotocol { void GuiRemoteProtocolParserData(vl::stream::IStream& outputStream) { - static const vl::vint dataLength = 8193; // 113198 bytes before compressing + static const vl::vint dataLength = 7660; // 109122 bytes before compressing static const vl::vint dataBlock = 256; - static const vl::vint dataRemain = 1; - static const vl::vint dataSolidRows = 32; - static const vl::vint dataRows = 33; + static const vl::vint dataRemain = 236; + static const vl::vint dataSolidRows = 29; + static const vl::vint dataRows = 30; static const char* compressed[] = { - "\x2E\xBA\x01\x00\xF9\x1F\x00\x00\x21\x00\x01\x82\x80\x02\x0B\x82\x81\x82\x06\x89\x82\x9A\x0A\x85\x0E\x85\x12\x0A\xA9\x0A\x90\x1A\x84\x1A\x85\x1D\x0A\xC2\x0A\x88\x2A\x86\x26\x84\x2A\x0A\xDA\x0A\x82\x3A\x80\x36\x85\x37\x0A\xF6\x0A\x9A\x3A\x82\x1D\x09\x84\xFF\x31\xB2\x91\x9A\x80\x03\x99\x99\x35\xB7\xB2\x99\x9A\x9F\x7C\x9E\x9D\x3F\xB7\x81\xB8\x9A\x85\x9E\x9F\xA2\x3D\xC3\xBB\x88\xA0\xA5\x9A\x85\x00\x4F\xD1\x89\x82\x02\xAE\x83\x01\xAA\x03\x84\x18\xA2\x85\x03\xAD\x80\x03\x5E\x80\x07\x01\xB8\x01\xB2\xA2\xA5\x34\x8A\x89\x0A\x84\xA8\x99\xA4\xA6\x42\xF0\x84\xAE\xBD\xA4\xB9\xB8\xBB\x73\x86\xA7\xB2\xBB\xA0\xBD\xBE\xBD\x6F\xFE\xA9\xA2\xC7\xA4\xC0\xB5\xC2\x80\xF5\x89\xD7\xBB\xC1\xBF\x81\xBD\x86\xFC\x83\xCD\xCF\xBF\xC5\xC0\xCA\x93\x96\xCA\xDA\xCC\xC4\xCE\xC6\x81\x90\x98\xC8\xDE\xC5\xC8\xD3\xCA\xD2\x99\xA6\xDB\xCA\xDD\xCC\xD7\xCF\x80\xA1\xA8\xE3\xCE\xD5\xD0\xDB\xD2\xDA\xA9\xB6\xEB\xDA\xDD\xD4\xDF\xD6\x9B\xB7\xBE\xF5\xC0\xEB\xDC\xE1\xDE\xE3\xBF\x8B\x21\xAC\x0A\x87\xA9\xC9\xE7\xA2\x87\xD2\xF2\xC3\xDA\xE1\xDC\xE4\xC3\xB1\xF8\xD5", - "\xE8\xEF\xEA\xEC\xEB\xDC\xDF\xDD\xE1\xF1\xE3\xF3\xE8\xE8\xB2\xE7\xD1\xF4\xEA\xF1\xF4\xF7\xF7\xE8\xDB\xED\xF2\xF0\xFB\xF5\x85\x07\x61\x90\x0D\xF5\xFE\xF1\xF8\xF1\xF9\xFF\x7C\x74\x7E\x7F\xE6\x42\x81\x80\x81\xE2\x49\x85\x7A\x82\xC5\x4C\x87\x72\x83\xBF\x50\x89\x77\x82\x14\x8D\x85\x87\x83\x17\x91\x89\x87\x70\x13\x21\x54\x07\x7E\x08\x9B\x8E\x76\x88\xE4\x56\x86\x88\x86\x27\x9A\x89\x8B\x84\x2B\xA3\x8D\x89\x89\x28\xB1\x8A\x8A\x8C\x2C\xB4\x8E\x8A\x8D\x30\xB3\x8A\x8D\x8D\x3B\xB7\x8D\x8D\x8E\xC3\x57\x01\x58\x06\x20\xB6\x76\x91\x7F\x47\x83\x89\x93\x81\x4B\x85\x81\x8B\x8B\x00\x8E\x9D\x92\x84\x3E\xBC\x86\x95\x95\x58\x80\x99\x95\x94\x54\x9A\x9E\x94\x97\x24\x91\x9B\x05\x58\x1C\x05\x98\x93\x99\x4A\xA8\x9C\x92\x9A\x52\xAC\x9D\x94\x98\x50\x86\x8D\x99\x9A\x74\xAB\x95\x9F\x9C\x76\xB9\x98\x9F\x9E\x6F\xB2\x9D\x9F\x93\x38\x91\x9F\x05\x58\x20\x26\x97\x9F\x9F\x53\xA1\x9E\x9E\xA2\x80\xBF\x80\x9D\xA0\x8B\xB1\x9D\xA3\x95\x5F\x91\xA0\xA7\xA4\x5B\x96\xAE\xA2\xA6\xC3\x63\x01\x58\x09\x86\xBA\x98\xA2\x9B\x8C\x89\xA2\xA6\xA9\x97\xA8\xAB\xA4\xA6", - "\x95\xAC\xAF\xA3\xAA\xAA\x94\xAF\xAA\xAC\x9C\x99\xA4\x83\x09\x61\x68\x01\xA8\x9F\xA5\xA4\xA7\xAA\xAF\xA9\x80\xB0\xAE\xB0\xB4\xAE\xA5\xAD\xAB\xB1\xB6\xA9\xB0\xB2\xC4\x8A\xBD\xB0\xB3\x77\xAB\x01\x58\x0B\xBB\xA3\xA7\xA1\xAF\xD7\xBF\xA9\xB5\xB0\xDB\x83\xBD\xB5\xB1\xCB\xB3\xAE\xB3\xB7\xE3\xA2\xA8\xB6\xB9\xDA\xA8\xBC\xB6\xBA\xDE\xAC\xB0\xBB\xB3\xE2\x90\xBE\xB9\xB9\xBC\xA9\xB5\xBF\xBA\x7B\xAF\x06\x5B\xB9\xF7\xAD\xBD\xBF\xBB\xE4\xB2\xBB\x9C\x45\x09\x50\x59\x41\x0C\xD5\xBC\xB6\xB7\xBC\x02\xCB\xCF\xBC\xBD\x0E\xD1\xCA\xC3\xC4\xF6\x92\xC5\xC4\xC5\xF8\x96\xC9\xC4\xC6\xFE\x9A\xCD\xC4\xC7\x00\xCC\xC1\xBF\xC8\xC7\xA4\xC6\xB0\x81\x16\x45\xC5\xCB\xCA\x27\xE1\xBC\xCA\xCB\x2D\xF0\xBF\xCA\xCC\x31\xC1\xC6\xC8\xCC\x38\xF4\xC9\xCE\xCD\x33\xFC\xC9\x41\x0D\xFB\x97\xC2\xD3\xC6\x43\xDF\xC5\xD1\xC8\x0F\xCD\xC0\xC8\xC4\x4B\xCA\xD6\xBE\x0D\x41\xC4\xD2\xD6\xD1\x53\xC3\x77\x0D\x58\x38\x09\xC7\xD0\xD3\x5B\xCE\xD5\xD4\xD7\x5F\xDE\xD4\xD7\xD8\x48\xDE\xC5\xD9\xD3\x37\xFA\xC3\x40\x46\x2A\xC9\x4C\x0E\xD6\x61\xE9\xDE\xCF\xCE\x22\xFD\xC5\xDD\xCD\x77", - "\xF4\xD9\xD2\xDC\x79\xEA\xD3\xDE\xDF\x01\x7F\x01\x58\x10\x70\xE4\xD0\xDA\xE1\x62\xE7\xDD\xD4\xDF\x7B\xF6\xDD\xE0\xDE\x8F\xFA\xD6\xDB\xE1\x8A\xF1\xDE\xE3\xE4\x89\xD4\xEA\xE5\xE6\x9C\xCC\xE8\xE6\xE7\xE5\x43\x11\xD4\xE2\xA0\xCB\xE7\xE4\xDA\xA7\xE6\xE4\x80\x11\x61\x45\x11\x5A\x11\x61\x47\x11\x58\x47\x6D\xC6\x49\x11\x58\x4A\x21\x5B\x11\x58\x4C\x23\xE8\xD1\x13\x6C\x69\xE6\xE4\xE4\x9F\xCE\xEF\x11\x58\x50\x05\xE5\xE4\xE9\xC2\xCC\xF4\xF0\xEA\xCF\xEA\xE2\xE4\xF4\xD3\xD2\xF0\xE1\xE4\xD7\xC5\xF1\xF7\xF0\xD5\xDC\xF9\xF4\xF5\xDF\xD6\xF2\x43\x14\xBE\xDB\xE5\xEA\xF7\x7F\xE9\xFD\xDE\xFA\xD8\xEC\xFA\xF5\xF7\xCE\xF0\xFB\xF3\xFC\xE6\xCD\xF8\xD0\x48\xB5\xE1\xF8\xFB\xFA\xFC\xED\xFD\xFF\xFB\xFA\x71\x7D\x00\xF4\x7C\x3B\x2A\x25\x7D\x73\xF6\x75\x7F\xF6\x02\x8E\x7C\xF0\x4D\x82\x7C\xFF\x6E\x81\x04\x90\x8B\x4E\x2B\x07\x87\x7C\x0C\x93\x83\xFE\x7E\x7C\x82\x00\x8F\x83\x83\x1E\x9A\x83\x6F\x57\x07\x83\x04\x88\x83\x81\x04\x98\x81\x0A\xA6\x8A\x84\x05\xB2\x7E\x85\x03\x90\x87\x07\x99\x8D\x82\x09\xB5\x84\x82\x58\x05\x84\x0A\xB2\x82\x85\x15\xBB\x87", - "\x84\x2F\x80\x89\x0C\xC2\x83\x86\x1F\x81\x8D\x85\x44\x9D\x84\x0F\xB7\x80\x84\x1B\xA1\x84\x89\xFE\x59\x0A\x0E\xC7\x8C\x85\x2A\xBF\x80\x89\x58\x96\x88\x15\xD7\x8A\x8B\x21\x99\x8C\x8B\x60\x9B\x8A\x18\xDE\x8D\x8B\x22\x8B\x8F\x89\x0E\x62\x25\xFE\x66\x89\x88\x28\x86\x8C\x8C\x61\x90\x8F\x18\xEC\x8F\x8B\x39\x8A\x8D\x8D\x4F\x9B\x09\x58\x5C\x03\x8A\x39\xBE\x8C\x8E\x65\x97\x8D\x1D\xFF\x82\x90\xC7\x5D\x0D\x8F\x80\x91\x8D\x22\xF6\x8E\x8D\x33\x8E\x8F\x91\x14\x88\x8C\x24\xCD\x81\x93\xF2\x1E\x08\x91\x85\x8A\x92\x9E\x5F\x08\x93\x46\xB8\x8B\x92\x34\x92\x91\x25\xA3\x94\x93\x52\xA1\x90\x94\x6F\x8B\x90\x21\x9E\x93\x90\x55\xAE\x91\x93\x8C\x8E\x60\x18\x1D\x92\x94\x53\xA9\x90\x96\xAB\x95\x97\x29\xA4\x94\x87\x30\x34\x90\x95\x8E\x9C\x97\x2D\xAC\x91\x90\x62\x9A\x96\x98\xB1\x80\x9B\x27\xC2\x91\x98\x5B\x97\x3C\x24\x6B\x98\x97\x2B\xC8\x99\x96\x65\xAD\x92\x9A\xD8\x94\x9B\x34\xBA\x93\x98\x6E\x8D\x9B\x97\xCE\x8B\x99\x38\xD7\x9A\x9B\x6C\xA3\x0F\x97\xCC\x82\x60\x19\x68\x93\x9D\x62\x9E\x9A\x9C\xE0\x91\x9D\x37\xD6\x9E\x9C\x7A\x87\x9F\x9D\xE4\x98", - "\x9D\x3D\xE9\x99\x9E\x7B\x89\x9C\x9F\xFB\x8D\x9F\x3D\xFE\x95\x9A\x7B\x65\x0C\x9D\xF2\x9F\x9B\x3C\x80\xA3\xA0\x86\xBF\x9A\xA0\x0F\xB4\x86\x19\x1D\x97\x0C\x84\x8B\xA0\xA2\x05\xB8\xA3\x36\x84\xAB\xA2\x87\xAB\x96\x24\xD1\x9B\x4D\x1A\x16\xAA\xA1\x92\xAD\x8A\x0D\x24\xB0\x9F\x45\x89\xAA\xA4\x93\xBD\x9E\xA3\x1D\xBA\xA1\x36\xFA\x9D\xA0\x99\xA5\x9F\xA6\x34\xBA\x6F\x1A\x29\xAF\xA4\x9B\xB9\xA1\xA3\x2C\xBD\xA5\x50\x81\xA4\x86\x36\x3C\xA4\xA8\x2B\xA9\xAA\x4B\xC8\xAB\xA9\x9A\x83\xAE\xA9\x4A\xAD\xA6\x54\xC2\xA8\x69\x36\x07\xA8\xAA\x4D\xB1\xA1\x54\xD4\xA9\xAA\xA0\x9B\xAC\xA9\x53\xA0\xAC\x57\xE1\xA8\xAA\xB2\x9A\xAD\xAB\xD3\x8E\x0F\x55\xE7\xA2\x60\x94\x21\xA7\xA7\x31\xAF\xA8\x5B\xE3\xA4\xAE\xB1\xB6\xAD\xAC\x75\xB8\xAF\x5D\xF3\xAB\xAE\xAF\xA8\xAB\xA6\x1C\xA0\xB0\x4C\x82\xBE\xA7\xC0\x80\x00\x0E\x6B\xBE\xAE\x59\x8A\xB9\xAE\xBE\xBA\xAF\xB1\x8E\xAD\x49\x1C\x1D\x92\x0F\xC4\xB1\xAF\xAB\x90\xAC\xB1\x5F\x97\xBF\xAE\x9C\xA5\x3B\x0E\x9D\x94\x0E\x65\x84\xB2\xAE\x36\x75\x0B\xB4\x9E\xA3\xB1\x6A\x85\xBA\xB4\xB8\xA4\xB0\xB3\x91\xBA\xB1\x66\x9C", - "\xBB\xB0\xDA\xA4\x9A\x25\x6F\xA6\xB2\x6B\xAB\xBE\x5F\x3B\x28\xB3\xB7\xC0\xBA\xB6\x70\xAD\xB3\xB8\xD6\x86\xBD\xB4\xB6\xBB\xB3\x6B\x9D\xB1\xB8\xE2\x8E\xBF\xB8\xB0\xB2\xB5\x6C\xC9\xB3\xB7\x80\x38\x0F\xB7\xC5\xA8\xBB\x72\xB5\xBB\xBA\xC6\x79\x09\x2C\x2C\x21\xA7\x1E\x61\x2C\x0F\xB0\x3D\x09\x2C\x7E\x01\x2F\x1F\x61\x20\x11\xB0\x01\x10\xB5\x82\x01\x79\x75\xBC\xB1\xBB\x3B\x44\x10\xBB\xCF\xBA\xB8\x7D\xCC\xB9\xBB\xFA\x9D\xBA\xB9\xFB\xBC\xB9\x80\x8D\xB2\xBB\x02\xD4\xBB\xBA\x01\x25\x10\x7E\xD0\xBC\xBF\xFC\xBE\xBB\xC0\x00\xCD\xBB\x06\x86\x1B\xC0\xFD\x92\xC6\xC2\xFD\xAD\xC0\x83\xDC\x37\x11\x0A\xCF\xC7\xC2\x1F\xD9\xC2\x80\xA0\xCA\xC2\x0C\xCE\xC5\xC4\x21\xD4\x80\x22\x1E\xC8\xC5\x16\xE3\xC2\xC4\x8C\x69\x10\x8B\xAF\xC7\xC4\x81\x4A\x13\xC6\x04\xC7\xC2\x81\xFF\xB0\x73\x45\x38\xC1\xC2\x36\x8C\x13\x8F\xF3\xB4\xC4\x1A\xDB\xC1\xC7\x3C\xC8\xC0\x84\xC4\xC0\xC6\x20\xF5\xC4\x9C\x8D\x03\xCA\x92\xC5\xC8\xC8\x00\x0E\x11\x2C\x8F\x12\xCB\x8E\xCB\xC3\xCB\x26\xCC\xCF\xC9\x4E\xC7\xC9\x98\xA6\xC2\xCD\x2F\xE5\xCC\x91\x90\x1A\xCA\x8E\xEB\xC9\xC9\x2D", - "\xD4\xCB\xCC\x29\xC7\xCE\x9B\xDE\xCD\xCA\x30\xC4\x41\x12\x6A\xCD\xCC\x9B\xFB\x42\x13\x3C\xDC\xCB\xCE\x76\xD5\xCE\x9C\xFB\xCF\xCC\x33\xE4\xCF\xD0\x71\xC8\xD0\xBD\x13\x1E\xCF\x42\xC2\xD2\xD1\x02\xD4\x11\xA3\xF4\xC0\xD1\x41\xFA\xCF\xD2\x7F\xC4\xD0\xA5\x9A\xD1\xD1\x4A\xD0\xD5\xCA\x8E\xDE\xD3\x30\x95\x11\x2C\x4B\x21\x2F\x12\x61\x38\x11\x58\x19\x11\x2C\x4D\x21\x2B\x13\x61\x3C\x11\x58\x1D\x18\xB4\x4F\x32\xBF\xD1\x89\xCF\xC0\x28\x13\xDD\xD2\x4E\xD6\xD1\xD3\x98\xC1\xD6\xAF\x9F\xD0\xCE\x17\xE0\xD3\xD3\xC1\xD6\x85\x28\x3C\xDF\xD6\x61\xC9\xDD\xD7\xCF\xCD\xD8\xBF\x22\x1C\xD8\x62\xC6\xD0\x69\xA3\x15\xD9\xAE\xC6\xD5\xD8\x23\xD6\xD8\xD7\xDC\xD7\xD9\xB8\xE0\xDE\xDB\x6D\xE5\xDB\xDC\xA2\xCB\x88\x29\x61\x25\x15\xB0\x26\x11\x2C\xA7\x01\x2C\x2A\x61\x29\x15\xB0\x2A\x11\x2C\xAB\x01\x2C\x2B\x28\xBD\x15\x5B\xE9\xDF\xDC\x02\xCF\x16\xB6\xE8\xD3\xD8\x73\xC7\xD8\xDA\xC0\xC9\xE2\xB3\x8A\xE8\xD8\x86\xC8\xE3\xE1\x0E\x70\x17\xC0\x80\xE7\xE0\x69\xCF\xE5\xE1\x10\xE5\x3D\x2C\x13\xE5\xE2\xFD\xB2\x14\xE3\xDD\xDD\xE2\xC1\xA1\xE4\xE4\x71\xD4\xE5\xE4", - "\xE4\xC2\xE4\xC1\xD1\xDF\xDB\x7F\xEA\xE7\xE4\x26\xF5\x27\x2C\x20\xE1\xE6\x94\xEE\xE2\x4E\xB4\x01\x2D\x2D\x34\xE9\xE4\x9B\xC2\x26\x16\x3C\xF7\xE5\xCD\xC3\xE6\x21\x5B\x01\xED\xE0\x2B\xFB\x4C\x2E\x47\xEC\xE5\x91\xC4\xEA\xE8\x3D\xEF\xEB\x9D\x39\x1C\xE8\x87\xF8\x5A\x17\x55\xF9\xE3\xC5\xDB\xE6\xE3\xAE\xED\xE0\xE9\x30\xF1\xEA\xD8\xDB\xCB\x17\xAC\xD8\xE7\xEC\x08\xFC\x16\xD9\xDC\xEF\xEB\xA6\xC9\xEA\xEB\x5E\xEE\xEB\xD8\xE0\xEF\xE5\xBA\xFE\xE6\xED\x61\xE3\x21\x2F\x61\x2E\x17\xB0\x3F\x11\x2C\xC0\x01\x2D\x30\x61\x22\x19\xB0\x03\x19\x2C\xC4\x01\x2D\x31\x28\xB6\x18\x7F\xF4\xEF\xEE\x1C\x88\x1B\xDA\xF1\xEF\xEC\xB4\xD4\xF1\xEF\x8F\xF2\xE8\xDE\xF6\xEA\xF2\xAB\xED\xEB\x4F\xC9\x13\xF3\xE7\xF0\xE3\xF4\xCB\xE5\xF2\xB5\xCA\x02\xF6\xDC\xD0\xEC\x4D\x65\x2A\xF5\xF2\x6C\xEB\xF5\xE6\xF3\xEB\xF2\xC8\xE4\xF2\xF6\xB5\xFD\xF3\xED\xB0\xF7\xF2\xCE\xCD\x4C\x19\xAF\xF8\xF1\xEE\xB4\xFB\x4F\x66\x01\xFE\xF7\xAC\xE2\x22\x33\x47\xF6\xF6\xD3\xF8\xF6\xF3\xCF\xEB\xE3\x33\x4C\xFD\xF2\x68\x14\xFC\xF8\xBB\xE2\xF8\xF4\xBC\xF7\xF5\xDE\xCD\xF9\xF6\xDC\xE8\x69", - "\x34\x57\xF9\xF8\x4C\xD2\x19\x2C\xD3\x01\x2C\x35\x61\x25\x1B\xB0\x16\x18\xB5\xD7\x04\xFF\xEC\xE5\xFB\xFA\xED\xD9\xF8\xF9\xF3\xF9\xFF\xF0\xF4\xFB\xB6\x6C\x32\xFB\xFF\xFA\x75\x7F\xF8\x70\x80\x98\x69\x0D\xFF\x72\x80\xDF\x7E\x7D\xBA\x7E\x7C\x4B\x4A\x0D\x07\x87\x7F\x09\x8D\x7D\x12\x81\x7D\x36\x4B\x0D\x0F\x8C\x80\xF6\x78\x81\x03\x88\x80\xC7\x4C\x0D\x17\x80\x7E\x19\x80\x82\x1B\x80\x81\x9D\x7D\x0D\x61\x1E\x0D\x61\x1F\x0D\x61\x10\x0E\x61\x11\x0E\xA8\x52\x0E\x1F\x8A\x80\x8C\x43\x0E\x31\x83\x81\xE1\x77\x83\x21\x82\x83\xFC\x7A\x81\x90\x74\x0E\x61\x15\x0E\x61\x16\x0E\x61\x17\x0E\x61\x18\x0E\xA8\x59\x0E\x35\x84\x81\xAA\x5A\x0E\x49\x8D\x59\xEB\x0D\x84\x39\x86\x83\x51\x8A\x84\x3A\x81\x80\xE2\x1C\x0E\x61\x1D\x0E\x61\x1E\x0E\x61\x1F\x0E\x61\x10\x0F\xA8\x51\x0F\x50\x83\x82\x36\x42\x0F\x63\x81\x81\x54\x82\x85\x64\x82\x82\x68\x88\x83\x35\x13\x0F\xA8\x54\x0F\x61\x15\x0F\x61\x16\x0F\x61\x17\x0F\x61\x18\x0F\xA8\x59\x0F\x67\x8B\x80\x14\x4A\x0F\x7D\x8C\x48\xFB\x08\x5A\xFC\x01\x16\xFD\x01\x16\xFE\x06\x16\x61\x10\x00\x06\x33\x10\x8D\x87", - "\x3D\x01\x0F\x88\x01\x12\x89\x04\x8C\x81\x4A\x62\x00\x94\x84\x89\x96\x8B\x65\x67\x0D\x16\x03\x1E\x89\x03\x1D\x00\xD4\x10\x8A\x02\x12\x8A\x84\x14\x8A\x01\x16\x8A\xA2\x18\x8A\x00\x0A\x8A\xB2\x1C\x8A\xAE\x8B\x1D\xB0\x83\x8A\x0A\x11\x8B\xE0\x13\x8B\xA7\x85\x8B\xB4\x8E\x14\xCB\x26\x14\x6B\x1C\x8B\xAF\x8A\x10\x0E\x07\x2C\xBE\x8A\x10\x1D\x24\x18\x9A\x85\x16\x84\x1F\x8B\x06\x18\x10\xA2\x1D\x15\x84\x16\x14\xC9\x84\x1D\xCC\x83\x10\xCE\x82\x1B\xD0\x82\x1A\x46\x13\x16\xD1\x8D\x13\xAC\x8C\x1C\x84\x1A\x8C\xDA\x8D\x13\xD5\x82\x10\x2F\x18\x8C\x0A\x12\x8E\xB2\x15\x8E\x01\x17\x8D\xDB\x19\x8D\xB2\x1B\x8D\xD4\x16\x14\xAC\x8A\x89\x46\x1A\x8E\xDB\x15\x8C\x53\x14\x1D\xD3\x8B\x8C\x0A\x1E\x8E\xE0\x10\x8F\xF9\x8D\x13\xDC\x83\x8E\x3A\x1C\x8A\xF8\x80\x1E\x09\x93\x1E\xFA\x86\x10\xCA\x18\x8E\xC0\x8B\x1D\xEC\x84\x10\xD4\x12\x90\xE0\x12\x8D\x11\x92\x91\xFF\x85\x91\xF3\x84\x90\x1D\x97\x90\x0A\x10\x8E\xA2\x1B\x90\x46\x1D\x90\x03\x17\x8E\xA2\x1A\x89\x87\x13\x91\x00\x93\x1E\x16\x9C\x90\x1E\x9D\x8D\x20\x99\x5B\x3A\x14\x92\x25\x9A\x13\x13\x9C\x8A", - "\x18\x99\x91\xE3\x1C\x92\x1C\x92\x93\x37\x15\x90\xF1\x8E\x8D\xE9\x84\x1D\x36\x97\x93\x33\x13\x91\x0F\x99\x92\x0A\x1F\x92\x26\x97\x10\x3F\x96\x90\x37\x1A\x89\x4E\x94\x8E\x1B\x94\x18\x55\x98\x94\x32\x12\x94\x03\x93\x93\x06\x12\x92\xB2\x17\x94\x5A\x9F\x0F\x13\x98\x92\xB2\x14\x95\xD4\x87\x95\xCF\x8F\x91\x41\x9C\x96\x33\x15\x8F\x46\x9E\x96\x32\x19\x93\xFC\x8D\x94\x69\x99\x10\x2D\x96\x14\x59\x93\x96\x5C\x97\x91\x44\x99\x10\x62\x93\x13\x81\x98\x94\x4A\x95\x97\x09\x1D\x97\x3D\x9A\x96\xD8\x82\x97\x31\x1A\x89\x88\x9F\x94\xED\x81\x95\x43\x9A\x13\x8F\x93\x96\x31\x1F\x8D\x71\x90\x94\x49\x9A\x10\x66\x9B\x1D\x8E\x97\x97\xCD\x82\x99\x5D\x9D\x96\x9A\x92\x13\x70\x91\x8E\x8C\x94\x96\x8E\x70\x1E\x9F\x9E\x8F\x78\x92\x9A\x7E\x94\x99\xA9\x98\x90\x99\x92\x95\x9B\x99\x10\x4B\x97\x96\xCA\x31\x13\x3E\x98\x95\xA9\x9A\x89\xCE\x12\x1A\xBD\x9B\x96\xA5\x91\x13\x95\x96\x99\x98\x98\x9A\xC5\x9A\x9A\x09\x1D\x99\xAC\x9B\x9B\xCC\x91\x9A\xBE\x9B\x9C\xC7\x93\x96\xA7\x93\x92\xA9\x94\x97\x10\x96\x15\xA0\x96\x8D\xB0\x90\x93\xB2\x9B\x9C\xB4\x9A\x9C\xB6", - "\x93\x97\x0A\x19\x9B\x9E\x9B\x9A\x89\x9F\x9A\xD3\x95\x9E\x8D\x9A\x9E\x90\x94\x91\xED\x93\x99\xA4\x9E\x9E\xFF\x09\x9C\xD8\x9B\x9C\x65\x96\x98\x06\x1A\x93\x56\x9C\x9E\xC4\x96\x9F\xD5\x9A\x95\xD7\x91\x96\xD9\x90\x9F\x3D\x1A\x89\xFE\x98\x93\x8A\x9F\x8E\xA9\x93\xA0\x48\x93\x9E\xF9\x96\x9F\x85\x9B\x9D\x8E\x8D\x9D\x50\x93\x9F\xA3\x93\x13\x9A\x86\x8F\xFF\x92\x9D\x01\xA4\x9F\x33\x10\xA1\x37\x98\x9F\x06\xAA\x9F\x9C\x9C\x9F\x17\xAE\x9A\x20\xAB\x98\xD4\x93\x9B\x07\x43\x98\x37\x9A\x9D\x4C\x94\x93\x37\x13\x9C\x2E\xA2\xA0\x30\xA0\x98\xB5\x92\xA2\xE6\x98\x9B\x2A\xA2\x10\x60\x1C\xA2\xDE\x9A\xA1\xB1\x93\x95\x0A\x13\xA4\xC2\x9D\xA0\x01\x9F\xA0\x3B\xAF\x95\x3D\xAB\xA1\x3F\xA6\x10\xCE\x93\x1E\x9A\x8A\xA4\xEB\x8C\xA4\x2E\x9E\xA4\xE2\x91\xA3\x07\xAB\x8F\x16\xA2\xA4\x18\xA1\x99\x46\xA0\x9E\xF5\x9E\xA3\x97\x95\x94\xE4\x98\xA6\xD1\x93\x10\xE8\x9F\x9C\x09\x1A\x15\x44\xA9\xA1\x21\xA2\xA5\xEF\x91\xA7\x63\xA2\x9F\x75\xA7\xA4\x23\xAF\xA4\x03\x10\x96\xDB\x12\xA3\x25\x9B\x9F\x61\xA1\x10\x72\xAB\xA4\x00\xA9\xA3\x6C\xA4\xA2\x25\x95\xA0\x81\xAF", - "\xA5\xFD\x91\xA4\x86\xA9\xA7\x79\x9D\x13\x7B\x9A\x95\x8C\xA4\x8F\x6A\xA3\xA1\x6C\xA5\xA1\xBD\x8F\xA1\x2B\xAB\xA7\x66\xA3\x13\x97\xA8\x94\x99\xAF\x97\x50\xAB\xA6\x76\xAD\xA6\xE6\x8F\x9D\x96\x96\x9C\x7E\xA2\x10\x1E\xA5\x93\x90\xAF\x89\xAE\xAF\xAA\xA7\xAE\x95\x03\x12\xA8\x82\xA1\x9F\x6F\xAB\xA5\xCB\x95\xAA\x37\x99\xAB\x37\x16\xA2\x8F\xA8\xA2\xCD\x97\xAB\x96\x94\xAC\x6F\x9E\xA5\xC8\xA1\xA9\x65\xAF\xAA\xFF\x0C\xAC\xA6\x9B\xA9\x27\xA4\xA1\xE7\x9A\xAC\x63\x92\xAC\x25\x94\xAD\x69\xA9\x10\x80\xAA\x90\xB5\xAD\xAA\xD1\xA8\xAB\xB1\xA3\x89\x51\xAC\xA7\x53\xA6\xAB\xE5\xAB\xAC\xE7\xA0\x00\xBC\xA3\xAE\x01\x1F\xAB\x7A\x99\x9A\xDC\xA2\x8F\x5D\xA0\xAE\xE9\xA3\xAA\xEB\xA4\xAE\xA2\xA2\xAD\xDE\xA7\x9F\xCE\xA8\xAD\x60\xAF\xAF\xE6\xA9\xAF\x06\x11\xAF\xCF\xAE\xA6\xBB\x86\x10\xB6\x83\x1E\xB8\x8B\x8A\xBA\x89\x8B\x09\x1F\xB0\x9A\xA5\xB1\x0D\xB1\x8A\x19\xB5\x8A\x1B\xB9\x8A\x1D\xBD\x8A\x1F\xB1\x2F\xF1\x97\x18\xAC\x83\x8C\xAC\x21\x9F\xC7\x86\xB0\x96\x97\xAF\x31\x96\x9F\xC6\xA2\xAE\x0B\xBE\xAF\x8A\xAB\xAA\x01\xBE\xA8\x30\xB4\xB0\xD0\xAA\xB2", - "\x7C\x9F\xAE\x0A\xB8\xB3\x0C\xB7\xB2\xA0\xA2\x10\xC1\x91\x8C\x05\xBF\x2C\xF1\x97\xA8\x46\xB1\xB4\x01\x13\xB4\x0E\xA8\xB0\x03\x1C\xAD\x87\x11\x9F\x82\xAC\xB2\xBA\xA2\x10\x48\xB1\x30\xF1\x98\xA5\xB2\x86\x97\x40\xBC\xA0\x3C\xA4\xB1\x06\x10\xB5\xF2\xA0\xAF\xDA\xA4\xA0\x0A\x1F\x21\x5D\xB7\xA3\x0A\x1C\x10\xED\xA6\x9D\xC6\x84\x8C\x4A\xB0\x00\x5A\xB7\x8B\x67\xB0\xB7\x5E\xB6\x10\x6C\xB2\xB1\x09\x18\xB6\x9F\xA7\xB7\x03\x19\xB7\x33\xBA\xAE\xDF\xA4\xA5\x76\xBA\xB6\x09\x12\x24\x60\xBA\xB1\x89\xBC\xB1\x8B\xBE\xB1\x8D\xB0\xB2\x8F\xB6\xB1\xA8\xAA\xB8\x7A\xBE\xB0\x1F\xB2\xB9\x55\xBE\xB8\x95\xB1\x91\x5D\x23\xB2\x1F\xB6\xB2\x7D\xB6\xB8\x06\x19\xB2\x81\xBC\xAF\x83\xB3\x10\xFA\x19\xB6\xB7\x96\x10\x73\xB0\xB1\x29\xAF\xB8\x55\xA5\xAF\xCB\x9C\xB4\x82\xBF\x0F\xB4\xB6\xBA\xFF\x0D\xA1\x79\xA6\x01\x65\xB1\xA1\x0A\x19\xBA\xA1\xBB\xBA\x03\x1D\xBA\x3B\x99\x91\xF1\x9C\xBB\x6D\xB6\xB6\x09\x10\xBC\x49\xBE\xB7\x62\xAF\xB8\x0A\x07\xB9\xD2\xB1\xB9\xD3\xBB\xB9\x8C\xB6\xBD\x9A\xB4\xB4\x96\xB4\xBD\xDC\xB8\xBD\x4E\x1D\xB9\x71\xB4\xB2\xC2\x85\xB8\xC2", - "\xB2\x10\xA4\xBD\xB4\x2E\xB9\xAD\xDD\xBA\xBD\x94\xBC\xBE\xD7\xBE\xBE\xD9\xBB\xB5\x18\xBB\xBE\xF2\xBB\xBD\xDE\xB8\xB9\xC5\xA3\xB1\xDE\xB2\xB2\xE1\xBF\xB9\xE4\xBD\xAF\x01\x17\xBE\x4D\xAE\xB4\x02\x13\x91\xE0\xBE\xBC\x5F\x1F\xB1\xD1\xBF\xB8\xF4\xA3\xB9\x02\x1D\xC0\x3A\x14\xB5\xF9\xB7\x98\xD5\xB0\xBF\x90\xB7\xBF\x15\xC5\xBF\xED\xBA\xC1\xEF\xBC\xC1\xF1\xB4\xB7\xF3\xB8\xC1\x8F\xBC\xBF\x08\xCF\xBD\x0E\xC1\x10\xA0\xBD\xBC\xA2\xB3\x10\x02\xC0\xAC\xE9\xB9\x10\xC4\xB4\x22\x59\xBF\xB1\x8C\xA2\xC1\x33\x17\xBB\xD2\xAC\x8A\x57\xB0\x1E\x38\xCF\xAA\xAC\x8D\xC2\x46\x1D\xC3\x96\x92\xC4\x63\x94\xC4\x5A\x96\xC4\x48\x98\xC4\x25\xAA\x16\xD4\x1A\xC4\x8D\xA9\xA4\xD4\x1B\xC3\xB8\xB6\xC3\x32\x12\xC5\xD2\xA4\xC5\x31\x16\xC5\xAF\xA8\xC5\xFF\x0A\xC5\x2B\xB9\x9A\x5E\xCB\xAD\xA9\x9E\xC4\x41\xCF\xAE\x61\xC7\xC3\x63\xCF\xAE\x40\xCD\x13\x64\xCC\xC6\x69\xC3\xBB\x6F\xC6\x9F\x6D\xCA\x13\x73\xC7\x13\x75\xCD\xAC\x09\x16\xC0\x6E\xC0\xC7\x04\xC9\xC0\x84\x17\xC7\xD5\xA5\xB4\xDB\x10\xC8\xA7\xB6\xB5\x4D\xCA\xC6\x87\xCC\xC7\x72\xC1\xC7\x6C\xA4\xC8\x02\xB9", - "\xC7\x89\xCF\xC2\xAC\xBF\xB1\x0B\xA7\x13\x5C\xCC\x8A\xF8\x1F\xC7\x8C\xCB\xAA\x3A\xCF\xB1\x99\xC2\x1A\x8E\xCE\xC8\x3F\xCE\xC9\x91\xCD\xC8\x9B\xC5\xBB\x98\xC5\xCA\xAB\xA1\xCA\xEF\xAF\xC9\xB2\x1C\xCA\x7D\xC0\x00\x7A\xC9\xB9\x00\x0E\xCA\x83\xC7\xCA\xB8\xBC\x8A\x31\xC4\xCB\xB6\xCC\xC3\xEF\xA5\xC9\xA4\xA8\xCB\xD2\xA2\xCA\x0A\x17\xC6\x32\x10\xCB\x92\xCC\xC2\xAA\xC5\xBB\xC8\xC6\xCA\x8A\xCE\xCC\x8B\xCF\xCC\x9C\xCC\xC4\x9A\xC2\xCD\xA8\xC0\xC5\xD5\xC9\xCC\x02\x10\xCC\x32\x1C\xC5\xCD\xC3\xCD\x78\xA9\xCD\xD0\xCC\xA6\xA3\xC2\xCE\xAB\xC2\xCC\xAF\xAF\xCD\xCC\xC8\xCE\x43\xCF\xAE\xB3\xC6\xC7\xEC\xCE\xB6\x30\xCB\xCC\xB9\xC8\xA0\x25\xC1\xAE\xEB\x96\x10\x8C\xA3\x91\xFB\xCA\x10\x19\x09\xA7\xFF\xC3\xA7\x01\x14\x24\x02\xD0\x00\x15\x09\xA7\x07\xD4\x18\xC6\xC7\x93\x0B\xD3\xA8\x0A\x1D\xCB\xF9\xC8\xBA\x79\xA8\xBF\xE5\xB8\xC2\x79\xA9\xC2\x1A\x99\x10\x0B\xC8\xA8\x06\x1F\xCE\x33\x1D\xD0\xF1\x9C\xAD\x20\xD1\xB7\xDC\xA3\x91\x7C\xB9\xA5\x7B\xB9\xA7\x27\xDB\x1D\xBB\x6C\x93\x2E\xDF\xD2\x30\xD1\xD3\x3C\x9A\xA0\xBB\x22\xC5\x2F\x9D\xBA\x38\xD8\xCD", - "\x93\xC3\xCF\x3C\xDB\xD3\x3E\xD3\xBC\x3A\xD3\x10\x88\x9B\x90\x13\x9B\xD1\x3F\xBE\x90\xEA\xB8\xD4\x40\xAB\xD4\x4A\xDD\xD4\x47\xDF\xD4\x0F\xC1\x92\x52\xDA\xAF\x54\xD9\xAA\x56\xDF\xA7\x53\xD7\xD5\x02\x18\xCF\xF8\xCF\xB0\x18\xD1\x10\x10\xDC\xBC\x02\x12\xD6\x01\x14\xD6\x00\x06\xD6\x68\xDF\xBB\x6A\xDB\xBC\x6B\xD6\x10\x66\xD5\xA5\x2D\x9D\xC2\x2B\xD1\x10\x73\xD6\xD0\x0A\x18\xBC\x06\x18\xB8\x2D\xA2\x10\x7A\xDA\xCC\x87\xB5\xB7\x7F\xD9\xD2\x81\xD6\x10\x09\xD9\xD7\x77\xDA\x10\x04\xD6\x10\x01\xDB\xD7\x01\x1B\xD8\x7E\xDA\xD8\x80\xD0\xD9\x82\xD2\xD9\x84\xDE\xCF\x87\xD9\x10\x80\xB2\x10\x63\x23\xD8\x45\xA6\x10\x9B\xD6\xD8\x09\x1D\xC2\x9F\xD3\x10\x7D\xD2\x10\x75\xD3\xDA\x7C\xD1\xD9\x03\x18\xDA\x01\x15\xDA\x01\x15\xD8\xAB\xDA\x10\xAE\xD0\x00\x78\xD1\xDB\x09\x19\xD8\x03\x15\x26\x9C\xD4\xA7\xB9\xD2\xDB\x6F\xB9\x10\xBA\xD0\xDA\x06\x15\xD7\xC1\xD4\xDA\xAA\xD2\x10\xC5\xD9\xDA\x09\x10\xDB\xC8\xDE\xDB\x09\x15\xDB\xCD\xD7\xDB\x0D\x1E\xDC\x8C\xD0\x00\x0E\x1B\xDB\x01\xC3\xDD\xD8\xD0\x00\x75\xD7\xDD\xC2\xD3\x10\xDD\xD4\xDD\x03\x1C\xDC\x01", - "\x1E\xDD\xC6\xDF\xDC\xDA\xD6\x10\xB8\xD2\x10\x1E\x0E\xD2\xD0\xD1\xD3\x4F\x08\x8A\xBA\xB9\x10\xA0\x23\xD3\x72\x27\xBB\x2D\x02\xD3\x03\x10\x05\xF2\xDB\x2B\xF9\xDA\xDF\x01\x11\x05\xFD\xD9\x10\x2F\x99\x35\x00\xE0\x00\x52\x03\xE0\x61\xBA\x10\x06\xE0\xE0\x53\x0A\xE0\x11\x94\x38\x07\xE4\x05\x10\xE2\x10\x88\x9E\x3A\x07\xE5\x05\x15\xE1\x10\x17\xE7\xE0\x00\x06\x05\x1B\xE4\xB6\x09\x19\x3B\x3C\x97\xBB\x57\x01\xE2\x0B\x9D\x3B\x25\xEA\x10\x58\x01\xE2\x35\x12\x05\x1E\xE9\x05\x2E\xEC\xE2\x1E\xEA\x05\x21\xE6\xD4\x02\x17\x49\x07\xEB\x05\x21\xEF\xAB\x9C\x47\xE0\x5C\x0D\xE3\x0A\x1F\xE3\x00\xED\x05\x33\xE9\x10\x13\x57\xE0\x5E\x01\xE2\x0F\xB6\x54\x07\xEF\x05\x21\xE2\xC5\x93\x5B\xE2\x04\x2D\xBA\xA7\x54\xE5\x4D\x23\x91\xA2\x58\xE5\x6C\x28\xCF\xA0\x5C\xE5\x77\x2F\xD5\x00\x05\x59\x60\xEA\x27\x10\xDF\x5D\x65\xE0\x00\x60\x01\xE2\xAC\x87\x5D\x07\xE1\x06\x21\xE7\xE6\x2E\xD7\xBB\x62\x0C\xE6\x0A\x1E\xE6\x00\xE3\x06\x21\xE6\xD6\xE5\x57\xE0\x64\x0B\xE7\x0A\x17\x5E\x07\xE5\x06\x80\xE9\x10\x82\xE0\xE0\x66\x01\xE2\x03\x0A\x92\x09\x1E\xC4\x1E\xEC", - "\x88\x8E\x35\x13\x82\xAF\xD2\xF3\xDA\x37\x35\x1C\xA8\x2F\xD6\xB3\x1C\x45\x13\xBB\xC7\x1C\x35\x17\xBB\xB3\xA8\x2F\x35\x18\xE3\x7A\x25\x13\x52\xC1\xEA\xFE\x26\xEA\x72\x25\x13\x2F\x98\xEA\x48\x35\x13\x1E\xD3\x1C\x9C\xE8\x5A\xAC\xEB\xEA\x0A\x18\x98\xAE\xE4\x2F\x35\x1C\xCD\xD7\x12\xE9\xB4\xEF\xD0\xB6\xE0\xC9\x21\x54\xEA\x00\x0C\xEB\xDC\x15\x13\x66\xD2\x1E\x35\x18\xCF\x9A\x8F\xB0\xC6\xEB\xEB\x9D\x45\x13\x10\xDE\xE8\x72\x2C\x8A\xB3\xDA\xEC\x5A\xAD\xBA\xEB\xD8\xAE\x04\x2C\x8A\xDB\xEB\x27\x35\x1E\xD8\xCF\xB6\x10\x83\x26\xA3\xBF\x1C\x8A\xE2\xE5\xEA\x0A\x15\x28\x3D\xD3\x10\x26\x0D\x49\xA0\xE1\xEC\x06\x18\x2B\x8D\xEE\x38\xB7\xB7\xED\xE5\x15\x13\x2A\x01\xD4\x02\x14\x30\x06\x19\xEB\xDC\x17\xBB\xDF\xE8\xED\x07\x3C\xEF\x01\x17\x35\xE6\xE3\x1C\xB7\xB9\xEE\xE0\xEC\xE0\x06\xF0\x00\x3E\x0D\x49\xA7\xE2\xEF\x03\x12\x38\xF5\xE0\x39\x52\xC8\xEF\xC5\x15\x13\x1A\x1D\xEE\x02\x14\x3B\xFF\xE2\x27\x52\xC3\xF0\xF9\xEA\x10\xB7\x3E\xF1\x01\x17\x3C\x09\xF7\x1D\x52\xCC\xF0\x04\xF6\x10\xC9\x38\xF2\x1F\xED\x49\xAD\xE4\xF1\x02\x14\x42\x17\xFA\x37", - "\x2F\x9A\xF1\x9E\xE1\x12\x0F\xF3\x4B\x2B\xFC\x1D\x2F\x94\xF2\x1B\xFA\x10\xBE\x42\xF3\x15\x51\xF4\xB5\xE9\x10\x2E\xF5\xF2\x09\x10\x52\x3F\xD2\x10\x6A\x5A\xF4\x0F\xF0\xF0\x2F\xDE\x56\xDC\x90\x39\xAD\xBC\xF3\xBF\x15\x13\x64\xE1\xF5\xD6\x5D\x49\xDA\xE6\xF3\x01\x18\xE6\x60\xF0\x00\xEB\x54\xF5\x32\xFD\xF4\x45\xF9\x10\xED\x52\xF3\x14\x6A\xF6\xFA\xC1\xED\x0A\x1D\x61\x39\xF7\x3D\x88\x9C\xF5\xB2\xEA\x10\x37\x62\xF3\x69\x62\xF7\x42\xD8\xD8\x64\xF0\x00\x78\x62\xF3\xA8\x60\xF8\x16\xE6\xD9\x04\x25\x13\xAA\x62\xF3\xB6\x68\xF8\x01\x1B\x90\x56\xFE\xD2\x9F\x00\x9D\x51\x2B\x90\x7A\xFD\xEB\x0A\x14\x6D\x32\xF3\x6F\x90\xF2\xE2\xEA\xD3\xF8\xF5\x62\xF3\x02\x7F\xF9\x0B\x9C\xF6\x3D\xF9\x10\x12\x72\xF3\x40\x7F\xF9\x13\x93\xF9\x3C\x96\x74\x77\xFC\x3E\x13\x99\xF9\xC7\xEA\x10\x58\x72\xF3\x81\x7E\xFA\x82\xFB\xF8\x0A\x13\x78\x32\xF7\x0C\x9D\x43\x91\xA8\xFD\xF5\x0A\x12\x79\x32\xFB\x7C\x9F\xF4\xEC\xB0\xF9\x91\xD3\x73\xFB\xFD\x34\xEC\xB6\xFF\xD2\xE7\x72\xF3\xFE\x7B\xFC\xBD\xFD\x24\x35\x16\x80\x32\xFA\x82\xD8\xFC\xF4\x83\xFC\x82\x32\xF2\x84\x9F", - "\xFF\xAB\x14\xDB\xF7\x04\x24\x84\x82\xCA\x27\xCC\xE3\xF8\x48\x8F\xF9\xE2\x18\xCF\xD3\xFE\xD2\x4C\x81\xCE\x06\x1C\x85\x9F\xF8\xCF\x44\xF9\xFA\x06\x1E\x85\xF6\xF3\x10\x70\x41\xFF\x4A\x7C\xED\x7A\x10\x72\x43\xFF\x62\x08\x7A\x47\xF3\x4F\x58\x7C\x6F\xF2\x2B\x26\x98\x70\x60\xFC\x7B\x95\x10\x68\x31\x7D\x00\xD3\x26\x59\x6D\x7E\x11\x4C\x0F\x70\x7F\xF2\x06\xD6\x73\x7C\x4F\x40\x44\x07\x81\x20\x09\x45\xCF\x76\xD6\x7B\x7E\xF1\x70\x09\xC5\x65\x39\x19\x44\x39\x16\xD6\x45\x7C\xFA\x66\x08\x04\x04\x12\x52\x62\x04\x0B\x02\x84\x11\x95\x58\x80\xC0\x41\x01\x35\x80\xBD\x15\xA5\x1E\x81\x46\x4A\x00\x32\x82\x18\x7B\x80\x36\x15\xA5\x26\x83\x0B\x83\x08\x0F\x01\x08\xA1\x6D\x21\x87\x27\x55\x52\x0B\x9A\x7C\x7B\x5A\x09\xAA\x6E\x26\x8A\x27\x2D\x48\x0E\x9C\x45\x19\x04\x0A\x9C\x21\x96\x4E\x03\x91\x4A\x06\x12\x82\x03\x0E\x03\x1A\x82\xF1\x0D\x92\x46\x80\x14\x84\x77\x60\x82\x20\x23\x01\x31\x85\x1E\x2D\x4B\x13\x97\x7D\xF4\x69\x0D\x81\x08\x14\x0C\x06\xC5\x0D\x0B\x75\x54\x6D\x7C\x91\x35\x6A\x6A\x7C\x93\x29\x01\x1D\x91\x80\xB2\x57\xB8\x51\x7D\xC1\x7A", - "\x02\x7F\x83\x6F\x15\x74\xE0\x6F\xD6\x43\x7D\x15\x06\x08\xC3\x0E\xA6\x75\x6B\x9D\x77\x04\x86\x08\x16\x0D\x08\xD7\x0D\xBC\x73\x6C\x03\x0C\xD8\x55\x81\x80\x0D\x02\x15\x84\x77\x13\x78\x98\x86\x90\x7E\x7D\x84\x0E\x02\x1E\x87\xD2\x61\x79\xA1\x81\x20\x31\x75\x33\x83\x10\x2F\x02\x29\x95\x7A\x82\x80\x00\x22\x5A\x9E\x40\x03\x2F\x84\x05\x61\x29\x75\x6F\xD9\x6E\x69\x18\x06\x0B\x89\x5A\x87\x00\x76\xA3\x86\x20\x32\x00\x2D\x83\x03\x14\x44\x2B\x4F\x7D\xB1\x81\xD9\x4E\x7A\x83\x05\x03\x5A\x82\x0D\x06\x86\x0A\x0C\xF9\x4A\x08\xF2\x60\xE9\x41\x87\x40\x18\x01\xBD\x84\x4D\x14\x87\x2E\x80\x8C\x39\x02\x1C\x80\x00\x3D\x01\x1B\x82\x08\x6A\x86\x06\xF0\x82\x41\x1E\x01\xDF\x82\x08\x22\x87\xD7\x63\x00\xEC\x11\x4D\x03\x02\xDF\x87\x08\x2B\x86\xDA\x63\x0D\x83\x7F\x13\x33\x6D\xB1\x5B\x19\xAB\x25\x6F\x7B\xC6\x79\x83\x2A\x2C\x78\x75\x6B\x13\xB7\x29\xCC\x61\x10\x49\x6E\xBA\x64\x10\x48\x00\x1A\x84\x10\x83\x80\x00\x2C\x6D\xC3\x67\x26\xE6\x6A\x20\x25\x76\x02\x83\xE2\x73\x86\x78\x13\x88\x03\x0C\xDD\x54\x89\x26\x1B\x04\x0A\x89\x93\x1A\x88\x03\x0E\x53", - "\x16\x87\x69\x20\x12\x82\x08\x40\x03\x89\xD9\x27\x24\x86\x08\x86\x82\x10\xE2\x0D\x13\x1E\x88\x50\x6C\xDB\x46\x08\x11\x0A\x10\x22\x8B\x46\x8B\x25\x36\x89\x0C\x83\x7D\x27\x06\x11\xE5\x0D\x7D\x73\x89\xF6\x86\x86\x10\x09\x84\x0A\x2B\x28\x88\x00\x10\x02\x5A\x81\x0A\x30\x89\x3B\x14\xEF\x06\x0B\xBB\x66\x8A\x53\x05\x27\x85\x0F\xA2\x83\xEF\x41\x88\x05\x32\x08\x09\x0A\x5A\x06\x8A\x2A\x02\x15\xC7\x0E\x56\x86\x08\xFA\x16\x28\xA2\x0F\x2A\x0B\x14\xFA\x10\xB5\x04\x8A\x83\x7F\x0A\x1A\x82\x2C\x05\x16\x80\x01\xFB\x69\x08\x67\x8E\x20\x2E\x00\xAB\x8B\x41\x7F\x6E\x41\x14\x8A\xEE\x81\x24\x1A\x83\x2D\x0D\x16\x8F\x5A\x26\x56\x8B\x03\x0B\x2E\xA2\x8A\x1B\x22\x18\x86\x0B\xBE\x66\x8A\x5D\x05\x2B\xBF\x0D\xB0\x83\x09\xF4\x88\x0D\x3E\x77\x03\x0B\x06\x03\x7C\x2F\x0A\x05\xDF\x01\x5B\x82\x0F\x32\x02\x21\x08\x18\xA3\x81\x06\x0A\x8F\x70\x12\x8C\x09\x09\x33\x83\x8C\x0A\x29\x32\x06\x08\xD4\x06\x8A\x62\x06\x33\x97\x0F\xD3\x86\x10\x3A\x02\x63\x83\x0E\x63\x07\x32\xA5\x0E\x84\x76\x10\x20\x8F\x4D\x82\x08\x65\x02\x0B\xA6\x03\xB6\x82\xE6\x1A\x44\x6D\x83", - "\x08\x39\x07\x35\x8B\x23\x06\x71\x19\x83\x7C\x1A\x1A\x82\x69\x05\x2D\x90\x68\x4D\x44\x1C\x82\x09\x70\x83\x8D\x1B\x27\x39\x8C\x87\xC1\x7B\x06\x2A\x8C\x77\x0E\x8D\x09\x0F\x37\xB7\x12\x72\x2C\x36\x06\x09\x0F\x03\x7C\x6C\x06\x3A\xB5\x09\xEF\x89\x10\x41\x02\x70\x9C\x0E\x6D\x02\x36\x85\x0F\x88\x70\xFD\x0F\x8A\x41\x0F\x03\xF3\x87\x02\x8A\x08\xF6\x8E\x0B\xC6\x88\x1C\x13\x87\x37\x83\x3E\x8A\x84\xA3\x81\x07\x73\x86\x15\x9A\x8F\x32\x7A\x20\xB2\x03\x79\x8D\xC2\x1A\x44\x7D\x99\x84\x83\x7B\x0E\x33\x87\xBA\x66\x20\xA9\x82\x51\x94\x03\xF3\x84\x1A\x8D\x90\x61\x77\x1B\x81\x09\x1D\x13\x87\xEF\x6D\x1A\xA7\x86\xAE\x55\x21\x80\x02\x1D\x13\x87\xB3\x6B\x42\xB9\x59\xBC\x89\x10\x77\x03\x3C\x9F\x76\x22\x90\x09\x83\x7C\x3C\x0A\x05\xF9\x01\x5B\x8C\x78\x29\x93\xAC\x43\x7D\x3D\x0A\x05\xFC\x01\x5B\x84\x88\x1A\x95\xE2\x4A\x09\xB7\x16\x14\xFE\x02\x78\x8A\x08\x12\x76\x20\x16\x79\x0E\x9F\x44\x66\x8D\x42\x07\x90\xDB\x8D\x98\x1D\x78\x83\x02\x3B\x46\x8B\x1F\x1A\x82\x80\x02\x3D\x87\x0E\xD6\x19\x10\x64\x8D\x87\x82\x04\xF3\x86\x21\x9A\x44\x2A\x96\x10", - "\x30\x1C\x74\x94\x21\x18\x76\x3B\x83\x7D\x41\x03\x0F\x8C\x8A\x26\x41\x93\x03\x0E\x4B\x84\x92\x1B\x2A\x26\x83\x0A\xE8\x06\x8A\x84\x07\x47\x89\x09\x26\x96\x10\x5C\x90\x89\x8C\x24\x20\x7B\x20\x00\x1E\xA3\x85\x08\x72\x92\x41\x19\x93\x02\x0B\x77\x06\x8A\x43\x0E\x27\x83\x08\x89\x76\x1D\x83\x7F\x10\x14\x44\x3E\x8C\x11\x8A\x08\x9D\x97\x93\x03\x0A\x11\x1A\x83\x45\x0D\x16\x91\x8A\x4C\x83\x08\x2A\x70\x51\x86\x8B\x46\x0B\x28\x8E\x1F\x9E\x8C\x92\x83\x78\x12\x1A\x83\x48\x0D\x16\xED\x6D\x48\x3E\x08\x09\x0C\x7C\x06\x8B\x49\x05\x28\x82\x09\xCC\x79\x7A\x1D\x94\x12\x33\x86\x8C\x81\x08\x89\x0B\xAB\x9B\x55\x83\x7D\x12\x33\x87\x92\x87\x29\xAE\x97\x7E\x9D\x90\x96\x03\x1E\xAA\x89\x50\x5B\xDF\x0F\x7A\x40\x97\x04\xF3\x84\x26\xA1\x29\x5B\x92\x10\x1A\x86\x3E\x82\x08\x98\x03\x1E\xB9\x89\x5A\x90\xF3\x0E\x91\x87\x99\x04\xF3\x87\x27\x84\x96\x5F\x94\x21\x90\x96\x40\x1A\x04\xF3\x83\x28\xA8\x85\x6A\x94\xE0\x03\x7F\x26\x13\x87\x4F\x8B\x5C\x85\x97\xF5\x7E\x1E\x83\x08\x27\x13\x87\x4D\x8B\x5B\x81\x08\x66\x90\xD6\x03\x7D\x27\x1A\x82\x9E\x05\x2D\xB8", - "\x8A\x6A\x9B\x2E\xEE\x6B\xE0\x60\x05\x5A\x81\x14\x2D\x8A\xAC\x8A\x2E\x82\x09\x14\x0A\x08\x2A\x7D\x43\xA3\x05\x56\x91\x10\x30\x71\x42\x07\x98\x5F\x93\x98\x2A\x94\x72\x9B\x26\x94\x20\xFE\x06\x08\x52\x26\x28\xA4\x04\x86\x93\xF3\x6D\x8E\x40\x85\x05\xF3\x87\x30\x85\x99\x80\x06\x41\x5F\x59\x87\x86\x05\xF3\x87\x2B\xB2\x97\x8E\x93\xF7\x46\x8B\x29\x13\x87\x71\x8B\x65\xA5\x99\xB3\x72\x10\xA8\x07\x3C\x80\x8C\xFC\x92\x20\x33\x98\x04\x96\x14\xA9\x07\x3C\x85\x8C\x32\x9E\x5A\x9E\x97\x80\x0A\x0A\x73\x84\x63\x81\x9A\xDD\x91\x49\x89\x09\x55\x03\x0F\x90\x8D\xCE\x84\x99\x1C\x93\x68\x80\x00\x56\x03\x0F\x9B\x8F\xC8\x8C\x99\xEC\x55\x43\xAD\x05\x79\x82\x1A\xD7\x9B\xCE\x82\x08\x10\x6A\x20\xAE\x04\x2D\x8F\x0A\x6D\x8A\x6D\x88\x9A\xFE\x96\x28\xB1\x04\x2D\x82\x0B\x6D\x89\x69\x8B\x99\x38\x7E\x20\x06\x20\xA3\x84\x0B\x1C\x99\x0E\x29\x08\x71\x9A\x6A\x8F\x23\x8C\x96\x10\x5F\x9B\x41\x8C\x24\x6A\x26\x20\x3C\x22\xA3\x85\x0B\x1C\x9B\xE0\x86\x08\x47\x7D\x62\x87\x0E\x5B\x02\x25\xBF\x0F\x21\x29\x95\x83\x78\x17\x33\x86\xA0\x11\x52\x0F\x9C\xC6\x83\x7C", - "\xB9\x03\x1E\xAC\x8D\x95\x96\x39\x83\x08\xD0\x6A\x9C\x34\x22\xC7\x57\x9C\xA3\x8A\x0B\x73\x86\x76\x9D\x95\x01\x0A\x74\x9E\x9D\xF3\x8C\x38\x44\x73\xEA\x91\x98\x4B\x27\x73\x83\x08\x3D\x26\x14\xBB\x04\xC7\x89\x9C\x03\x0D\x73\x8A\x9A\x46\x20\x4D\x06\x09\xD2\x7D\x90\xBC\x04\x63\xAB\x26\x8F\x9F\x2C\x81\x09\x2F\x13\x87\xCD\x88\x75\x80\x01\xE1\x95\x1F\x9D\x92\x2F\x13\x87\xD2\x8B\x65\x8C\x9F\xC0\x76\x14\xBF\x07\x3C\x98\x8E\x57\x9B\x7A\xA3\x76\xA9\x90\x0C\x73\x85\x77\x92\x9E\xD1\x83\xF0\x41\x07\x79\x8C\x23\xD9\x9E\xD0\x9B\x9D\x03\x0A\x18\x33\x86\x2B\x90\x3E\xC9\x9B\xDF\x83\x08\xC3\x03\x1E\x88\x92\xE5\x9A\x3D\x81\x0B\x2C\x99\x48\xC4\x03\x1E\x83\x93\xF6\x93\x22\xE8\x9E\x40\x05\x06\xF3\x81\x48\xBC\x9E\x15\x96\x14\xC6\x06\x16\x87\x06\x6D\x8E\x48\xA6\x9E\xB6\x66\x14\xC9\x06\x16\x8A\x06\x6D\x8B\x49\xAB\x99\x83\x29\x10\x67\x26\x51\x8C\x06\x1C\x99\xC9\x46\x08\x0A\xA0\x3A\xC3\x27\xEF\x83\x08\xF5\x9D\x5D\x93\x26\xA8\x73\x10\x28\x2A\x51\x8D\x06\x1C\x9E\x84\x86\x09\xA9\x7D\x41\xD7\x0E\x33\x0D\x9C\xC3\x0B\xA7\x09\x09\x0F\xAE\x3F\x81", - "\x08\x34\x13\x87\x6F\x97\x6A\xB2\xA0\x83\x06\x55\x30\x9D\x1B\x2E\x72\x3C\xA4\x75\x8E\x1D\x1E\xA6\x10\x23\x2A\x51\x91\x06\x1C\x9C\x85\x83\x09\x1D\xAA\x37\xB6\x20\xD6\x63\x08\x2A\x9D\x86\x80\x00\x69\x00\x43\xD7\x0E\x9D\x8F\x9A\x00\x07\x89\x82\x09\xCD\x92\x45\xD4\x05\x15\xBC\x0E\x68\x90\x8B\x9A\xA3\x80\x0F\x29\xD2\x9A\x35\x1F\xA2\x35\x0D\x4D\xA2\xA2\x85\x02\x28\x9D\x90\x36\x08\xA3\x8E\x91\x2C\x23\xA2\x00\x07\x38\xD2\x9A\x36\x10\xA3\x09\x08\x50\x8A\x9F\x39\xAA\x42\xD2\x98\x37\x18\xA3\x9A\x97\x6A\x93\x72\x83\x08\x58\x46\x8A\x37\x00\xA4\x6C\x17\xEB\x43\x09\x42\xAD\x21\xE0\x04\x22\xB7\x13\x5F\x74\x90\x83\x7C\x71\x0F\x48\xFA\x13\x96\x72\xA4\x46\x8C\x1C\x15\xA5\x3D\x17\xE5\x18\xA5\x87\x86\x07\x9B\xA2\x3C\x38\x2C\x83\x01\x45\xEF\x9E\x40\x08\x07\x9D\x94\x40\x07\x95\xAC\x93\x10\x23\xA7\x40\x1C\xA2\xA6\xA1\x20\x2B\x07\x54\xAD\x24\x19\x94\x2B\xA2\x08\xAE\xA2\x20\x25\xA2\x29\xAE\x0E\x34\xA4\x9B\x08\x95\xFD\x99\x20\x39\xA5\x80\x0D\x46\xD2\x99\x3C\x1E\xA5\x77\x14\x5E\x85\x77\x94\x0A\x10\x75\xA2\x14\xB4\x07\xC8\xA2\x4F\x0E\x99", - "\x60\xAE\x21\x8A\x09\x1F\xB2\xA2\xF7\x01\x9A\xBB\x13\x8B\x97\x4B\xC2\xA6\x42\x14\x95\xB1\xA0\x00\x3A\x07\x4D\xAE\x37\xB9\x92\x40\x18\x73\x50\xA3\xF0\x7C\x07\x4D\xA9\x37\xDB\x67\x9D\x6A\x08\xB0\xA2\x84\xA2\x81\x4D\xAC\x37\xDD\xA4\x00\x08\xA7\xBA\xA3\xF0\x4B\xA6\x6A\xA2\x1E\x34\x9C\x35\xB8\xA7\xC4\xA3\xF0\x42\x00\x54\x4A\x0B\x89\x0A\xEE\x81\x08\x6D\x75\x99\x83\x7C\x02\x04\x50\xF2\x12\xEB\x8E\xA7\x09\x08\xA0\x80\x01\x6B\xA1\x4E\x86\x01\x43\xA4\x10\xB8\x98\xA2\x86\x08\x89\xA0\x4E\xF2\xA4\xBC\x41\x71\xE2\x0E\x82\x97\x9A\xB3\x73\x10\x3E\x2E\x51\x89\x00\x20\xAC\x5F\x21\x2E\x52\xA3\xF8\x0A\x00\x2A\x4D\x68\x35\x09\x84\xB7\x5D\x95\xAF\x4A\x83\x7E\x03\x0F\xA9\x72\x14\x86\x8B\x5B\x95\x0A\x10\x3B\xA5\x38\xB2\x00\x38\xAC\x40\x14\xA8\x00\x03\x53\xEC\xA3\xE0\x76\x00\x41\xAD\x49\x04\xA3\x81\x05\x54\x89\x0A\x33\xA1\xA7\x1A\x01\xA9\xAC\x12\x46\xAC\x54\xBC\xA9\x42\x03\xAA\x02\x8E\x03\x12\xAA\x48\xAB\x2B\x34\xAA\x44\x83\x7C\x22\x00\x15\x4C\x95\x56\xAA\x9E\x7D\x72\x41\x03\x2F\x46\x8D\x04\x29\xA8\x7B\x16\x56\xE9\xA6\x51\x86\x01\x62", - "\xAA\x4E\x12\xA9\xDB\x5D\x56\xDB\xA3\xE0\x69\x01\x71\xAC\x40\x28\xAA\x58\x93\x10\x75\xA8\x19\xA3\x7C\x2C\x01\xAF\x8D\x13\xF4\x2D\x1E\xFE\xA8\x00\x05\xA6\x52\xA7\x05\x02\xAC\x36\x1F\x5E\x05\xAE\x42\xA6\x8A\x32\x03\xB1\xB6\x2F\x5D\x16\x58\xD8\xA9\xF1\x80\x00\x35\x02\xB2\xBA\x12\xBB\x7C\x57\x82\x0A\x61\xBD\xA8\x02\x88\x07\x17\xA9\x26\x1D\xF7\x54\xA7\xA1\x63\x08\x7B\xAA\x6A\xBA\x01\xB5\xA8\x2F\x27\xAE\x40\x05\xA5\x1E\xAB\x07\x1A\xAD\x3D\x12\x64\x6D\x8E\x6B\xA1\x08\xF1\xA2\x20\xBE\x01\xD9\xA2\x1E\x59\x32\x6D\xBD\xA9\x83\x79\x08\x3C\xAD\xF2\x0D\x67\x3F\xAD\x42\x08\xAC\xE1\xA4\x08\x03\xAF\xE2\x04\x6A\x46\xAE\xE0\x83\x7C\x47\x03\xB9\x87\x0F\xC6\x7D\x59\x81\x0B\x6D\xB3\xA8\x83\x7A\x09\x12\xAF\xDF\x00\x6B\x4E\xAF\x40\x00\xAD\x97\xAD\x09\x23\xAC\x36\x1F\xF8\x54\xA4\x61\xA6\x5E\xF9\x75\x24\x7E\x75\x47\x77\x0A\x99\x48\x62\x4E\x0A\xB7\x5E\x29\x2C\x44\xA7\x0C\xE8\x0F\x7A\x53\x12\x62\x4E\x0C\xD8\x79\xAF\x97\x6A\x5F\xA3\x74\x7F\xAF\x69\x13\x4E\x29\x3F\x54\xA7\x08\xCF\x04\xB3\x4B\x6F\x58\x4E\x08\xC1\xB5\x08\x05\xB9\xD4\x19\x49", - "\x81\xAB\xB0\x35\x0E\xEA\x40\x79\xDC\x59\xE9\x6C\x0E\xB1\x6F\x64\x3C\x4B\xBE\x90\x76\x97\x6A\x61\xEA\x4E\x7C\xAF\x69\x8E\x74\x8C\x71\xAF\x4F\x7F\xD2\x30\xA8\x48\x78\xAF\xAA\x76\xA5\x68\xB1\xF3\x90\x8C\x2B\xB1\xB9\x86\x0C\xF7\x57\x25\x4E\x0A\x19\xB3\xEB\x06\x0D\x24\x93\x09\xAD\x5E\x29\x39\xB1\x1A\xBC\x93\x3B\xB2\x7D\xB7\x74\xEC\x09\x53\x6F\xAE\x20\xBE\xD2\x43\xB3\xAF\x8E\xAF\x2F\x6B\xD2\x7D\x55\x85\x4E\x14\x4C\xB3\x7A\xBC\x49\x4E\xB4\x9A\x51\x0F\x55\x8C\x9B\x0B\x44\x32\x92\xB2\x19\x49\xC0\xBE\xAE\xC3\x0E\x2C\xBD\x09\x7F\xA1\x9F\x2E\x6F\xCB\x9A\x69\x97\x60\x01\xB8\x09\x99\xB3\x09\x03\xB5\x26\x29\xB3\x06\xB1\x91\x6B\xB1\x55\x69\x0F\x0C\x86\x28\x0F\xB1\xAC\x6E\x60\xAF\x6B\x9C\xAF\xB3\x11\x4F\xCE\xB6\x5F\xF4\x07\xFE\x32\x08\x83\xA1\x61\x19\x4F\xCF\xBB\xB3\x88\x44\x01\xC9\x09\xA1\xBD\x09\x62\x76\x29\x09\xB5\x9A\x0B\x68\xE3\x5E\x4B\x6D\xB4\xF7\x0C\x3D\x21\x9A\xA3\x00\xD1\x4E\x08\x44\x78\xAF\xD3\x72\xDA\x5E\xB1\xE5\x88\xEC\x6C\x0E\x32\x9D\x09\x66\x6E\x29\x21\xB5\x9A\x09\x0F\xC0\x09\xA9\xBA\x09\x55\x56\x29\x29\xB5\x97", - "\x60", + "\x42\xAA\x01\x00\xE4\x1D\x00\x00\x21\x00\x01\x82\x80\x02\x0B\x82\x81\x82\x06\x89\x82\x9F\x7C\x85\x84\x87\x0C\x0A\x80\x89\x85\x1A\x84\x16\x84\x18\x0A\xB7\x0A\x9E\x1A\x84\x22\x84\x25\x0A\xD0\x0A\x96\x2A\x86\x2E\x84\x32\x0A\xEB\x0A\x92\x3A\x86\x3A\x84\x57\x10\x09\x8E\x8E\x8A\x80\x03\x99\x86\x35\xB7\x8C\x99\x9A\x9C\x9F\x9A\x9F\x33\xC0\xB4\x8A\x8A\x9F\x7E\xA0\x9C\x44\xBD\x89\xBF\x95\x9A\x85\x00\xA7\x50\x89\x82\x11\xA6\x83\x00\xAB\x81\x04\x57\x82\x85\x0A\xA9\x82\x03\xAE\x00\x07\x20\xA8\x00\xB5\xA3\xA3\x9D\x0A\x89\x25\xAA\xA2\x9C\xB6\x82\xB3\x4B\xC1\xB1\xA3\xAD\xB4\xA5\xBA\xB9\x77\xF4\xAF\xAE\xB3\x80\xB9\xBC\xA4\x7F\xE8\x81\xC6\xA3\xB8\xC3\xBC\xBB\x87\xF8\x89\xDA\xBD\xBC\xBF\x84\xC7\x01\xFE\x8B\xC6\xCD\xC0\xC5\xCA\xC5\x97\x8C\xCF\xD6\xCB\xC8\xCD\xCE\xCD\x91\x90\xF6\x82\xD2\xC9\xCC\xCB\xCF\xA7\xA1\xDC\xCA\xDE\xCC\xD4\xD1\xD1\xAB\xB0\xED\xD2\xDF\xD5\xD0\xD4\xC1\x93\xB8\xE6\xDA\xD7\xDC\xC3\xC1\xB3\xBE\xB9\xC1\xFB\xD3\xE2\x82\x04\xB0\x0B\x0A\x96\xBF\xD5\xC4\xDE\xD7\xD4\xB4\xD0\xF6\xCF\xEE\xE1\xE9\xEB\xE9\xD6\xC5\xD4\xFA", + "\xE9\xE8\xE2\xEF\xE6\xDC\xD8\xE2\xE4\xD4\xF1\xDB\xF0\xF3\xE5\xB3\xE7\xEA\xF9\xF5\xD9\xF6\xE9\xEF\xD7\xF1\xFC\xEE\x00\xB3\x06\xE5\xE0\xDF\xCC\xFB\xF2\xE2\xFD\xFF\xFC\x00\xBC\x74\x72\x7F\x03\x81\x8F\x7E\x80\xBD\x44\x89\x82\x81\x05\x88\x8B\x76\x82\x0F\x8C\x8B\x82\x83\xDD\x52\x81\x84\x85\xD8\x48\x46\x43\x53\x09\x53\x08\x7C\x86\xF3\x50\x85\x84\x88\xE8\x65\x8C\x7A\x89\xEE\x68\x80\x7E\x8A\xF2\x6C\x81\x79\x88\x16\xA3\x87\x83\x8C\x0D\xB4\x83\x86\x8D\x17\xB8\x82\x8D\x8D\x3C\xB7\x83\x42\x05\x60\x57\x0F\x86\x8E\xEB\x69\x87\x8B\x91\x46\x89\x9B\x88\x92\x4B\x8A\x9D\x88\x93\x4F\x8E\x9F\x8A\x8B\x22\x85\x9D\x93\x95\x51\x98\x93\x94\x94\x5B\x92\x95\x94\x8C\x14\x9A\x00\x5B\x06\x43\xBD\x89\x8E\x99\x3B\xBE\x8A\x9B\x99\x6B\xA9\x9C\x9B\x9B\x6E\xB1\x96\x95\x96\x74\x9D\x9A\x97\x97\x54\xB1\x83\x9E\x9D\x75\xB8\x9C\x96\x9F\x5E\x8A\x4E\x04\x58\x1F\x25\x9D\x9B\x9E\x80\xB7\x9A\x9C\x98\x44\x8C\xA8\x98\xA2\x8B\xB9\x94\x8B\x9F\x91\x94\xA3\xA5\xA0\x97\x8A\xA9\xA5\x9F\x0A\x62\x00\x5B\x08\x86\xB0\x90\xA7\xA6\x7C\xA5\xA9\xA0\xA7\xA4\xA7\xA6\xA9\xA5", + "\x98\x8D\xA2\xA6\xAB\x96\xB0\xAD\xAB\xA3\x8E\x87\xA5\xAD\x40\x26\x20\x57\x09\xA8\x72\xB7\xAD\xAF\xAB\xB4\x80\xB6\xAE\xB0\xA2\xBE\xA3\xAA\xAC\x9A\x88\xB8\xAA\xB2\xAB\xA9\xAC\xA9\xB2\xC1\xB3\x6A\x08\x58\x2B\x3C\xA7\xB1\xB4\xB3\x83\xB1\xAC\xB6\xD0\x9A\xB9\xB5\xB1\xC4\xBF\xAB\xB6\xB7\xDD\xA0\xB3\xBA\xB9\xDF\xA2\xB9\xBB\xB5\xE4\x8B\xBC\xB6\xBB\xED\x8D\xBC\xB2\xAA\xF4\x8F\xB0\xBC\xBA\xE5\x80\x0E\x0B\x5A\xE1\xAC\xB8\xBF\xBD\xEA\xB9\xBE\xBC\x00\x2F\x20\x58\x45\x42\xCB\x73\xB6\xBE\xBC\xEF\x8C\xC1\xBD\xBD\xCE\x91\xCA\xC2\xC4\x0D\xD0\xC3\xC7\xC5\x15\xCB\xC6\xC5\xC6\x14\xCF\xCA\xC7\xC7\x1D\xFF\xBE\xC2\xC8\x1B\xDE\xC1\xC9\xC0\xD5\x73\x0C\xBF\xB9\x28\xE3\xCD\xC9\xC9\x24\xE0\xC8\xC6\xC9\x33\xF1\xC7\xCB\xC0\x38\xC6\xBA\xCD\xBF\x3B\xEC\xC9\xCD\x6C\x34\x2B\xC9\xB9\x0D\x60\x76\x06\xB5\xCF\xEB\x88\xD2\xC2\xD2\x00\xFF\xCE\xCC\xD3\x2E\xCE\xD9\xD0\xCF\x54\xCF\xD5\xD7\x6B\x39\x20\x5A\x0F\xD1\x57\xCB\xDD\xD5\xD3\x50\xF0\xCF\xCA\xCC\x1C\xF5\xC3\xDB\xCD\x61\xE4\xD4\xCD\xD9\x6C\xEB\xDE\xDA\xCD\x66\xD2\xDE\xD6\xD5\x74\xD3\xD5\xDF\xDC\xAF", + "\x7D\x02\xD0\xDE\x7C\xE0\xDF\xD5\xD4\x69\xE8\xDF\xDE\x88\x1C\x49\x4C\x86\x41\x3F\x20\x50\x10\x58\x41\x20\x52\x10\x58\x43\x20\x5E\x46\xE1\x0A\x45\x10\x5A\x11\x7B\xC0\xC7\x11\xE6\x80\xC3\xEA\xD8\xDC\x6D\xF0\x98\x10\x58\x49\x1C\xD7\xDE\xDF\xA7\xDD\xE9\xEA\xD8\x72\xE8\xE6\xDF\xEB\x7D\xEA\xE0\xEE\xEB\xB1\xEC\xE1\xE1\xDC\xB7\xE1\xE7\xD8\xEE\x9E\xC2\xEB\xEB\xE7\x71\x8C\x1C\xE6\xED\xBD\xFC\xEF\xEE\xEF\xB3\xF2\xE5\xEC\xF0\xAD\xCA\xF4\xEF\xF3\xCE\xD1\xF4\xF3\xF1\x3A\x8D\x13\xF0\xF3\xB9\xEF\xDB\xEE\xEE\xCD\xD3\xF9\xF2\xF7\xCB\xD4\x8E\x13\xF5\xC8\xE1\xF6\xF3\xF7\xD8\xC5\xFC\xF5\xF6\xA0\xDA\xFD\xF5\xFA\xD4\xE8\x9F\x10\xF9\xE7\xE6\xFB\xF9\x6C\x22\x54\xE9\x41\x14\xA6\xE8\xF5\xF8\xF4\xE0\x60\x80\xFC\x7E\x75\x7E\x01\x89\x24\x0A\xF4\x77\x7D\xFC\x6E\x7C\x7D\xED\x4C\x82\x7D\x0F\x8B\x81\xFB\x13\x8E\x80\x0A\xAF\x79\x21\x55\x09\x81\x04\x84\x8A\x80\x0E\x9B\x86\x7E\x1F\x86\x81\x01\xD2\x73\x80\x10\x96\x85\x81\x17\x83\x85\x00\xA4\x8F\x7E\x16\xAA\x85\x84\x22\x9D\x82\x09\x80\x04\x24\xFD\x6F\x85\x85\x2B\x99\x84\x0C\xAE\x82\x87\x18\xA1\x84", + "\x87\x3F\x9A\x84\x0E\xBB\x85\x27\x2B\x20\x28\x0B\x1A\x87\x84\x04\xCA\x82\x83\x0A\x8E\x89\x85\x3D\x80\x88\x13\x9E\x83\x8B\x19\x99\x09\x89\x4F\x88\x86\xAF\x5A\x08\x8A\x28\x81\x8C\x88\x60\x83\x8A\x18\xB7\x84\x8D\x28\x82\x8D\x8C\x5F\x83\x8E\x19\xE1\x88\x8D\x2A\xBE\x86\x8D\x52\x99\x89\x6C\x5B\x0D\x8A\x2D\x8B\x8A\x8E\x4D\x9E\x88\x1C\xE7\x8B\x8D\x93\x5C\x0D\x8E\x77\x9A\x8C\x1E\xD4\x83\x91\x19\x82\x97\x90\x76\x99\x8D\x22\x84\x98\x3B\x2E\x00\x92\x91\x81\x8B\x92\x21\x92\x9F\x8D\x42\x95\x90\x91\x91\x99\x90\x24\x9B\x9C\x90\x4A\xAE\x66\x24\x36\x9D\x8D\x1B\x96\x91\x8E\x4C\x9C\x93\x92\x9A\x9D\x91\x2A\xA8\x97\x95\x4B\x9E\x94\x8F\x69\x83\x96\x29\xAA\x9D\x95\x52\xBE\x57\x0B\x8F\x94\x95\xBA\x60\x09\x96\x56\xBA\x96\x97\xC0\x8E\x97\x2A\xC2\x95\x96\x58\xBB\x8C\x8D\xA2\x89\x99\x2C\xCA\x97\x98\x35\x8B\x9F\x99\xCD\x92\x97\x2B\xC8\x90\x9A\x52\x86\x9E\x9A\xD4\x90\x4D\x18\x3D\x94\x99\x5F\x9D\x99\x98\xB6\x83\x99\x38\xC5\x99\x9A\x6C\xA7\x62\x0C\x58\x83\x0C\x37\xE3\x9E\x9A\x76\xA0\x9F\x9A\xB3\x8F\x9D\x39\xF1\x90\x60\x94\x21\x95\x4D\x65\x0B", + "\x9C\x3C\xD3\x94\x42\x33\x3A\x9B\x9E\xFC\x92\x9A\x38\xFB\x93\xA0\x80\x85\xA6\x99\xD1\x8C\x9A\x39\x82\xA4\x9C\x84\x8B\xA2\x77\x67\x1F\x9E\x43\xF4\x9E\x9D\x6F\x96\xA5\xA2\x18\xA4\xA1\x43\xE6\x68\x0C\x89\x8C\xA5\x9D\x1A\xA0\xA6\x41\x9B\xAA\xA0\x8A\xA1\xA2\x9E\x13\xA1\xA2\x42\xE9\x0E\xA3\x92\xAA\xA5\x9A\x26\xA3\xA6\x48\xA9\xA7\xA1\x8F\xA8\xA6\xA6\x17\xA7\xA5\x4E\xB2\xA7\xA6\x97\xB5\xA3\x20\x6A\x0D\xA4\x4C\xBE\x5A\x25\x7B\x89\xA3\xA8\x3F\xA8\xA8\x49\xCA\xA3\xA6\x9C\x99\xA4\xA7\x3B\xB4\xA7\x52\xC7\xA4\xAB\x87\x8C\xAD\xA7\x57\xB1\xAA\x53\xBA\xAF\xA8\xA9\x8D\xA8\x4D\x6C\x02\xA9\x55\xB1\xAE\xAA\xAC\xA3\xAF\xA5\x67\xA9\xA9\x5A\xB3\x3D\x0C\x2C\xAE\x0A\xAC\x56\xAB\xAF\x57\xD9\xAD\xAB\xAD\x90\xAD\xAE\xBA\x6F\x0C\x16\xF0\x00\xAE\xB2\xB6\xA9\x21\x71\x1D\xAC\x5A\xF1\xA4\xB0\xBF\xBE\xA3\xAA\x85\xA3\xB2\x61\xF4\xAC\xAB\xC6\xB7\xAE\xB1\x0E\xAC\x26\x51\x89\xBA\xAC\xCA\x8D\x8B\x0E\x82\xB5\xB3\x62\xF2\xA6\xAC\xCB\xB3\xAC\xB3\x5A\xA7\xB3\x67\x9E\xBD\xB3\xCD\xA4\xB1\xB4\x8C\xAF\xB2\x6A\xE5\xA8\xB4\xD0\xB8\xA9\xB5\x0E\xB4\x0D\x66\x88", + "\xB6\xB5\xDA\x8A\xB7\xB6\xB1\x35\x0C\x58\x2E\x23\xB3\x3B\x20\x28\x0F\x60\x39\x0C\x58\x7A\x00\x2D\x3D\x20\x2C\x0F\x60\x3D\x0C\x5C\xFE\x03\xB7\xD1\xB6\xB1\x5C\x7F\x0D\xB9\x69\xB8\xB4\xB6\xEA\x8E\xBE\xBA\xD3\xBA\xB0\x76\xAD\xB7\xB5\xD7\xAE\xB0\xB2\x7F\xA3\x94\x20\x52\xBC\xBB\xE7\x95\xBA\xBB\xE8\xA7\xBE\x7A\x84\x91\x10\xF2\x9E\xBD\xBB\xE0\xA2\xB5\x76\xEB\xB9\x5E\x41\x2E\xB9\xBE\xB0\xA1\xBE\x7C\xE5\xBB\xBB\xF7\xA6\xBF\xBA\xE9\xA0\xC1\x13\x83\x17\xBF\xD5\xBA\xB9\xBF\xFB\xB1\x8C\x21\x05\xCC\xB4\xFF\xBE\x55\x10\x0C\xC7\xC3\x77\x86\xC9\xC0\xB1\x46\x11\xC2\x15\xC5\x9F\x21\x18\xC8\xC1\x0E\xD3\xC5\xC1\xF8\xBF\xC2\x84\xF0\xB4\xC2\x0F\xE4\xC0\xC4\x25\xD4\x80\x22\x1C\xC2\xC5\x0C\xE8\xC4\x42\x89\x00\x2E\x22\x2C\xC7\xC5\x11\xFF\xBB\xBE\x02\xD9\xC4\x8E\xBB\xCC\xBF\x00\xFC\xC6\xC1\x3E\xDD\xC4\x62\x8B\x14\xC7\x1B\xC2\xCA\xC7\x47\xDF\xC5\x88\xB5\xCE\xC4\x1B\xFD\xBB\xC9\x46\xD1\x8C\x23\x45\xCF\xC9\x14\xC0\x05\x11\x54\xC1\xC8\x90\xF4\xB9\xC9\x2E\xDB\xC8\xC9\x5F\xCA\xCA\x95\xD1\xC0\xCB\x06\x8E\x11\xCB\x5C\xC1\xCE\x97\xCB\xCF\x10\x34", + "\xE0\xCD\xCC\x5A\xD0\xCD\x9A\xF2\xCF\xCD\x31\xD5\xCF\xC5\x4E\xD1\xCE\x9D\xFA\xC8\xCE\xDD\x50\x10\x2C\x91\x00\x2E\x24\x60\x23\x12\xB0\x14\x10\x2C\x95\x00\x2E\x25\x60\x27\x12\xB0\x18\x10\xAE\x99\x0E\xCE\x98\xFD\xC2\x20\x4D\x12\xD3\xCD\x7B\xD3\xCD\xA6\xF5\xC4\xD3\x16\xE6\xC4\xCC\x9B\xD3\xD1\x9E\x9A\xDE\xA1\x4D\x17\xD2\xCD\xA8\xD4\xCE\xA8\xCD\xCC\xD4\x13\xDC\x17\xD4\xAA\xD8\xD0\x85\x1D\x10\xD7\x50\xF2\xD3\xD4\x9C\xD8\xD7\xAA\x9F\xD7\xCE\x5D\xF7\xD5\xD5\x9E\xC1\xD8\x93\xBC\xD1\x5C\x4F\x20\x2F\x13\x60\x20\x14\x58\x21\x10\x2C\x51\x20\x2B\x14\x60\x24\x14\x58\x25\x10\x2C\x53\x30\xAF\x14\xB5\xDD\xD3\xB0\x81\x28\x15\x6C\xFE\xD1\xD5\xB6\xC0\xDE\xB6\xA0\xD3\xDD\x5E\xC0\xDB\xDB\xE8\xC4\xDF\xB7\xE2\x69\x14\x6F\xE7\xDA\xDD\xEF\xC6\xDC\xB1\xA4\xD6\x6C\x55\x2E\xDB\xDE\xA3\xAB\x17\xBD\xC2\xD0\xDE\x7C\xFB\xD4\xDF\xF2\xC0\xE0\x9F\xEB\xD1\xDD\x58\xE2\xDC\xE0\xE5\xC3\xE1\xBC\x8A\xEA\x7A\x56\x3B\xD9\xDD\x01\xF0\xE3\x1D\xAD\x10\x2C\x57\x0F\xE5\xDF\x02\xF3\x37\x2B\x17\xE1\xE2\x8C\xD2\xE3\x36\xB0\x1C\xE0\xC3\x99\xEF\x35\x58\x22\xE4\xDE", + "\x0B\xE8\xE6\xBF\xBF\xDB\xE5\x38\xB2\x17\xE4\xB9\xC8\x4F\x2C\x30\xEF\xDF\x8F\xF1\xE5\xE5\x06\xF9\xE5\xC1\xBB\xE9\xE0\x95\xE4\xE0\x3A\xB4\x14\xE4\xCB\xBF\xE3\xE9\x38\x75\x12\xE8\x07\xE9\xE7\xCD\xC4\xE9\xE8\x9C\xFC\xE0\xE1\x50\xEA\xE9\xCD\x9E\xE4\xEB\x8E\xE2\x36\x16\x60\x37\x14\x58\x38\x10\x2D\x5C\x20\x2A\x17\x60\x3B\x14\x58\x3C\x10\x2D\x5E\x20\x2E\x17\x70\xBF\x14\xD2\xBA\xE7\x64\x60\x2B\xEF\xE9\x52\xE5\xE9\xD5\xA3\xE6\xE7\xA9\xD6\xEC\xEE\x73\xFE\xE5\xDD\x80\x61\x19\xB7\xFD\xE3\xE9\x7B\xED\xE8\xD3\xEC\xE6\x20\x61\x3E\xE9\xEA\x4E\xE9\x23\x30\x07\xF1\xEE\xC1\xC1\xF4\xF0\x8D\xF0\xF1\xE2\x88\xF3\xF0\xB8\xD3\xF1\xF2\x96\xF5\xF3\xDF\xB3\x84\x18\xC6\xD7\xF7\xF3\x9A\xE6\x21\x31\x1E\xF1\xF4\xCC\xC9\x26\x18\xA4\xEF\xF1\xE6\xAA\xFB\xF2\xB9\xD1\xE7\x18\xA9\xFE\xE0\x32\x31\xF7\xEE\xBD\xF9\xE8\xF0\xB7\xF6\xEC\xDE\xB5\xF8\xF6\xDE\xF9\x59\x19\xB4\xFB\xF5\x65\xCA\x10\x2D\x65\x20\x2C\x19\x60\x2D\x18\x58\x4E\x10\xAF\x67\x01\xFE\xF6\xBE\xEE\xF6\xF0\xD0\xF3\xFB\xDE\xD5\xFA\xF7\xD4\xE8\xB0\x34\x4F\xF6\xFB\xEC\xDD\xFF\xFB\xD8\xE3\xB5", + "\x34\x5C\xF1\xFD\xF2\xD2\xFE\xFB\xE6\xEF\xBE\x34\x64\xF7\xFC\xF0\xED\xF9\xFD\x92\xF5\xAB\x34\x6C\xFE\xF1\xDC\xEF\xFF\xFE\xF5\xE3\xB0\x35\x74\xF1\xFE\xD6\xD4\xF6\xFF\xA6\x7F\x7F\xD8\x15\x0D\x60\x16\x0D\x60\x17\x0D\x60\x18\x0D\x60\x19\x0D\x70\x5A\x0D\xFC\x7B\x7A\x82\x4B\x0D\x0F\x8D\x7A\xF9\x77\x7D\xF8\x7D\x7F\xF6\x75\x81\xE8\x75\x1D\xDC\x00\x16\xDD\x00\x16\xDE\x00\x16\xDF\x00\x16\xE0\x00\x57\xE1\x03\x81\x02\x8D\x40\xE2\x08\x82\x0A\x53\x0E\x2C\x80\x7A\x00\x80\x83\x19\x88\x81\x11\x74\x0E\x60\x15\x0E\x60\x16\x0E\x60\x17\x0E\x60\x18\x0E\x70\x59\x0E\x2F\x85\x7A\xD5\x4A\x0E\x41\x81\x83\x42\x87\x84\x46\x89\x84\x33\x80\x81\xBE\x2B\x0E\x70\x5C\x0E\x60\x1D\x0E\x60\x1E\x0E\x60\x1F\x0E\x60\x10\x0F\x70\x51\x0F\x45\x8B\x84\x27\x32\x0F\x5B\x8D\x40\xF3\x00\x57\xF4\x00\x16\xF5\x00\x16\xF6\x00\x16\xF7\x00\x16\xF8\x00\x57\xF9\x0F\x85\x16\x81\x47\xFA\x0E\x86\x4D\x41\x0B\x53\x16\x10\x75\x82\x1C\x03\x37\x87\xC4\x19\x87\xE0\x1C\x87\x83\x1E\x87\x78\x8E\x2B\x7A\x8D\x1B\x80\x8B\x87\x82\x8D\x87\x87\x8F\x87\x89\x81\x88\xE1\x27\x38\x03\x14", + "\x16\x93\x59\x15\x09\x1D\x00\xE0\x1C\x15\x09\x1A\x21\x03\x1E\x88\x02\x12\x16\x8A\x87\x13\x9A\x81\x10\x90\x8B\x21\x0A\x12\x89\x06\x14\x89\x83\x16\x89\x06\x18\x89\x02\x1F\x89\x61\x18\x88\x37\x13\x88\xDB\x15\x14\x09\x38\x26\xAC\x81\x8A\x99\x83\x8A\x0A\x16\x8A\xC2\x18\x8A\x03\x1A\x8A\x01\x1C\x8A\x9C\x8C\x88\x33\x10\x8B\xD9\x12\x8B\x31\x25\x8B\x60\x14\x8A\x03\x1A\x8B\xC4\x1C\x8B\x07\x10\x16\xC1\x86\x88\xAF\x8E\x8A\x33\x13\x8B\x6D\x2C\x8A\x35\x1C\x8A\xCA\x82\x10\xCC\x8D\x1B\xCE\x81\x10\xBE\x80\x00\xC0\x84\x8D\x0E\x18\x8D\xC9\x89\x8B\x95\x8A\x10\xE1\x83\x8E\x9D\x83\x8C\xE4\x8D\x10\xD6\x80\x27\xE6\x81\x89\xE8\x87\x8A\xEA\x80\x8D\xEF\x8C\x10\xC4\x85\x14\xC6\x84\x21\xF3\x82\x8A\x09\x1B\x8D\x01\x1D\x8D\xDB\x1F\x8D\x04\x18\x8F\xED\x8E\x10\xFB\x8C\x8F\x37\x11\x8F\x71\x2C\x8A\x06\x9A\x8D\xF5\x8B\x8B\xF7\x83\x59\xD1\x84\x88\x3A\x10\x91\xE7\x83\x89\xE9\x87\x89\x08\x92\x8C\x0A\x99\x8F\xFF\x0E\x90\xD8\x1A\x91\xF4\x8C\x91\xF6\x8E\x91\x16\x92\x92\x0B\x9C\x90\x0E\x14\x92\xA2\x16\x92\x00\x96\x10\x02\x90\x00\x04\x99\x1D\x06\x9B\x8E", + "\x0A\x17\x91\xB1\x8A\x13\x2D\x9E\x92\x0C\x10\x93\xB1\x1C\x8E\x33\x98\x15\x13\x9D\x8C\x15\x95\x94\x9B\x82\x92\x44\x97\x8B\x01\x97\x94\xDE\x89\x94\x4E\x96\x10\x3C\x95\x8C\x3E\x92\x92\x42\x93\x1B\x4D\x9B\x8A\xB8\x88\x92\x14\x9A\x92\x4A\x91\x10\x55\x90\x94\x21\x99\x90\xF0\x87\x8C\x3B\x9B\x91\xA5\x8D\x91\xA9\x8F\x91\xD2\x8E\x8E\x66\x91\x94\x68\x98\x30\x6A\x9B\x8C\x6C\x9D\x8B\x6E\x98\x91\x9E\x8C\x2B\x12\x9E\x95\x48\x90\x96\x53\x93\x10\x63\x94\x96\xFA\x88\x95\x73\x95\x15\x75\x9C\x8D\x77\x9F\x8C\x2B\x91\x97\xFF\x0F\x93\x40\x99\x95\xAF\x1C\x8A\x0E\x9D\x97\x6B\x99\x92\x6D\x9D\x98\x20\x9D\x10\x90\x9E\x92\x92\x90\x1D\xAC\x84\x8C\x96\x96\x97\x98\x98\x97\x9A\x9F\x96\xE5\x8A\x10\xA2\x9D\x95\x97\x9F\x95\x99\x91\x96\xAD\x8E\x98\x9D\x9C\x90\x9F\x95\x1D\xA1\x99\x98\x03\x9B\x98\xE0\x89\x97\x3D\x93\x8D\x8E\x95\x9B\xDC\x17\x9B\x27\x9D\x9A\x7F\x9F\x9A\x81\x9B\x94\xB2\x96\x98\xFE\x80\x16\xA3\x9A\x98\xA5\x9C\x98\xB0\x93\x98\x84\x9C\x8A\xD4\x9C\x9A\xA4\x9E\x9A\xA6\x91\x9D\x2C\x9A\x9C\x3A\x25\x9D\xC3\x97\x9D\xC5\x99\x9D\xC7\x92\x96\xDB", + "\x9F\x9B\x87\x93\x9E\xE2\x86\x9D\xCE\x98\x9D\xD0\x98\x9E\xD2\x94\x96\xB3\x9C\x8F\xC0\x99\x8D\x0A\x1F\x15\xDF\x9B\x9E\xE1\x9D\x9E\x5C\x99\x10\xEF\x90\x94\xAC\x86\x9F\xB0\x95\x93\x37\x95\x14\x39\x9C\x9B\x56\x9E\x9B\x9B\x92\x97\xCB\x99\x10\x00\xA8\x9E\x02\xAA\x9B\x07\x97\x9A\x7A\x90\x97\x09\xA3\x92\xE7\x92\x10\x0D\xAB\x9F\x34\x90\x95\x05\x92\x95\x1A\xA2\x98\xE5\x95\xA1\xF3\x98\x9B\xE9\x9F\x94\x7E\x91\x95\x80\x9F\xA1\xC8\x95\xA1\xCD\x9F\x8B\xEA\x99\x9B\xCF\x9B\x9B\x12\xAD\x9B\x14\xA8\x9A\x67\x9B\xA0\x1B\xA7\x9F\x30\xAC\x9E\x32\xAA\x9D\xC9\x96\x9E\x38\xA6\x94\x3A\xA6\x93\x10\xAA\x93\xFC\x91\xA2\x36\xAA\xA0\x3A\x20\x1C\x0E\x95\x93\xC0\x16\x90\x4D\x1A\x10\x11\x9C\x2B\xFD\x9E\x92\x4E\xA0\xA1\x51\xA9\x10\x53\xA4\x97\x47\xAF\xA3\x22\xA1\x23\x57\xA1\xA3\x59\xAA\xA5\x60\x1E\x90\x55\xAC\x90\xF1\x9D\x8F\x3A\x21\xA6\x3C\xA3\xA6\x06\x1B\xA5\x88\x9D\xA5\x15\xA9\xA6\x3A\x13\xA2\x6E\xA9\x1D\x6C\xA4\x1C\xC4\x85\x93\x0C\x00\xA1\x11\x07\xA7\xB1\x95\xA1\x7C\xAE\xA7\x80\xA7\xA6\xFC\x84\xA7\x0D\x90\xA6\x0A\x1D\xA7\x62\xAF\xA7\x77\xA6", + "\xA8\x45\x18\xA8\xD5\x8A\xA8\x09\x1C\xA8\x6D\xAE\xA8\x6E\xA0\xA9\x57\x90\xA4\x6B\xAC\x39\x06\x94\x8C\x35\x1A\xA9\x37\x15\x93\xAC\x84\xA0\xAA\x95\xA8\x48\xA3\xA1\x2F\x94\xA9\xB0\x96\xAA\x52\x18\xAA\x5E\xA9\xA4\x16\xA4\x21\xA4\xA0\xA1\xA0\xA9\x96\xB1\xAA\xAA\x37\xAB\xA4\xE0\x14\x8C\x92\xA9\x2E\xBF\xA9\x2F\xC1\xA0\x30\xC3\xAE\x32\xC5\xA2\x22\xC7\xA1\x23\xC9\xA4\x21\xCB\xAA\x23\xCD\xA8\x26\xCF\xAD\x26\x35\x96\x8B\x28\xA6\x10\xC9\x17\xA7\x06\x96\xA9\x03\x14\x8C\xA2\xA3\x13\xD3\xA0\xA1\xD7\xAE\xA6\xD9\xA7\xAA\x72\xA2\xAB\xC5\xA6\xA7\x39\xA6\x10\xD4\xAD\xA1\x09\x11\xAE\x63\xA3\xAE\xAF\xA5\xAE\xBA\xA5\x98\x9C\xA8\x26\xDF\xA2\xA6\xEE\xA9\xA5\xF0\xA6\x87\xB8\xA3\xA7\xDC\x98\x26\x4C\xA0\xA8\x45\x1F\x8F\xC4\x14\xB0\xBD\x1D\xA2\x00\x05\x1F\x62\xAE\x21\x8F\xA2\x92\x35\x9A\xB0\x6D\xAC\xB0\x99\xA9\xAA\x34\xAB\xAA\xB4\xAA\x10\x10\xB9\x9F\x01\x12\xB1\x63\xAD\xAD\x65\x9F\xA5\x17\xB9\x10\x19\xB5\xAD\x03\x1C\xB1\x59\xAE\xB1\x9C\x9F\xAF\x6D\x20\x1C\xC2\x95\xA1\x22\x2C\xB2\x02\xBA\x13\x50\xAD\xAB\x31\xB7\x13\x06\x95\x93\xF1\x97\xB3", + "\x60\x16\x90\x0E\x96\xA6\x22\x90\x1C\x79\xAD\x1B\x0E\x91\xAD\x70\x25\x93\x06\x9E\xAA\xEA\xA0\xAB\x2E\xB0\x1E\x2D\xB2\xAB\x2F\xBC\xB4\xE4\xAB\xB4\x14\x20\xB4\x51\xBE\xB4\x31\x24\xB5\x26\xA9\xAE\x1A\xB0\x00\x19\xAE\xA2\x64\xA2\xAF\x01\x1E\xB3\x8E\x90\x1C\xBE\xAF\xB3\xAC\xA3\x10\x14\x00\xA1\x62\x2D\xB0\x63\xB0\xB5\xF1\xA2\xB5\xBC\xA3\x18\x4D\xB3\xAF\x2E\x38\xB5\xFC\xAD\xB6\x53\xB0\x1E\x35\x95\x93\x26\xBC\xAE\x06\x1D\xB5\x25\xAF\xA6\x0A\x10\x11\x5C\xA4\x95\x66\xB3\x18\x65\xB8\xB7\x71\xB2\x1C\x73\xB5\xB1\xC2\xA7\xB8\xCE\xA0\xB9\xD0\xA2\xB9\x6D\x24\xB4\x71\x26\xB9\xD8\x18\xB9\xA2\x1A\xB9\xB1\x1C\xB9\xB3\x1E\xB9\xAF\x15\x93\x98\xAB\xB5\x42\x23\x59\x06\x98\x01\x54\xA4\xB9\xDB\x11\xB4\xDB\x19\xB8\x70\xB3\xB9\x8A\xB0\xB0\xE0\x13\xB4\xAA\xB1\x27\x01\xB9\xB5\x03\x11\x13\x62\xA0\xB8\x35\x16\x90\x15\x05\xB5\x2B\xA6\xB5\x72\xB0\xBC\x8E\xB4\xAC\xB5\xB5\x92\x60\x14\x8C\x06\x90\x24\x6F\xB0\xA2\xB9\xA5\xBC\x2E\x36\xB0\x01\x1A\xBC\x0A\x1C\xBC\x77\xB6\xB8\xCF\xB7\xA0\x2C\x30\xBA\xD0\x1C\xBD\xD5\x1E\xBD\xDC\x10\xBE\x35\x12\xBE\xC4", + "\xBA\xBD\xC0\xA7\xBC\x9B\xB8\xBE\x9D\xBA\xBE\x9F\xBC\xBE\xAF\x14\xBE\xB8\xB6\x1C\x10\xA7\x1F\xCD\xB1\xBC\x74\xB7\xBB\x6E\xA3\xB0\xE5\xB4\x98\xC6\xB1\xBB\x95\xBE\xBE\xDD\xB0\xC0\xDF\xB2\xC0\xE1\xB4\xC0\xE3\xB6\xC0\xFB\xBC\xBF\xC8\xA8\xC0\xF5\xB0\xBD\x0B\xCE\xBF\x45\xBA\x10\xF9\xAE\xB7\xB9\xB5\xBE\x28\xB5\x27\x0E\x90\xB3\x0D\xC6\xBE\xF9\x2A\xC1\xD7\xB2\xBC\x91\xB0\xC1\xB6\xB6\xAB\x0C\xC9\xBF\x32\xB5\xB3\x33\x1A\xB3\x09\x1A\x16\xBB\xBB\xB3\x1C\xA0\x00\x0E\x96\x90\x23\xB1\x10\x35\x97\xC1\xA5\x2E\xBA\x20\xC0\xBB\xAF\xBF\xBF\x22\xC9\xB9\x25\xCB\xAD\x3F\xC2\x10\xF0\xBF\xC1\xF7\xBA\xAC\x41\xC3\xBD\x47\xC0\x00\x43\xC0\xC4\x3D\xC2\x1A\x35\xC0\xA1\xC7\x1B\xC1\x36\xC8\xBF\x63\xAA\xBF\x1B\xCC\xBF\x75\xBE\xB6\x44\xCE\xC0\x57\xBA\xB7\x28\xCE\x10\x7B\xB5\x9F\x10\xA0\xB8\x32\x93\x10\x2C\xC1\xA7\xD8\xBB\xC3\xAD\xB9\xC0\x84\x9F\xC0\x6A\xC7\xB9\x49\xCB\xC4\x42\xC1\xC7\x49\xC6\xC3\x76\xC2\x92\x77\xC9\xBD\x58\xCE\xC6\x39\xCC\xC3\x6F\xCE\xC3\x4D\xCB\xBE\x81\xCD\xBE\x83\xCF\xBE\x74\xC5\xC8\x01\xC8\xC8\x03\xCA\xC8\x05\xCC\xC8\x07\xCE", + "\xC8\x6C\xC4\x96\x7C\xC5\xC4\x14\x26\x90\x33\xB0\xB6\x1C\xC4\xAF\x7F\xC9\xBE\x90\xC7\xC5\x0A\xC6\xC4\x9D\xCB\xC5\x99\xC6\xAC\x87\xCB\xC9\xB1\x15\x93\xF4\xBD\xA6\x69\xB8\xAD\x0A\x1B\xCA\x3E\xAE\xAF\xA1\xCC\xC4\xA6\xC4\xC8\xB3\xC6\xC8\xB1\xC3\xC7\xB7\xC8\xC4\xB9\xCA\xC4\x49\xC8\xCA\x10\xAE\xCA\xEF\xAD\xCA\x06\xA8\xC5\x72\xCA\xCB\xB5\xC9\xC8\xC7\xCB\xC8\xC9\xCD\xC8\xCB\xCF\xC8\xCD\xC1\xC9\x40\x92\x22\xC0\x94\x8C\xC0\x9D\xB3\xB3\xBD\x3F\xBB\xA3\x10\xD5\xC8\xCD\x4A\xAA\xCD\x34\xB5\xB8\x7A\xAC\xCD\x8F\x92\xCE\xD4\xC7\xCD\xE0\xCD\x1B\x35\x90\x9C\xE9\xCF\xCD\x68\xC4\x1C\xB4\xBA\xC7\xFC\xB5\xAC\xF2\xC4\xB1\xA3\xC7\xAE\x31\x28\xAE\xB2\xC2\xAB\xF8\xC2\x10\xC0\x94\x99\x5A\xC3\x10\x96\x60\xA8\x02\xD3\xD0\x04\xD5\xD0\x81\xB9\xCF\xFC\xCF\xA2\x00\x06\xC9\x52\xAD\xD0\x5F\xB2\xB8\x0F\xD3\x10\x0C\xD1\xD1\x18\xAD\xAF\x8F\x89\x16\x0A\x11\xC5\x06\x1A\xD1\x03\x1C\xD1\xF2\xB9\x10\x1E\xD1\x10\x21\xD0\x00\x23\xD5\xD2\x19\xD2\xC1\x28\xDD\xAE\x29\xD6\xAD\x2B\xD3\x10\x13\xC0\x00\x2F\xD1\xD3\x8B\xAF\xC2\x33\xC0\x00\xA9\xC3\x10\x37\xD2\x10", + "\x39\xD1\x10\x3B\xD6\xD3\x0A\x1D\xD3\x40\xDF\xD3\x42\xD9\x10\xBA\xB6\x10\xA3\xBA\x9F\x1B\xBA\x10\x7D\xB0\x00\xC0\xC2\x10\xBF\xB9\x10\xD6\xB3\x10\x47\xD1\x10\x51\xD8\xD4\x00\x05\xD5\x49\xD0\xD5\x4A\xD5\xBD\xC2\xCA\xD5\x09\x1F\xD4\x06\x15\xBA\x06\x18\xBA\x09\x13\xD5\x00\x04\xD6\xC6\x92\x10\x68\xD5\xB2\x0A\x1B\xD6\x02\x1B\xD4\x6E\xD1\x10\x4D\xD1\x10\x71\xD0\x00\x60\xD3\x10\x84\xB6\x10\x6B\xB6\x10\x58\xD0\x00\x66\xDB\xD7\x3F\x2E\xA1\x01\x10\xD8\x02\x1D\xD7\x4B\xD4\xD8\x54\xDB\xD5\x09\x18\xD8\x57\xDD\xD5\x7A\xDC\xD5\x5F\xDA\x10\x8C\xD2\xD6\x03\x14\x26\x5E\xD6\xD4\x0A\x16\xD9\x7C\xD2\xD8\x00\x0A\xD9\x81\xDD\x21\x99\xD0\xD9\x06\x1B\xD4\x9E\xD5\xD8\x8E\xD5\xD9\xA2\xD3\x10\x77\xD2\x10\xA5\xD1\x10\x94\xD2\x10\x1C\x09\xDA\x02\x16\xD6\xB1\xD7\xD9\xE2\x90\xDB\xB2\xD9\xD5\x06\x15\xDB\x9B\xD0\xDA\x09\x1C\xDB\x9F\xD6\x10\x73\xD0\x00\xC0\xD6\xDA\x91\xDF\xDB\x0A\x1F\xDA\x51\xAD\x01\x80\xA3\xDC\xD8\x15\x13\x95\x00\x8B\xFE\xC9\x10\x29\x0D\xC5\x09\x16\x09\xD2\xDC\x2B\xD5\xD9\xB7\x09\x17\x09\xD9\xD4\xD1\x01\x11\x34\xDC\xD6\x10\x98", + "\x0F\xDD\x10\xD6\x10\xE2\xDB\xB8\x03\x19\x09\xE6\xD3\xA6\x3C\x06\xDD\x06\x1A\x09\xED\xD6\xBF\x01\x1D\x38\xE3\xD3\x10\x9B\x03\xDF\xE4\x99\x10\xF6\xDA\xDE\x02\x1C\x09\xFA\xD0\x00\xEB\xA0\x00\x98\x34\x21\xFB\xC0\x8A\x0A\x13\x3A\x06\xE0\xDF\x03\x13\x3E\xF7\xD2\x10\x9D\x01\xE0\x35\x18\x40\x0F\xE1\x10\x9E\x01\xE0\x23\xDC\x45\x15\xE0\x00\x9F\x01\xE0\x2F\xD4\x47\x1B\xE0\x0A\x1E\xEA\x10\x20\xEE\xDF\x01\x11\x0A\x12\xEA\x10\xE8\x4B\xE1\xA2\x01\xE0\x37\x9D\x51\x1B\xE3\x0A\x01\xE5\x93\x6D\x5B\xE0\x09\x14\x0A\x01\xE0\xB8\x81\x56\xE3\x06\x15\x0A\x01\xE7\xC6\x03\x1C\x57\x3C\xE3\x10\xA6\x01\xE0\xDA\xA2\x10\x7A\x53\xE4\x02\x17\x0A\x01\xE5\xD3\x6F\x5A\xE4\xDC\x61\xE0\x3D\xDA\x5B\x50\xE0\x00\xA9\x01\xE0\xC4\x82\x5B\x1B\xEA\x0A\xB0\x84\x8C\x53\xE7\xCF\xA0\xC6\x10\x5A\xE6\xE2\x00\x0C\x0A\x01\xE5\xD4\x03\x10\x5C\x1B\xED\x0A\x5D\xEA\x10\x68\xE2\x10\xC2\x5B\xE1\xAF\x07\xE6\x0A\x11\xE7\x64\xE0\x0B\x01\xEB\x0F\x80\xA7\xE0\x23\xCE\xC9\xB1\x15\x13\x03\xE5\x88\xB8\xC4\xE6\x86\xA2\x22\x38\xBC\xE0\x15\xD7\x32\x80\xB1\x9F\x02\xD3\xD2\x03\x33", + "\xE0\x8C\xE0\xA8\x35\x93\x30\x23\xD1\xE9\x77\xA0\xE4\xDA\x37\xE4\xC6\xC2\xBB\xE0\xDE\x44\x35\xD6\xE9\x6E\xA0\xEA\x68\x2F\xE6\x9B\xEB\xB2\x6D\xD0\x3C\xE1\x82\xEA\x83\xE8\x9E\x03\x33\xDC\x93\xEC\xC9\x06\x1B\xDA\x14\x45\xD7\x80\xB0\xC8\xBD\xD6\x36\x83\x2C\xA0\x61\xE3\x10\xCA\xDE\x44\x24\x02\xC6\x55\xE5\xAA\xBE\x23\x2D\xF1\xB0\x27\x0E\x92\xEB\x4E\x4B\x2F\xBA\xE5\xE5\x7D\xD3\x30\xE9\xD3\x10\xB5\xE2\x1A\x0E\x9D\xEB\x03\x3B\x35\xCB\xED\xA9\x93\x53\x30\x8B\x35\xEC\x71\x25\x93\xC8\xE3\x30\x93\x3F\xB7\x67\xB6\xDC\x66\x30\x12\xD7\xE6\xAF\xC9\xD0\x3C\xF9\x32\xEE\x95\xC0\x57\x35\x4A\xB5\x6D\x2E\xBB\xC0\x3A\xE1\xEC\xEA\x23\xCB\xB0\x3C\xBC\x47\xEE\xF1\xE9\xEE\x27\x3E\x4F\xFA\xE0\x27\x64\xC0\x3C\x61\x5C\xED\xD8\x10\xB8\xDF\xEE\x2B\x42\xE5\xEF\x68\x20\xB8\xCD\xEE\x2B\xBC\x5A\xF0\x6D\x20\xB8\xD4\xEE\x2B\xC8\x5F\xEF\x71\x25\x95\xC2\xE1\x2E\xF6\x54\xF0\xA2\x15\x95\x07\xF1\x2E\x17\x66\xF1\xD8\x15\x95\x0D\xF1\x2E\x53\x62\xF2\x1D\xFC\xEF\x66\x33\x68\x28\xF1\x1B\x03\xE9\xF1\x2C\x3F\x68\x1C\xFE\xF2\x0A\x1F\xF1\x2C\x3F\x6A\x2D\xF3\x1B", + "\x03\xE5\xF2\x2C\x3E\x6C\x39\xFF\x1A\x03\xE3\xF1\xE1\x2D\x6D\x3F\xF0\x1D\x98\xEE\xB5\x66\x36\x71\x33\xF3\x1B\x47\xF6\xD7\xC0\x3F\x72\x45\xF5\x1D\x4D\xFC\xF3\xE9\x2C\x75\x51\xFC\x1D\x4D\xF2\xF4\x2C\x38\x76\x57\xF5\x13\x23\xD0\xF3\xE9\x2D\x79\x4B\xFF\x1A\x23\xD6\xF3\xE9\x23\x7B\x5D\xF7\xD2\xB6\xDA\x3D\xCC\x79\xF6\x20\xDA\xF2\xBA\x3B\x7F\x6E\xFC\xD2\x27\xA4\x41\x0E\x89\xED\xA2\x1A\xE9\x07\xDA\x3D\x12\x83\xF6\xD0\x1A\xF7\x66\xF9\x2F\x23\x83\xF7\x03\x1A\xF7\x54\xF9\x2F\x38\x84\xF8\x02\x1A\xF7\x5A\xF9\x2E\x4E\x8A\xF8\x3B\xA5\xF8\xC0\x3A\x85\x78\xF1\x1B\x35\xDF\xD2\x03\x3E\x85\x95\xF3\x1B\x3D\xD0\xF6\xF9\x21\x86\xE7\xC0\x27\x3D\xD1\xF8\x00\x37\x86\x9D\xE8\x1D\x3D\xD7\xF8\x00\x3A\xE7\xA7\xF2\x1A\x3D\xDD\xF8\x1D\xCF\x89\x47\xB2\x1A\xA4\xEB\xF7\x14\x45\x00\x9F\x8C\xE7\xB5\xF4\xFA\x2E\x38\x00\xB2\xF1\x23\xB5\xFA\xFA\x2E\x3D\x00\xBF\xF4\x21\xB5\xF0\xFB\x00\x32\x01\xC5\xFA\x23\x66\xD5\xFB\x03\x37\x01\x9F\x8E\xF9\xD5\x11\x8E\x7C\xE8\x1D\x18\x0F\x89\xB7\xA3\x59\xE1\x81\xE8\xBE\x2A\x01\xD8\xFC\x9C\x9C\xD5\xE8\x31\x2C\x01\xDF", + "\xFB\xC1\xAC\x81\x8E\xD1\xE1\x2E\x1E\x05\xFE\xED\xCA\xA2\x3D\xAD\xD1\xC0\x30\x02\xEC\xF2\xA4\xB0\x91\x8E\xAF\xE1\x2E\x22\x03\xFF\x5B\x10\x16\xE1\x8D\xF4\x03\x34\x02\xFA\x7E\x2B\x3C\x7E\x87\x66\x36\x26\x01\x00\x81\x54\xE8\x49\xD5\x40\x1E\x14\x07\x00\xAF\x78\x67\x75\x6B\x03\x1A\x05\x07\x81\xA6\x7C\x8A\x4B\x6A\xF4\x6E\x19\x2C\x07\x13\x77\x7F\xD9\x0B\xD4\x3C\x7E\x88\x10\x01\x9F\x41\xFD\x5C\x81\xDC\x6E\x44\x36\x01\x08\x91\x11\x4B\x68\xF9\x6E\x18\x1E\x07\x02\x94\x13\x70\x6B\x6A\x03\x1A\x08\x11\x7F\x18\x18\xEC\x3D\x6B\xC0\x03\x02\x33\x84\x42\x3D\x6A\xB3\x60\xEE\x39\x82\x8E\x1D\x75\xE1\x43\x60\x05\x02\x1F\x88\x26\x75\x6B\x05\x82\x11\x46\x01\xF7\x71\x11\xBA\x6E\x01\xB1\x11\x12\x0B\x7E\x45\x84\x04\x83\x18\x27\x00\x05\xED\x11\x5D\x6A\x81\x22\x13\x0A\x15\x82\x38\x15\xD7\x35\x6B\xC0\x18\x02\x44\x85\x4D\x39\x6A\xD4\x67\x32\x59\x03\x01\x98\x0E\xAD\x6C\xB8\x40\x1F\x2D\x01\x06\xF0\x11\x71\x61\x08\xB9\x76\x6C\x1C\x03\x36\x81\x27\x6F\x80\x00\x00\x01\xC0\x1D\x0B\x34\x82\xEC\x0C\xDC\x09\x09\x1C\x9A\x1D\x5E\x03\x0F\xA2\x0D\x3F\x82", + "\x10\x0C\x6F\xC0\x1F\x02\x1A\x81\x46\x05\x15\x84\x0D\x07\xE6\x1B\x18\x02\x84\xB1\x08\x0F\x89\x09\x45\x86\x36\x64\x00\x24\x93\x0D\x12\x0E\x20\x3F\x75\x93\x15\x06\x67\x82\x68\x00\x15\x09\x0E\x53\x27\x19\x33\x0A\x04\x94\x13\x26\x86\x08\xA0\x86\x6C\x2A\x03\x4B\x8F\x1A\x14\x09\x42\x1B\x15\x27\x1B\x0D\x1E\x85\xD8\x00\x0B\x86\x09\xB5\x07\x19\x6D\x04\x15\x90\x0E\x14\x0A\x10\x27\x86\xEE\x0E\x03\x07\x87\xEB\x4A\x08\x5E\x89\x10\x44\x76\xD9\x10\x03\xBA\x85\x3A\x1B\x6E\x4D\x80\x3C\x71\x03\x01\x8F\x69\xAC\x43\x19\x83\x08\x63\x8A\x3B\x73\x01\x32\x9C\x0E\xD4\x82\x20\x39\x15\x93\x14\x07\x09\x84\x85\x17\x85\x06\x0C\x18\xA6\x1A\x3C\x07\x0D\xB5\x0A\x45\x09\x08\x05\x1F\x64\x39\x03\x59\x83\x1B\x4A\x76\x41\x0D\x01\xC0\x1B\x0F\x25\x84\x1D\x19\x0E\x86\x0A\x3B\x9A\x1D\x7E\x05\x1C\x97\x08\x85\x02\x03\x40\x1F\x1F\x0C\x87\xAF\x0D\x1F\x89\x08\xA3\x17\x32\x01\x06\x3E\x89\x08\x2A\x18\x1D\x80\x1E\x41\x07\x00\xFA\x78\x2B\x49\x88\x06\x0C\x68\x27\x18\x42\x07\x10\xE8\x6E\x42\x15\x87\xBA\x1D\x10\x07\x81\x9B\x4C\x8A\x4F\x76\x40\x12\x88\x66\x1F\x10", + "\x15\x89\x81\x00\x12\x83\x09\x0C\x00\x1E\x88\x06\x1B\xBA\x10\x82\x86\x10\x10\x8A\xEE\x0C\x04\x23\x8A\x20\x1A\x09\x84\x09\x35\x27\x19\x23\x00\x88\xD0\x0D\x26\x86\x08\xBD\x17\x32\x0F\x05\x4C\x81\x08\xD6\x75\xFD\x54\x20\x48\x07\x00\xB5\x68\x2B\x41\x8A\x17\x6F\x64\x12\x05\x03\x8D\xF9\x0A\x08\x52\x94\x6F\x4E\x24\x12\x07\x81\xDA\x77\x14\xC0\x76\xD9\x16\x04\x07\x86\xAC\x55\x8B\xB7\x77\x32\x18\x07\x01\x86\x52\x06\x0F\x29\xB4\x60\xE0\x1A\x09\x07\x82\x05\x8E\x8A\x18\x6F\x64\x1C\x05\x03\x83\xDC\x5B\x8B\x79\x7A\x1D\x9E\x07\x00\x88\x76\xB7\x88\xD0\x14\x20\x28\x07\x80\x7D\x6C\x2E\xAA\x6A\xE0\x12\x0A\x07\x81\xAF\x6C\x45\x3B\x02\x21\x38\x00\xE0\x14\x0A\x2A\x88\x9A\x0F\x6F\x09\x09\x30\xA7\x18\x54\x0F\x13\x80\x00\x4F\x81\x8B\xC0\x19\x15\x0D\x8D\xC2\x16\x10\x11\x1F\xC9\x0A\x05\x38\x8D\x3A\x1B\x76\x83\x0A\x13\xBA\x1C\x2B\x07\x80\x46\x82\x21\x1B\x8D\x81\x0F\x38\x27\x1A\x2B\x0D\x8C\xFD\x6B\x20\x1D\x8C\xED\x1F\x0A\x07\x83\x18\x8E\x7F\x00\x01\x35\x82\x09\xD2\x86\x36\x31\x05\x63\x94\x8D\x03\x09\x71\x27\x18\x59\x06\x18\xED\x12\x65\x86", + "\x08\xA3\x8A\x7B\x36\x05\xC6\x81\xEE\x03\x09\xE9\x07\x19\xB7\x01\x33\x9C\x0F\xE2\x82\x10\x1B\x1F\xC9\x19\x05\xCA\x8D\x26\x05\x70\x83\x06\x39\x27\x1B\x2E\x13\x87\x68\x16\x39\x95\x8C\xE0\x1E\x0B\x07\x80\x63\x6C\x45\x0A\x74\x3A\x80\x1E\x60\x08\x1D\xED\x13\x71\x9B\x8E\x27\x1B\x18\x07\x81\x34\x8C\x8A\x66\x76\x41\x13\x1F\x27\x1D\x18\x11\x8E\x85\x02\x3C\x21\x7E\x13\x27\x06\x07\x86\x0E\xAC\x45\xFA\x89\xB4\x27\x19\x32\x07\x80\x8D\x80\x3D\x7C\x8E\xE7\x56\x36\x4B\x07\x01\x84\x84\x48\x7B\x20\x03\x91\x44\x76\x36\x4D\x07\x01\x94\x84\x02\x92\xED\x66\x1B\x67\x07\x00\x92\x84\x6C\x4B\x90\x63\x8F\x64\x11\x07\x03\x89\x09\x91\x93\x0A\x60\x1E\xD3\x07\x00\xA2\x85\x0B\x94\x00\xBA\x1D\x35\x07\x80\xA9\x86\x43\xA2\x65\x81\x17\x0D\x07\x82\x2F\x90\x8D\x18\x97\xAC\x40\x1F\x6C\x07\x00\xAE\x84\x6C\x56\x1E\x09\x0B\x09\x00\x1F\x6D\x05\x1E\xF0\x12\x83\x66\x08\x38\x96\x6C\x1E\x07\xC6\x80\x1F\x86\x09\x8C\x83\x18\xDF\x05\x31\xAB\x77\x81\x09\x41\x27\x18\x38\x13\x8F\x09\x0A\x0A\x22\x66\x11\x12\x0E\x07\x83\x36\x90\x4D\x52\x91\x21\x1C\x7F\x70\x14\x0E", + "\x07\x81\x2D\x88\x4F\x59\x91\x8D\x7A\x1C\x73\x07\x00\xE2\x84\x98\x96\x8A\xBA\x18\x1D\x07\x80\x69\x80\x1B\xE1\x90\xFC\x67\x19\xEA\x07\x00\x99\x87\x04\x92\x10\x6E\x92\x40\x1B\x80\xE9\x14\x1D\x07\x80\x70\x87\x26\x9F\x93\xC9\x0E\x07\x07\x87\x1C\x98\x93\x12\x9A\x3D\x70\x07\x01\x90\x87\x93\x2E\x4E\xA5\x74\x0A\x22\x0F\x07\x83\x3D\x8D\x93\xA7\x77\x64\x34\x07\x03\x88\x11\xB0\x8F\x14\x0A\x08\xFC\x1F\x64\x36\x07\x1E\x91\x27\x14\x72\x41\x17\x94\x27\x19\x1F\x0D\x8D\x26\x96\x10\x0A\x96\x13\x3A\x07\x8D\x8F\xDD\x43\x08\x24\x27\x32\x7B\x04\x94\x86\x08\xAC\x96\x20\x0E\x25\x93\x1D\x0F\x0D\x8F\x15\x29\x08\x45\x92\x77\x3E\x07\x03\x87\x30\x30\x4F\xAD\x86\x08\xA4\x92\x77\x3C\x64\x51\x67\x12\x93\x2F\xAF\x83\x08\x7F\x27\x64\x02\x01\x00\x78\x1D\x74\x74\x93\x80\x1E\x03\x05\xCD\x49\x08\x81\x80\x9B\x4E\x96\x40\x09\x96\x66\x1D\x00\x0C\x96\xD1\x05\xE2\x48\x94\xF0\x06\x00\xDB\x91\x36\x18\x97\x81\x06\x44\x27\x1B\x01\x10\x45\xB3\x79\x36\x33\x94\x83\x07\x2C\x99\x75\xB8\x93\x0D\xA0\x26\x20\x2A\x27\x93\x1D\x00\x52\x96\x8E\x19\x77\x42\x8E\x89\x0F", + "\x00\x7B\x93\x10\x2E\x88\x6C\x98\x97\x49\x8E\x6C\x11\x00\x7E\x92\x10\x1E\x88\x9D\x81\x08\x00\x98\x2A\x83\x19\x09\x04\x30\x81\x09\x49\x9F\x97\x68\x92\x7B\x15\x01\x86\x90\x00\x2C\x88\x7A\x49\x98\x22\x68\x78\x17\x00\x8A\x93\x13\xB0\x4C\xC6\x80\x00\x78\x91\x5F\x19\x00\x8A\x93\x18\x93\x2F\xC7\x9E\x7F\xBE\x13\x03\x14\x99\xD5\x87\x30\x80\x03\xC7\x89\x97\x2C\x1D\x03\x14\x98\xB1\x86\xFB\x2E\x98\x34\x79\x17\x1F\x04\x62\x8A\x8C\x8F\x91\x29\xE6\x19\x08\x14\x98\x88\x88\x36\x5B\x27\x84\x08\x4B\x27\x1B\x08\x10\x45\x7C\x73\xC5\x46\x09\xA1\x95\x00\xEF\x97\x6B\x13\x97\x06\x0F\x63\x83\x19\x13\x0E\x34\xD0\x0E\x3D\x26\x08\xFE\x76\x6C\x28\x00\x8A\x98\x1D\x59\x98\x50\x20\x1E\x2A\x05\x6A\x95\x0F\x88\x29\x10\x50\x9A\xEE\x0B\x01\x14\x9F\x31\xA8\x4E\xB2\x96\x10\x2C\x2B\xC9\x0D\x01\x62\x9C\x3B\x30\x71\xB6\x90\x3C\x2E\x01\xDC\x95\x09\x6E\x9E\x20\x39\x27\x93\x1F\x02\x30\x45\xC8\x95\x0E\x41\x29\x21\x2C\x9A\xDD\x13\x03\x77\x99\x4A\x0A\x08\x5F\x92\x7B\x34\x00\x8A\x94\x19\xE8\x4D\x51\x26\x08\xD4\x92\x77\x36\x00\x8A\x9A\x1B\xB0\x4F\xE3\x86\x8E", + "\xC0\x18\x07\x14\x99\xE0\x8D\x32\x97\x9D\x73\x80\x1E\x3A\x04\x62\xB2\x8D\xCE\x9A\x10\x31\x96\xEE\x1C\x01\x14\x98\x37\xB0\x8C\xCF\x91\x10\x5E\x9A\xF6\x1E\x01\x14\x9F\x37\xA8\x4F\x1A\x76\x10\x03\x7A\xD9\x00\x02\x86\x99\x21\x0F\x73\xDA\x90\x3C\x41\x01\xEE\x86\x08\x49\x74\x77\xA7\x18\x21\x0F\x3B\xC1\x72\x42\x16\x9D\xBA\x1B\x08\x05\x9E\x81\x0B\xE3\x42\x9E\xD9\x04\x02\xCB\x99\x20\x12\x2C\x83\x09\x38\x94\x21\x11\x14\x98\xCC\x8B\x51\x80\x01\xE9\x93\x10\x11\x9E\xF6\x07\x02\x14\x9B\x3A\xB5\x8B\xED\x9A\x10\x67\x8E\xEE\x09\x02\x14\x99\x3C\xA3\x9E\xEE\x9F\x39\xA7\x1B\x12\x14\x98\xEE\x8B\x7D\xA5\x9C\xE0\x1D\x04\x14\x99\x8C\x84\x46\xEC\x9D\x75\x80\x1F\x27\x04\x31\xBF\x92\xFC\x89\x08\x69\x83\x60\x11\x02\x8A\x9B\x24\xB0\x8F\x98\x63\x08\xD5\x9E\x89\x13\x02\x8A\x99\x29\xA2\x67\x01\xA2\x08\xDE\x9C\x82\x15\x02\x8A\x90\x2A\x8E\xA1\xF9\x80\x1E\x57\x04\x62\x81\x97\x55\x72\x10\x0F\xA1\x40\x1A\x8E\xBA\x19\x0B\x14\x99\x72\x96\x41\x89\x0A\xE9\x9A\x1E\x5B\x04\x62\xAD\x96\xED\x9E\x41\x80\x02\xEB\x94\x20\x5D\x04\x62\x9D\x96\x0E\xA1\x10\x2D", + "\xA1\x00\xB7\x25\x14\x9B\x5D\xA8\x4E\x2A\x76\x10\x18\x2F\xC9\x01\x03\x5C\x9A\x34\x0F\x78\x04\xA0\x3C\x63\x00\xC5\x91\x97\xDE\x61\x21\x03\xA2\x08\xA0\x3C\x65\x00\xC5\x8C\x9A\x49\xA6\x20\x0B\xA3\x80\x06\x3E\xDA\x1F\x19\x14\x98\x57\x99\x8A\x83\x09\x29\xA0\x00\x20\xA2\xF6\x09\x03\x14\x9B\x70\x89\x68\x25\xA3\x3F\xB1\x84\xC5\x81\x9C\xF9\x94\x8B\xAF\xA0\x27\x2D\x06\x14\x98\xED\x9A\xA2\x02\x0C\x8B\xB7\xA1\x70\x1F\x06\x14\x99\xC2\x63\x9F\x6A\x76\x20\x3E\x2D\x93\x11\x07\x7E\x99\x8C\x19\xA3\x44\xA7\x64\x35\x02\x8A\x99\x3F\xB0\x62\x42\x00\xA4\x4C\xA7\x64\x37\x02\x8A\x9C\x43\xF0\xA1\x40\x08\xA4\x54\xA0\x78\x39\x02\x8A\x90\x49\x86\xA5\x42\x15\xA4\x5E\xA4\x82\x3B\x02\x8A\x96\x5C\x76\x8D\x25\xA7\xA1\x14\x25\x0F\x14\x98\xE6\x2E\x49\x8A\x0B\x1A\xA3\x18\x7F\x04\x62\xAD\x2F\x52\xA0\x40\xC0\x1D\x20\x14\x98\x0B\x33\x83\x76\x73\x81\x0B\x47\xE6\x1B\x20\x1E\xA3\x14\x13\x96\x82\x09\x04\xA3\x30\x07\x04\xC5\x81\x79\xF9\x92\x97\x81\x09\x08\xAE\x44\x09\x04\xC5\x91\x31\xF6\x8A\x98\x80\x01\x2A\xA4\x41\x0B\x04\xC5\x87\x79\xC1\xA2\x21\x19\xA4", + "\x27\x2D\x08\x14\x99\x9B\x29\xA6\x65\xA6\x6C\x0F\x04\x8A\x9C\xF2\x51\xA5\x42\x07\xA5\xBE\x11\x12\x14\x99\x44\x38\x4D\xAD\xA7\xC9\x13\x04\x14\x9A\xE6\x62\x64\xE2\x26\xD0\x0B\x09\x3B\xAF\xA7\xF0\xA1\x9E\xB2\xA7\x79\xA4\x4F\xF5\xA5\x96\x40\x55\xFB\x40\x9F\x8E\x66\x51\x63\x2C\x9B\x62\x25\xB6\x8F\xB3\x56\x3E\xA0\x99\x9A\x03\xE9\x4E\x52\x41\xA4\xA8\x08\xAC\x50\xBB\x7E\x99\x00\xA5\x50\x50\xEF\x55\x75\x0F\xAD\x26\x11\xA9\x88\x90\x15\x88\x83\x42\x15\x4A\x16\xAD\xA2\x98\xA8\x8C\xA3\xE0\x02\x70\x51\x1D\xA8\x20\xA8\xD0\x75\x09\xA6\x70\x00\x7E\x7C\x49\xA7\xA9\x23\xAE\xEB\x6A\xA8\x99\x03\xD2\x24\x6B\x4A\xBC\x8A\x2A\x6D\xA5\x4B\x09\x97\x60\xD3\x35\x08\x4D\xB4\xA9\x7A\x78\x00\x3A\x7B\x7F\x09\x53\xBD\xA9\x4D\x1E\xA9\x33\x6F\x85\x44\x52\x99\x07\x93\x43\xA9\xDD\x71\x7C\x03\x0D\xA6\x49\x58\xA2\x0A\x54\xCD\xA9\x4D\x0E\xAA\x43\x69\x21\x36\x81\x9E\x6E\xD3\x51\xAA\x41\x14\xAA\x54\xAD\xF6\x40\x00\xE7\x7A\x55\xDA\xAA\x59\x7E\x6B\x44\x0F\xAB\x9F\xAB\x9A\x00", }; vl::glr::DecompressSerializedData(compressed, true, dataSolidRows, dataRows, dataBlock, dataRemain, outputStream); } @@ -12415,117 +12412,113 @@ namespace vl::presentation::remoteprotocol L"[12][RType]< NAME \"[\" \".\" NAME \"]\" @ >", L"[13][RType]< NAME \"[\" \".\" NAME @ \"]\" >", L"[14][RType]< NAME \"[\" @ \".\" NAME \"]\" >", - L"[15][RType]< NAME @ \"[\" \".\" NAME \"]\" >", - L"[16][RType]< NAME @ >", - L"[17][RType]< RType \"?\" @ >", - L"[18][RType]< RType \"[\" \"]\" @ >", - L"[19][RType]< RType \"[\" @ \"]\" >", - L"[20][RType]< RType \"[\" @ RType \"]\" >", - L"[21][RType]< RType \"[\" RType \"]\" @ >", - L"[22][RType]< RType \"[\" RType @ \"]\" >", - L"[23][RType]< RType @ \"?\" >", - L"[24][RType]< RType @ \"[\" \"]\" >", - L"[25][RType]< RType @ \"[\" RType \"]\" >", - L"[26][RAttributeParameter] BEGIN ", - L"[27][RAttributeParameter] END [ENDING]", - L"[28][RAttributeParameter]CPP_NAME @", - L"[29][RAttribute] BEGIN ", - L"[30][RAttribute] END [ENDING]", - L"[31][RAttribute]< \"[\" @ ATT_NAME [ \"(\" RAttributeParameter \")\" ] \"]\" >", - L"[32][RAttribute]< \"[\" ATT_NAME @ [ \"(\" RAttributeParameter \")\" ] \"]\" >", - L"[33][RAttribute]< \"[\" ATT_NAME [ \"(\" @ RAttributeParameter \")\" ] \"]\" >", - L"[34][RAttribute]< \"[\" ATT_NAME [ \"(\" RAttributeParameter \")\" @ ] \"]\" >", - L"[35][RAttribute]< \"[\" ATT_NAME [ \"(\" RAttributeParameter \")\" ] \"]\" @ >", - L"[36][RAttribute]< \"[\" ATT_NAME [ \"(\" RAttributeParameter @ \")\" ] \"]\" >", - L"[37][REnumMember] BEGIN ", - L"[38][REnumMember] END [ENDING]", - L"[39][REnumMember]< NAME \",\" @ >", - L"[40][REnumMember]< NAME @ \",\" >", - L"[41][REnum] BEGIN ", - L"[42][REnum] END [ENDING]", - L"[43][REnum]< \"enum\" @ NAME \"{\" { REnumMember } \"}\" >", - L"[44][REnum]< \"enum\" NAME \"{\" @ { REnumMember } \"}\" >", - L"[45][REnum]< \"enum\" NAME \"{\" { REnumMember @ } \"}\" >", - L"[46][REnum]< \"enum\" NAME \"{\" { REnumMember } \"}\" @ >", - L"[47][REnum]< \"enum\" NAME @ \"{\" { REnumMember } \"}\" >", - L"[48][RUnionMember] BEGIN ", - L"[49][RUnionMember] END [ENDING]", - L"[50][RUnionMember]< NAME \",\" @ >", - L"[51][RUnionMember]< NAME @ \",\" >", - L"[52][RUnion] BEGIN ", - L"[53][RUnion] END [ENDING]", - L"[54][RUnion]< \"union\" @ NAME \"{\" { RUnionMember } \"}\" >", - L"[55][RUnion]< \"union\" NAME \"{\" @ { RUnionMember } \"}\" >", - L"[56][RUnion]< \"union\" NAME \"{\" { RUnionMember @ } \"}\" >", - L"[57][RUnion]< \"union\" NAME \"{\" { RUnionMember } \"}\" @ >", - L"[58][RUnion]< \"union\" NAME @ \"{\" { RUnionMember } \"}\" >", - L"[59][RStructMember] BEGIN ", - L"[60][RStructMember] END [ENDING]", - L"[61][RStructMember]< \"var\" @ NAME \":\" RType \";\" >", - L"[62][RStructMember]< \"var\" NAME \":\" @ RType \";\" >", - L"[63][RStructMember]< \"var\" NAME \":\" RType \";\" @ >", - L"[64][RStructMember]< \"var\" NAME \":\" RType @ \";\" >", - L"[65][RStructMember]< \"var\" NAME @ \":\" RType \";\" >", - L"[66][RStructBody] BEGIN ", - L"[67][RStructBody] END [ENDING]", - L"[68][RStructBody]< NAME \"{\" @ { RStructMember } \"}\" >", - L"[69][RStructBody]< NAME \"{\" { RStructMember @ } \"}\" >", - L"[70][RStructBody]< NAME \"{\" { RStructMember } \"}\" @ >", - L"[71][RStructBody]< NAME @ \"{\" { RStructMember } \"}\" >", - L"[72][RStruct] BEGIN ", - L"[73][RStruct] END [ENDING]", - L"[74][RStruct]<< \"class\" !RStructBody @ >>", - L"[75][RStruct]<< \"class\" @ !RStructBody >>", - L"[76][RStruct]<< \"struct\" !RStructBody @ >>", - L"[77][RStruct]<< \"struct\" @ !RStructBody >>", - L"[78][RMessageRequest] BEGIN ", - L"[79][RMessageRequest] END [ENDING]", - L"[80][RMessageRequest]< \"request\" \":\" @ RType \";\" >", - L"[81][RMessageRequest]< \"request\" \":\" RType \";\" @ >", - L"[82][RMessageRequest]< \"request\" \":\" RType @ \";\" >", - L"[83][RMessageRequest]< \"request\" @ \":\" RType \";\" >", - L"[84][RMessageResponse] BEGIN ", - L"[85][RMessageResponse] END [ENDING]", - L"[86][RMessageResponse]< \"response\" \":\" @ RType \";\" >", - L"[87][RMessageResponse]< \"response\" \":\" RType \";\" @ >", - L"[88][RMessageResponse]< \"response\" \":\" RType @ \";\" >", - L"[89][RMessageResponse]< \"response\" @ \":\" RType \";\" >", - L"[90][RMessage] BEGIN ", - L"[91][RMessage] END [ENDING]", - L"[92][RMessage]< \"message\" @ NAME \"{\" [ RMessageRequest ] [ RMessageResponse ] \"}\" >", - L"[93][RMessage]< \"message\" NAME \"{\" @ [ RMessageRequest ] [ RMessageResponse ] \"}\" >", - L"[94][RMessage]< \"message\" NAME \"{\" [ RMessageRequest @ ] [ RMessageResponse ] \"}\" >", - L"[95][RMessage]< \"message\" NAME \"{\" [ RMessageRequest ] [ RMessageResponse @ ] \"}\" >", - L"[96][RMessage]< \"message\" NAME \"{\" [ RMessageRequest ] [ RMessageResponse ] \"}\" @ >", - L"[97][RMessage]< \"message\" NAME @ \"{\" [ RMessageRequest ] [ RMessageResponse ] \"}\" >", - L"[98][REventRequest] BEGIN ", - L"[99][REventRequest] END [ENDING]", - L"[100][REventRequest]< \"request\" \":\" @ RType \";\" >", - L"[101][REventRequest]< \"request\" \":\" RType \";\" @ >", - L"[102][REventRequest]< \"request\" \":\" RType @ \";\" >", - L"[103][REventRequest]< \"request\" @ \":\" RType \";\" >", - L"[104][REvent] BEGIN ", - L"[105][REvent] END [ENDING]", - L"[106][REvent]< \"event\" @ NAME \"{\" [ REventRequest ] \"}\" >", - L"[107][REvent]< \"event\" NAME \"{\" @ [ REventRequest ] \"}\" >", - L"[108][REvent]< \"event\" NAME \"{\" [ REventRequest @ ] \"}\" >", - L"[109][REvent]< \"event\" NAME \"{\" [ REventRequest ] \"}\" @ >", - L"[110][REvent]< \"event\" NAME @ \"{\" [ REventRequest ] \"}\" >", - L"[111][RDeclDetail] BEGIN ", - L"[112][RDeclDetail] END [ENDING]", - L"[113][RDeclDetail]<< !REnum @ >>", - L"[114][RDeclDetail]<< !REvent @ >>", - L"[115][RDeclDetail]<< !RMessage @ >>", - L"[116][RDeclDetail]<< !RStruct @ >>", - L"[117][RDeclDetail]<< !RUnion @ >>", - L"[118][RDecl] BEGIN ", - L"[119][RDecl] END [ENDING]", - L"[120][RDecl]<< { RAttribute @ } !RDeclDetail >>", - L"[121][RDecl]<< { RAttribute } !RDeclDetail @ >>", - L"[122][Schema] BEGIN ", - L"[123][Schema] END [ENDING]", - L"[124][Schema]< RDecl @ { RDecl } >", - L"[125][Schema]< RDecl { RDecl @ } >", + L"[15][RType]< RType \"?\" @ >", + L"[16][RType]< RType \"[\" \"]\" @ >", + L"[17][RType]< RType \"[\" @ \"]\" >", + L"[18][RType]< RType \"[\" @ RType \"]\" >", + L"[19][RType]< RType \"[\" RType \"]\" @ >", + L"[20][RType]< RType \"[\" RType @ \"]\" >", + L"[21][RType]< RType @ \"?\" >", + L"[22][RType]< RType @ \"[\" \"]\" >", + L"[23][RType]< RType @ \"[\" RType \"]\" >", + L"[24][RType]{{< NAME @ \"[\" \".\" NAME \"]\" > ; < NAME @ >}}", + L"[25][RAttribute] BEGIN ", + L"[26][RAttribute] END [ENDING]", + L"[27][RAttribute]< \"[\" @ ATT_NAME [ \"(\" ( CPP_NAME ) \")\" ] \"]\" >", + L"[28][RAttribute]< \"[\" ATT_NAME @ [ \"(\" ( CPP_NAME ) \")\" ] \"]\" >", + L"[29][RAttribute]< \"[\" ATT_NAME [ \"(\" ( CPP_NAME ) \")\" @ ] \"]\" >", + L"[30][RAttribute]< \"[\" ATT_NAME [ \"(\" ( CPP_NAME ) \")\" ] \"]\" @ >", + L"[31][RAttribute]< \"[\" ATT_NAME [ \"(\" ( CPP_NAME @ ) \")\" ] \"]\" >", + L"[32][RAttribute]< \"[\" ATT_NAME [ \"(\" @ ( CPP_NAME ) \")\" ] \"]\" >", + L"[33][REnumMember] BEGIN ", + L"[34][REnumMember] END [ENDING]", + L"[35][REnumMember]< NAME \",\" @ >", + L"[36][REnumMember]< NAME @ \",\" >", + L"[37][REnum] BEGIN ", + L"[38][REnum] END [ENDING]", + L"[39][REnum]< \"enum\" @ NAME \"{\" { REnumMember } \"}\" >", + L"[40][REnum]< \"enum\" NAME \"{\" @ { REnumMember } \"}\" >", + L"[41][REnum]< \"enum\" NAME \"{\" { REnumMember @ } \"}\" >", + L"[42][REnum]< \"enum\" NAME \"{\" { REnumMember } \"}\" @ >", + L"[43][REnum]< \"enum\" NAME @ \"{\" { REnumMember } \"}\" >", + L"[44][RUnionMember] BEGIN ", + L"[45][RUnionMember] END [ENDING]", + L"[46][RUnionMember]< NAME \",\" @ >", + L"[47][RUnionMember]< NAME @ \",\" >", + L"[48][RUnion] BEGIN ", + L"[49][RUnion] END [ENDING]", + L"[50][RUnion]< \"union\" @ NAME \"{\" { RUnionMember } \"}\" >", + L"[51][RUnion]< \"union\" NAME \"{\" @ { RUnionMember } \"}\" >", + L"[52][RUnion]< \"union\" NAME \"{\" { RUnionMember @ } \"}\" >", + L"[53][RUnion]< \"union\" NAME \"{\" { RUnionMember } \"}\" @ >", + L"[54][RUnion]< \"union\" NAME @ \"{\" { RUnionMember } \"}\" >", + L"[55][RStructMember] BEGIN ", + L"[56][RStructMember] END [ENDING]", + L"[57][RStructMember]< \"var\" @ NAME \":\" RType \";\" >", + L"[58][RStructMember]< \"var\" NAME \":\" @ RType \";\" >", + L"[59][RStructMember]< \"var\" NAME \":\" RType \";\" @ >", + L"[60][RStructMember]< \"var\" NAME \":\" RType @ \";\" >", + L"[61][RStructMember]< \"var\" NAME @ \":\" RType \";\" >", + L"[62][RStructBody] BEGIN ", + L"[63][RStructBody] END [ENDING]", + L"[64][RStructBody]< NAME \"{\" @ { RStructMember } \"}\" >", + L"[65][RStructBody]< NAME \"{\" { RStructMember @ } \"}\" >", + L"[66][RStructBody]< NAME \"{\" { RStructMember } \"}\" @ >", + L"[67][RStructBody]< NAME @ \"{\" { RStructMember } \"}\" >", + L"[68][RStruct] BEGIN ", + L"[69][RStruct] END [ENDING]", + L"[70][RStruct]", + L"[71][RStruct]", + L"[72][RStruct]", + L"[73][RStruct]", + L"[74][RMessageRequest] BEGIN ", + L"[75][RMessageRequest] END [ENDING]", + L"[76][RMessageRequest]< \"request\" \":\" @ RType \";\" >", + L"[77][RMessageRequest]< \"request\" \":\" RType \";\" @ >", + L"[78][RMessageRequest]< \"request\" \":\" RType @ \";\" >", + L"[79][RMessageRequest]< \"request\" @ \":\" RType \";\" >", + L"[80][RMessageResponse] BEGIN ", + L"[81][RMessageResponse] END [ENDING]", + L"[82][RMessageResponse]< \"response\" \":\" @ RType \";\" >", + L"[83][RMessageResponse]< \"response\" \":\" RType \";\" @ >", + L"[84][RMessageResponse]< \"response\" \":\" RType @ \";\" >", + L"[85][RMessageResponse]< \"response\" @ \":\" RType \";\" >", + L"[86][RMessage] BEGIN ", + L"[87][RMessage] END [ENDING]", + L"[88][RMessage]< \"message\" @ NAME \"{\" [ RMessageRequest ] [ RMessageResponse ] \"}\" >", + L"[89][RMessage]< \"message\" NAME \"{\" @ [ RMessageRequest ] [ RMessageResponse ] \"}\" >", + L"[90][RMessage]< \"message\" NAME \"{\" [ RMessageRequest @ ] [ RMessageResponse ] \"}\" >", + L"[91][RMessage]< \"message\" NAME \"{\" [ RMessageRequest ] [ RMessageResponse @ ] \"}\" >", + L"[92][RMessage]< \"message\" NAME \"{\" [ RMessageRequest ] [ RMessageResponse ] \"}\" @ >", + L"[93][RMessage]< \"message\" NAME @ \"{\" [ RMessageRequest ] [ RMessageResponse ] \"}\" >", + L"[94][REventRequest] BEGIN ", + L"[95][REventRequest] END [ENDING]", + L"[96][REventRequest]< \"request\" \":\" @ RType \";\" >", + L"[97][REventRequest]< \"request\" \":\" RType \";\" @ >", + L"[98][REventRequest]< \"request\" \":\" RType @ \";\" >", + L"[99][REventRequest]< \"request\" @ \":\" RType \";\" >", + L"[100][REvent] BEGIN ", + L"[101][REvent] END [ENDING]", + L"[102][REvent]< \"event\" @ NAME \"{\" [ REventRequest ] \"}\" >", + L"[103][REvent]< \"event\" NAME \"{\" @ [ REventRequest ] \"}\" >", + L"[104][REvent]< \"event\" NAME \"{\" [ REventRequest @ ] \"}\" >", + L"[105][REvent]< \"event\" NAME \"{\" [ REventRequest ] \"}\" @ >", + L"[106][REvent]< \"event\" NAME @ \"{\" [ REventRequest ] \"}\" >", + L"[107][RDeclDetail] BEGIN ", + L"[108][RDeclDetail] END [ENDING]", + L"[109][RDeclDetail]", + L"[110][RDeclDetail]", + L"[111][RDeclDetail]", + L"[112][RDeclDetail]", + L"[113][RDeclDetail]", + L"[114][RDecl] BEGIN ", + L"[115][RDecl] END [ENDING]", + L"[116][RDecl]", + L"[117][RDecl]", + L"[118][Schema] BEGIN ", + L"[119][Schema] END [ENDING]", + L"[120][Schema]< RDecl @ { RDecl } >", + L"[121][Schema]< RDecl { RDecl @ } >", }; return results[index]; } diff --git a/Import/GacUICompiler.h b/Import/GacUICompiler.h index 993bb44f..a10a3a81 100644 --- a/Import/GacUICompiler.h +++ b/Import/GacUICompiler.h @@ -1636,23 +1636,23 @@ namespace vl::presentation::remoteprotocol enum class ParserStates { RType = 0, - RAttributeParameter = 26, - RAttribute = 29, - REnumMember = 37, - REnum = 41, - RUnionMember = 48, - RUnion = 52, - RStructMember = 59, - RStructBody = 66, - RStruct = 72, - RMessageRequest = 78, - RMessageResponse = 84, - RMessage = 90, - REventRequest = 98, - REvent = 104, - RDeclDetail = 111, - RDecl = 118, - Schema = 122, + RAttributeParameter = -1, + RAttribute = 25, + REnumMember = 33, + REnum = 37, + RUnionMember = 44, + RUnion = 48, + RStructMember = 55, + RStructBody = 62, + RStruct = 68, + RMessageRequest = 74, + RMessageResponse = 80, + RMessage = 86, + REventRequest = 94, + REvent = 100, + RDeclDetail = 107, + RDecl = 114, + Schema = 118, }; const wchar_t* ParserRuleName(vl::vint index); diff --git a/Import/GacUIReflection.cpp b/Import/GacUIReflection.cpp index 7f490257..e026dbb1 100644 --- a/Import/GacUIReflection.cpp +++ b/Import/GacUIReflection.cpp @@ -776,7 +776,7 @@ Type Declaration BEGIN_CLASS_MEMBER(DocumentInlineObjectRun) CLASS_MEMBER_BASE(DocumentContentRun) - CLASS_MEMBER_FIELD(size) + CLASS_MEMBER_FIELD(sizeOverride) CLASS_MEMBER_FIELD(baseline) END_CLASS_MEMBER(DocumentInlineObjectRun) diff --git a/Import/Metadata/RemoteProtocol.json b/Import/Metadata/RemoteProtocol.json index a9c47be6..5760e734 100644 --- a/Import/Metadata/RemoteProtocol.json +++ b/Import/Metadata/RemoteProtocol.json @@ -2363,6 +2363,33 @@ } }], "type": "Struct" + }, { + "$ast": "StructDecl", + "attributes": [], + "name": "UpdateElement_DocumentParagraphResponse", + "members": [{ + "$ast": "StructMember", + "name": "documentSize", + "type": { + "$ast": "ReferenceType", + "name": "Size" + } + }, { + "$ast": "StructMember", + "name": "inlineObjectBounds", + "type": { + "$ast": "MapType", + "element": { + "$ast": "ReferenceType", + "name": "Rect" + }, + "keyType": { + "$ast": "PrimitiveType", + "type": "Integer" + } + } + }], + "type": "Struct" }, { "$ast": "MessageDecl", "attributes": [], @@ -2378,7 +2405,7 @@ "$ast": "MessageResponse", "type": { "$ast": "ReferenceType", - "name": "Size" + "name": "UpdateElement_DocumentParagraphResponse" } } }, { @@ -2386,6 +2413,13 @@ "attributes": [], "name": "GetCaretRequest", "members": [{ + "$ast": "StructMember", + "name": "id", + "type": { + "$ast": "PrimitiveType", + "type": "Integer" + } + }, { "$ast": "StructMember", "name": "caret", "type": { @@ -2426,6 +2460,13 @@ "attributes": [], "name": "GetCaretBoundsRequest", "members": [{ + "$ast": "StructMember", + "name": "id", + "type": { + "$ast": "PrimitiveType", + "type": "Integer" + } + }, { "$ast": "StructMember", "name": "caret", "type": { @@ -2441,11 +2482,58 @@ } }], "type": "Struct" + }, { + "$ast": "StructDecl", + "attributes": [], + "name": "GetInlineObjectFromPointRequest", + "members": [{ + "$ast": "StructMember", + "name": "id", + "type": { + "$ast": "PrimitiveType", + "type": "Integer" + } + }, { + "$ast": "StructMember", + "name": "point", + "type": { + "$ast": "ReferenceType", + "name": "Point" + } + }], + "type": "Struct" + }, { + "$ast": "StructDecl", + "attributes": [], + "name": "IsValidCaretRequest", + "members": [{ + "$ast": "StructMember", + "name": "id", + "type": { + "$ast": "PrimitiveType", + "type": "Integer" + } + }, { + "$ast": "StructMember", + "name": "caret", + "type": { + "$ast": "PrimitiveType", + "type": "Integer" + } + }], + "type": "Struct" }, { "$ast": "StructDecl", "attributes": [], "name": "OpenCaretRequest", "members": [{ + "$ast": "StructMember", + "name": "id", + "type": { + "$ast": "PrimitiveType", + "type": "Integer" + } + }, { "$ast": "StructMember", "name": "caret", "type": { @@ -2512,7 +2600,7 @@ "$ast": "MessageRequest", "type": { "$ast": "ReferenceType", - "name": "Point" + "name": "GetInlineObjectFromPointRequest" } }, "response": { @@ -2550,8 +2638,8 @@ "request": { "$ast": "MessageRequest", "type": { - "$ast": "PrimitiveType", - "type": "Integer" + "$ast": "ReferenceType", + "name": "IsValidCaretRequest" } }, "response": { @@ -2577,7 +2665,13 @@ "$ast": "MessageDecl", "attributes": [], "name": "DocumentParagraph_CloseCaret", - "request": null, + "request": { + "$ast": "MessageRequest", + "type": { + "$ast": "PrimitiveType", + "type": "Integer" + } + }, "response": null }, { "$ast": "StructDecl", @@ -2599,20 +2693,6 @@ } }], "type": "Struct" - }, { - "$ast": "EventDecl", - "attributes": [], - "name": "DocumentParagraph_RenderInlineObjects", - "request": { - "$ast": "EventRequest", - "type": { - "$ast": "ArrayType", - "element": { - "$ast": "ReferenceType", - "name": "RenderInlineObjectRequest" - } - } - } }, { "$ast": "EnumDecl", "attributes": [], @@ -3102,6 +3182,29 @@ } }, "response": null + }, { + "$ast": "StructDecl", + "attributes": [], + "name": "ElementDesc_DocumentParagraphFull", + "members": [{ + "$ast": "StructMember", + "name": "paragraph", + "type": { + "$ast": "ReferenceType", + "name": "ElementDesc_DocumentParagraph" + } + }, { + "$ast": "StructMember", + "name": "caret", + "type": { + "$ast": "OptionalType", + "element": { + "$ast": "ReferenceType", + "name": "OpenCaretRequest" + } + } + }], + "type": "Struct" }, { "$ast": "UnionDecl", "attributes": [], @@ -3135,7 +3238,7 @@ "name": "ElementDesc_ImageFrame" }, { "$ast": "UnionMember", - "name": "ElementDesc_DocumentParagraph" + "name": "ElementDesc_DocumentParagraphFull" }] }, { "$ast": "StructDecl", diff --git a/Import/Metadata/RemoteProtocol/Protocol_Renderer_Document.txt b/Import/Metadata/RemoteProtocol/Protocol_Renderer_Document.txt index 28f81fcf..3ab8ef27 100644 --- a/Import/Metadata/RemoteProtocol/Protocol_Renderer_Document.txt +++ b/Import/Metadata/RemoteProtocol/Protocol_Renderer_Document.txt @@ -62,10 +62,17 @@ struct ElementDesc_DocumentParagraph var removedInlineObjects : int[]; } -message RendererUpdateElement_DocumentParagraph { request: ElementDesc_DocumentParagraph; response: Size; } +struct UpdateElement_DocumentParagraphResponse +{ + var documentSize : Size; + var inlineObjectBounds : Rect[int]; +} + +message RendererUpdateElement_DocumentParagraph { request: ElementDesc_DocumentParagraph; response: UpdateElement_DocumentParagraphResponse; } struct GetCaretRequest { + var id : int; var caret : int; var relativePosition : CaretRelativePosition; } @@ -78,12 +85,26 @@ struct GetCaretResponse struct GetCaretBoundsRequest { + var id : int; var caret : int; var frontSide : bool; } +struct GetInlineObjectFromPointRequest +{ + var id : int; + var point : Point; +} + +struct IsValidCaretRequest +{ + var id : int; + var caret : int; +} + struct OpenCaretRequest { + var id : int; var caret : int; var caretColor : color; var frontSide : bool; @@ -91,16 +112,14 @@ struct OpenCaretRequest message DocumentParagraph_GetCaret { request: GetCaretRequest; response: GetCaretResponse; } message DocumentParagraph_GetCaretBounds { request: GetCaretBoundsRequest; response: Rect; } -message DocumentParagraph_GetInlineObjectFromPoint { request: Point; response: DocumentRun?; } +message DocumentParagraph_GetInlineObjectFromPoint { request: GetInlineObjectFromPointRequest; response: DocumentRun?; } message DocumentParagraph_GetNearestCaretFromTextPos { request: GetCaretBoundsRequest; response: int; } -message DocumentParagraph_IsValidCaret { request: int; response: bool; } +message DocumentParagraph_IsValidCaret { request: IsValidCaretRequest; response: bool; } message DocumentParagraph_OpenCaret { request: OpenCaretRequest; } -message DocumentParagraph_CloseCaret {} +message DocumentParagraph_CloseCaret { request: int; } struct RenderInlineObjectRequest { var callbackId : int; var location : Rect; -} - -event DocumentParagraph_RenderInlineObjects { request: RenderInlineObjectRequest[]; } \ No newline at end of file +} \ No newline at end of file diff --git a/Import/Metadata/RemoteProtocol/Protocol_UnitTest.txt b/Import/Metadata/RemoteProtocol/Protocol_UnitTest.txt index e46da983..d7d2fad6 100644 --- a/Import/Metadata/RemoteProtocol/Protocol_UnitTest.txt +++ b/Import/Metadata/RemoteProtocol/Protocol_UnitTest.txt @@ -1,3 +1,9 @@ +struct ElementDesc_DocumentParagraphFull +{ + var paragraph : ElementDesc_DocumentParagraph; + var caret : OpenCaretRequest?; +} + union UnitTest_ElementDescVariant { ElementDesc_SolidBorder, @@ -9,7 +15,7 @@ union UnitTest_ElementDescVariant ElementDesc_Polygon, ElementDesc_SolidLabel, ElementDesc_ImageFrame, - ElementDesc_DocumentParagraph, + ElementDesc_DocumentParagraphFull, } struct UnitTest_RenderingFrame diff --git a/Tools/Reflection32.bin b/Tools/Reflection32.bin index be37c6fc3e778b0ffa3536a9b29cd6beaf796e3e..5326029f4e0fef8142ec7281ac40aeb46f44f53a 100644 GIT binary patch delta 88 zcmeyd)oS53tA-ZF7N!>F7M2#)7Pc1l7LFFq7OpMaPlTr@@bd8R7H3wa`j@2^6=kNR qZkxVPl3Qo`f_p3i)6d^w5uDy2z^&8nE5Z%LJV4C5-B*NfbsGSK_a1=& delta 79 zcmZ3u&FaTitA-ZF7N!>F7M2#)7Pc1l7LFFq7OpMaPlTs0SjfrCl3A6yZF-^vxAgQ4 g=U4@&H+XU?Oka@A$F7M2#)7Pc1l7LFFq7OpMaPlTr@@bd8R7H3wa`j@2^6=kNR qZkxVPl3Qo`f_p3i)6d^w5uDy2z^&8nE5Z%LJV4C5-B*NfbsGSK_a1=& delta 79 zcmZ3u&FaTitA-ZF7N!>F7M2#)7Pc1l7LFFq7OpMaPlTs0SjfrCl3A6yZF-^vxAgQ4 g=U4@&H+XU?Oka@A$6lk>U{tyaZH!`)5A~uJk><9$?S@)|wM7%kpa=?~ z7bSl^*IT|s6hYui{}7}gd$pI|12KDv0@*ru-lE4o_`Y+_@0{=a&Y#USvAHImtxFh@ zderWwz0-~7=X&wIMMuAEU@J)CAOh|vR^4rwbsxY@R|gDtbK7LGJYBgKb$;0r_Xne$ z0SB;Ub-p?`b2*tjQK^(>tTLX+-5o8C-whw)L?ao!bEV@_BMmMenA zAwTMJA9H`jLr)xiiiR&9QY9yoB54+w7zhPgj)#Wr{%WCn) zObdk4F3sor)uF6odh?9Xhxc;_1*#Yt1Mt47My5y@+ivb?YhgeAty+||7)O}OwT z8){gqY{`h5DX8iAf5Z*oeOlv*TrrQLHFJi?$Sge4C6h3$5SBBSkj+zrwK%2Y5#z~h z1jLK^#O!6RW`b{AA*tSrlpMnA>?v-T%t`#3((pN*z=}EA(D#xX!j0p(5FT4PN=#Sb z#_VPWICYd8yJZol=FR4HY~>P6Z?K;D>$A&xkpIBL&KE*>RUl}LEEE#hF3@s-uu(9O dWB5m57~4!TX5Gf_1fk?5j5A5UW&A^!{0$36@!Sr3q3h7@0<7LoA14OZ)<~XZLqa> z3O2cppGpdGCylSnKwrRwqjn&yc40ek7#TH{*AMKjCeAI+%}-x17DsB8se^vJiF@%& z^Rt!e6?{{(c%~k~12uz|;CIdRsU{u=6Tx%tbRb4-}sZxx3I%p@oGF0NP+7kVgC^0E;%N3MZ zLN6PrmkLynN$0}e9hJFK{)`<*z~ll|!V>NKRO+%*Kzm5yqhsPF#eO-1*l`WYe23;a NXvfg!n)`AU{{h8E-s%7V diff --git a/Tutorial/GacUI_HelloWorlds/UIRes/Xml.bin.x86 b/Tutorial/GacUI_HelloWorlds/UIRes/Xml.bin.x86 index 3ee35882fa06f8d3755191760267f84f8afbfe4b..c9f84d05b8098bb9408b80762273cc1f10a518bf 100644 GIT binary patch delta 665 zcmZ8e&ubGw6n1tuyR*A#Gohu~*qSDxhv1L6tso^xK@oasgF;DvWRu+$g+yXnNe}j9 z4_XieAzzPzH$epnR6Q#cttU@H3WEPY@uo;o*4IrCap1jgX5M?>eD6(nmvwhp=Yxbj zHHz<224h|p`^-XKPQy^z_^OQJwQ>@tBN-ej$MIN6TG3;@b%d>r*7}WGg+ghyejW3X z7bwaOy7CmB%X!pP8#z^A#20v2<#?+WvF!?^Gz(F|F{3Sn=xIspXvua=$7gMl5A^x* zGh&DFD=OEe{-uPBnt&4*%)mQ7ge)IrQMmjZdGIsL#0*cf0gB~uUKR-WFcTQor^v7A zBY37q!(EoeFstVn!yCPXS5<*M9>XcaLW$JQ^Eejhj*tiag@%!20k(__OvkvHAkWMb zDZMZ3U-X;nb-z*fTZ6c*4oP=jxDJ z@#Q7tuW>x82s9mz2g{xR&TDWfrc~3EL;2;4;dy^0he4mCU9RDPW-d7vM>Udd+ia7>pz6vj7a<3Qal8!aVZ`CBeddG`Tq2Gh} znbk4G+BY2ok$Clh_~Tf&Al%Isv6&-Cw!!LF z?G8M22pM~j-&v0=g@UzYQ>YIWdxXo#8Nu5z9YyCRv(=C?nbUESeT7dl86=!`Ox(y_ zLelNw1wF7`i`U(AT@l7t_X@W11XE$j%sKXJ`DrYxI;#0O+-AAgS;hkMQRaQ;`D;BB Mk0M5+e#@Kq11;;(CIA2c diff --git a/Tutorial/GacUI_Layout/UIRes/RichTextEmbedding.bin b/Tutorial/GacUI_Layout/UIRes/RichTextEmbedding.bin index a2076f556e78da9e65bcb61443c82a91058c6a33..8911456fe9b8ea6d3845c455eccd0e3389b4c9c9 100644 GIT binary patch delta 37 qcmaF+k@@~d<_+qMoZ4&*V4%I(fRT@Baw@awWLsv*&9j(;zXAZ$h6