Skip to content

Commit 2d68777

Browse files
committed
- Add substitutable label fields. e.g. label can be "$(font_family)".
- Add assorted action to resize unwrapped object.
1 parent 09401a5 commit 2d68777

6 files changed

Lines changed: 111 additions & 18 deletions

File tree

DrawableObject.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ class DrawableObject : public ComObject
174174
////////////////////
175175
// Helpers
176176
static DrawableObject* Create(DrawableObjectFunction functionId);
177-
static void GenerateLabel(IAttributeSource& attributeSource, _Inout_ std::u16string& label);
177+
static void GenerateLabel(IAttributeSource& attributeSource, _Out_ std::u16string& label);
178178
static HRESULT GetDWriteFontFace(IAttributeSource& attributeSource, DrawingCanvas& drawingCanvas, _COM_Outptr_ IDWriteFontFace** fontFace);
179179
static HRESULT SaveFontFile(IAttributeSource& attributeSource, DrawingCanvas& drawingCanvas, char16_t const* filePath);
180180
static HRESULT ExportFontGlyphData(IAttributeSource& attributeSource, DrawingCanvas& drawingCanvas, array_ref<char16_t const> filePath);
@@ -185,6 +185,7 @@ class DrawableObject : public ComObject
185185
static const Attribute::PredefinedValue functions[12];
186186
static const Attribute::PredefinedValue visibilities[2];
187187
static const Attribute::PredefinedValue enabledValues[2];
188+
static const Attribute::PredefinedValue labelDefaults[2];
188189
static const Attribute::PredefinedValue textDefaults[68];
189190
static const Attribute::PredefinedValue readingDirections[8];
190191
static const Attribute::PredefinedValue glyphDefaults[3];

DrawableObject.ixx

Lines changed: 66 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ const Attribute DrawableObject::attributeList[DrawableObjectAttributeTotal] =
4141
{
4242
{Attribute::TypeUInteger32, Attribute::SemanticEnumExclusive,CategoryLight, DrawableObjectAttributeFunction, u"function", u"Function", u"IDWriteTextLayout", functions },
4343
{Attribute::TypeBool8, Attribute::SemanticEnumExclusive,0 , DrawableObjectAttributeVisibility, u"visible", u"Visible", u"visible", visibilities },
44-
{Attribute::TypeString16, Attribute::SemanticNone, 0 , DrawableObjectAttributeLabel, u"label", u"Label", u"", {} },
44+
{Attribute::TypeString16, Attribute::SemanticNone, 0 , DrawableObjectAttributeLabel, u"label", u"Label", u"", labelDefaults },
4545
{Attribute::TypeString16, Attribute::SemanticLongText, CategoryLight, DrawableObjectAttributeText, u"text", u"Text", u"This is a text", textDefaults },
4646
{Attribute::TypeArrayUInteger16,Attribute::SemanticNone, 0 , DrawableObjectAttributeGlyphs, u"glyphs", u"Glyphs", u"0 1 2 3 4", glyphDefaults },
4747
{Attribute::TypeArrayFloat32, Attribute::SemanticNone, 0 , DrawableObjectAttributeAdvances, u"advances", u"Advances", u"",{} },
@@ -129,6 +129,11 @@ const Attribute::PredefinedValue DrawableObject::enabledValues[] = {
129129
{1, u"on"},
130130
};
131131

132+
const Attribute::PredefinedValue DrawableObject::labelDefaults[] = {
133+
{0, u"", u"" },
134+
{0, u"", u"Family = $(font_family), Font size = $(font_size)"},
135+
};
136+
132137
const Attribute::PredefinedValue DrawableObject::textDefaults[] = {
133138
{0, u"Empty text", u""},
134139
{0, u"Feature tests",
@@ -975,13 +980,71 @@ DrawableObject* DrawableObject::Create(DrawableObjectFunction functionType)
975980
}
976981

977982

978-
void DrawableObject::GenerateLabel(IAttributeSource& attributeSource, _Inout_ std::u16string& label)
983+
void DrawableObject::GenerateLabel(IAttributeSource& attributeSource, _Out_ std::u16string& label)
979984
{
980985
// Update the current label, either using the explicit one or generating
981986
// one dynamically according to set attributes.
987+
988+
const char16_t escapeCharacter = '$';
989+
982990
array_ref<char16_t const> defaultLabel = attributeSource.GetString(DrawableObjectAttributeLabel);
983-
if (!defaultLabel.empty())
991+
992+
if (wcschr(ToWChar(defaultLabel.data()), escapeCharacter) != nullptr)
993+
{
994+
// Generate a label using the field names.
995+
label.clear();
996+
997+
std::map<std::u16string, uint32_t> attributeNameMap;
998+
for (auto const& attribute : DrawableObject::attributeList)
999+
{
1000+
attributeNameMap[attribute.name] = attribute.id;
1001+
}
1002+
const auto attributeNameMapEnd = attributeNameMap.end();
1003+
std::u16string fieldName;
1004+
1005+
// Walk string looking for replaceable parts. e.g. "Family name = $(font_family), Weight = ($weight)"
1006+
for (auto current = defaultLabel.begin(); current != defaultLabel.end();)
1007+
{
1008+
char16_t const* next = std::find(current, defaultLabel.end(), escapeCharacter);
1009+
label.append(current, next);
1010+
1011+
if (next == defaultLabel.end())
1012+
break;
1013+
1014+
++next; // Skip '$'.
1015+
if (next == defaultLabel.end())
1016+
break;
1017+
1018+
if (*next == escapeCharacter)
1019+
{
1020+
// '$$' maps to just '$'.
1021+
label.push_back(escapeCharacter);
1022+
++next;
1023+
}
1024+
else if (*next == '(')
1025+
{
1026+
// $(namedField) substitutes the string with that attribute's value.
1027+
++next; // Skip '('.
1028+
char16_t const* endOfEscape = std::find(next, defaultLabel.end(), ')');
1029+
if (endOfEscape == defaultLabel.end())
1030+
break;
1031+
1032+
fieldName.assign(next, endOfEscape);
1033+
auto nameMapResult = attributeNameMap.find(fieldName);
1034+
if (nameMapResult != attributeNameMapEnd)
1035+
{
1036+
array_ref<char16_t const> text = attributeSource.GetString(DrawableObjectAttribute(nameMapResult->second));
1037+
label.append(text.begin(), text.end());
1038+
}
1039+
next = endOfEscape + 1; // Skip ')'.
1040+
}
1041+
1042+
current = next;
1043+
}
1044+
}
1045+
else if (!defaultLabel.empty())
9841046
{
1047+
// Just assign the label directly.
9851048
if (wcscmp(ToWChar(defaultLabel.data()), ToWChar(label.c_str())) != 0)
9861049
{
9871050
label.assign(defaultLabel.data(), defaultLabel.size());

DrawableObjectAndValues.ixx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,10 @@ void DrawableObjectAndValues::Load(
441441

442442
for (TextTree::NodePointer objectNode = objectsNode.begin(), objectNodeEnd = objectsNode.end(); objectNode != objectNodeEnd; ++objectNode)
443443
{
444-
// Add another object, or fill in the shared object if first entry.
444+
// The very first object definition in the file is actually a shared object that factors
445+
// out all common attributes between objects (to avoid repeating them every time in each
446+
// object that uses them). So if reading the first object, just update the shared object,
447+
// otherwise the first real drawable object is the second object in the file.
445448
if (!isFirstObject)
446449
{
447450
drawableObjects.push_back(sharedDrawableObject);

MainWindow.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ class MainWindow
8080
HRESULT SaveUnpackedWoffFontFile();
8181
HRESULT ExportFontGlyphData();
8282
HRESULT AutofitDrawableObjects(bool useMaximumWidth, bool useMaximumHeight);
83+
HRESULT SetNoLineWrapOnDrawableObjects();
8384
HRESULT GetSelectedDrawableObject(_Out_ uint32_t& selectedDrawableObject); // S_FALSE and ~0 if none.
8485
HRESULT GetAllFontCharacters(bool copyToClipboardInstead, bool getOnlyColorFontCharacters);
8586
HRESULT GetLogFontFromDrawableObjects(_Out_ LOGFONT& logFont);

MainWindow.ixx

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,7 +1248,7 @@ MainWindow::DialogProcResult CALLBACK MainWindow::OnDragAndDrop(HWND hwnd, UINT
12481248
DragFinish(hDrop);
12491249

12501250
if (hr == HRESULT_FROM_WIN32(ERROR_BAD_FORMAT))
1251-
ShowMessageAndAppendLog(u"Unknown file format '%s', 0x%08X", fileName.c_str(), hr);
1251+
ShowMessageAndAppendLog(u"Unknown file format '%s' (TextLayoutSamplerSettings, txt, ttf, otf, tte, ttc, otc), 0x%08X", fileName.c_str(), hr);
12521252
else if (FAILED(hr))
12531253
ShowMessageAndAppendLog(u"Failed to load file '%s', 0x%08X", fileName.c_str(), hr);
12541254

@@ -1268,6 +1268,11 @@ std::vector<uint32_t> MainWindow::GetSelectedDrawableObjectIndices()
12681268
selectedIndices.resize(drawableObjects_.size());
12691269
std::iota(selectedIndices.begin(), selectedIndices.end(), 0);
12701270
}
1271+
else // Validate the indices, just in case the UI somehow became out of sync.
1272+
{
1273+
auto const drawableObjectsTotal = drawableObjects_.size();
1274+
selectedIndices.erase(std::remove_if(selectedIndices.begin(), selectedIndices.end(), [=](auto i) {return i >= drawableObjectsTotal; }), selectedIndices.end());
1275+
}
12711276

12721277
return selectedIndices;
12731278
}
@@ -1484,9 +1489,6 @@ HRESULT MainWindow::UpdateDrawableObjectsFromFontFamilyNameProperties(FontFamily
14841489

14851490
for (auto drawableObjectIndex : selectedDrawableObjectIndices)
14861491
{
1487-
if (drawableObjectIndex >= drawableObjectsTotal)
1488-
continue;
1489-
14901492
auto& drawableObject = drawableObjects_[drawableObjectIndex];
14911493
DrawableObjectFunction function = drawableObject.GetValue(DrawableObjectAttributeFunction, DrawableObjectFunctionNop);
14921494
bool isGdiOrGdiPlusFunction = DrawableObject::IsGdiOrGdiPlusFunction(function);
@@ -2112,9 +2114,6 @@ HRESULT MainWindow::AutofitDrawableObjects(bool useMaximumWidth, bool useMaximum
21122114
// The first pass gets the sizes of all the objects.
21132115
for (auto drawableObjectIndex : drawableObjectIndices)
21142116
{
2115-
if (drawableObjectIndex >= drawableObjectsTotal)
2116-
continue;
2117-
21182117
auto& drawableObject = drawableObjects_[drawableObjectIndex];
21192118

21202119
D2D_RECT_F layoutBounds, contentBounds;
@@ -2132,9 +2131,6 @@ HRESULT MainWindow::AutofitDrawableObjects(bool useMaximumWidth, bool useMaximum
21322131
// The second pass updates them, considering whether to maximize them to the largest object found.
21332132
for (auto drawableObjectIndex : drawableObjectIndices)
21342133
{
2135-
if (drawableObjectIndex >= drawableObjectsTotal)
2136-
continue;
2137-
21382134
auto& drawableObject = drawableObjects_[drawableObjectIndex];
21392135
D2D_SIZE_F& size = sizes[drawableObjectIndex];
21402136
if (size.width > 0 && size.height > 0)
@@ -2159,6 +2155,33 @@ HRESULT MainWindow::AutofitDrawableObjects(bool useMaximumWidth, bool useMaximum
21592155
}
21602156

21612157

2158+
HRESULT MainWindow::SetNoLineWrapOnDrawableObjects()
2159+
{
2160+
// Reduce all selected drawable objects to 1x1, and set no wrapping.
2161+
std::vector<uint32_t> drawableObjectIndices = GetSelectedDrawableObjectIndices();
2162+
for (auto drawableObjectIndex : drawableObjectIndices)
2163+
{
2164+
auto& drawableObject = drawableObjects_[drawableObjectIndex];
2165+
drawableObject.Set(DrawableObjectAttributeLineWrappingMode, LineWrappingModeNone);
2166+
drawableObject.Set(DrawableObjectAttributeWidth, 1);
2167+
drawableObject.Set(DrawableObjectAttributeHeight, 1);
2168+
drawableObject.Update();
2169+
}
2170+
2171+
DeferUpdateUi(
2172+
NeededUiUpdateDrawableObjectsListView |
2173+
NeededUiUpdateAttributesListView |
2174+
NeededUiUpdateAttributeValuesListView |
2175+
NeededUiUpdateAttributeValuesEdit |
2176+
NeededUiUpdateAttributeValuesSlider |
2177+
NeededUiUpdateDrawableObjectsCanvas |
2178+
NeededUiUpdateTextEdit
2179+
);
2180+
2181+
return S_OK;
2182+
}
2183+
2184+
21622185
HRESULT MainWindow::StoreDrawableObjectsSettings()
21632186
{
21642187
std::u16string filePath;
@@ -2184,11 +2207,11 @@ HRESULT MainWindow::StoreDrawableObjectsSettings()
21842207
}
21852208
if (hr == HRESULT_FROM_WIN32(ERROR_BAD_FORMAT)) // Consolidate this repeated error message.
21862209
{
2187-
ShowMessageAndAppendLog(u"Unknown file format '%s', 0x%08X", filePath.c_str(), hr);
2210+
ShowMessageAndAppendLog(u"Unknown sampler settings file format '%s', 0x%08X", filePath.c_str(), hr);
21882211
}
21892212
else if (FAILED(hr))
21902213
{
2191-
ShowMessageAndAppendLog(u"Failed to save to file '%s', 0x%08X", filePath.c_str(), hr);
2214+
ShowMessageAndAppendLog(u"Failed to save to sampler settings file '%s', 0x%08X", filePath.c_str(), hr);
21922215
}
21932216

21942217
return hr;
@@ -2983,8 +3006,9 @@ void MainWindow::OnAssortedActions(HWND anchorControl)
29833006
{IdcGetAllColorFontCharacters, u"Get all color font characters"},
29843007
{IdcCopyAllFontCharacters, u"Copy all font characters to clipboard"},
29853008
{0, u"-"},
2986-
{ IdcAutofitDrawableObjects, u"Autofit drawable objects" },
3009+
{IdcAutofitDrawableObjects, u"Autofit drawable objects" },
29873010
{IdcAutofitDrawableObjectsUniformly, u"Autofit drawable objects uniformly" },
3011+
{IdcSetNoLineWrapOnDrawableObjects, u"Reduce drawable objects size with no wrap"}
29883012
};
29893013

29903014
int menuId = TrackPopupMenu(make_array_ref(items, countof(items)), anchorControl, hwnd_);
@@ -2999,6 +3023,7 @@ void MainWindow::OnAssortedActions(HWND anchorControl)
29993023
case IdcExportGlyphImageData: ExportFontGlyphData(); break;
30003024
case IdcAutofitDrawableObjects: AutofitDrawableObjects(/*useMaximumWidth*/false, /*useMaximumHeight*/false); break;
30013025
case IdcAutofitDrawableObjectsUniformly: AutofitDrawableObjects(/*useMaximumWidth*/true, /*useMaximumHeight*/true); break;
3026+
case IdcSetNoLineWrapOnDrawableObjects: SetNoLineWrapOnDrawableObjects(); break;
30023027
}
30033028
}
30043029

resource.h

96 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)