Ticket #5606: fixes-mhegupdate.patch
File fixes-mhegupdate.patch, 54.6 KB (added by , 16 years ago) |
---|
-
libs/libmythfreemheg/Actions.cpp
1 1 /* Actions.cpp 2 2 3 Copyright (C) David C. J. Matthews 2004 dm at prolingua.co.uk3 Copyright (C) David C. J. Matthews 2004, 2008 dm at prolingua.co.uk 4 4 5 5 This program is free software; you can redistribute it and/or 6 6 modify it under the terms of the GNU General Public License … … 93 93 case C_GET_ENTRY_POINT: pAction = new MHUnimplementedAction(pElemAction->GetTagNo()); break; // EntryField 94 94 case C_GET_FILL_COLOUR: pAction = new MHGetFillColour; break; 95 95 case C_GET_FIRST_ITEM: pAction = new MHGetFirstItem; break; 96 case C_GET_HIGHLIGHT_STATUS: pAction = new MH UnimplementedAction(pElemAction->GetTagNo()); break;// ?97 case C_GET_INTERACTION_STATUS: pAction = new MH UnimplementedAction(pElemAction->GetTagNo()); break;// ?96 case C_GET_HIGHLIGHT_STATUS: pAction = new MHGetHighlightStatus; break; 97 case C_GET_INTERACTION_STATUS: pAction = new MHGetInteractionStatus; break; 98 98 case C_GET_ITEM_STATUS: pAction = new MHGetItemStatus; break; 99 99 case C_GET_LABEL: pAction = new MHUnimplementedAction(pElemAction->GetTagNo()); break;// PushButton 100 100 case C_GET_LAST_ANCHOR_FIRED: pAction = new MHUnimplementedAction(pElemAction->GetTagNo()); break;// HyperText … … 104 104 case C_GET_LIST_ITEM: pAction = new MHGetListItem; break; 105 105 case C_GET_LIST_SIZE: pAction = new MHGetListSize; break; 106 106 case C_GET_OVERWRITE_MODE: pAction = new MHUnimplementedAction(pElemAction->GetTagNo()); break;// ? 107 case C_GET_PORTION: pAction = new MH UnimplementedAction(pElemAction->GetTagNo()); break;// Slider107 case C_GET_PORTION: pAction = new MHGetPortion; break; 108 108 case C_GET_POSITION: pAction = new MHGetPosition; break; 109 109 case C_GET_RUNNING_STATUS: pAction = new MHGetRunningStatus; break; 110 110 case C_GET_SELECTION_STATUS: pAction = new MHUnimplementedAction(pElemAction->GetTagNo()); break;// ? 111 case C_GET_SLIDER_VALUE: pAction = new MH UnimplementedAction(pElemAction->GetTagNo()); break;// Slider111 case C_GET_SLIDER_VALUE: pAction = new MHGetSliderValue; break; 112 112 case C_GET_TEXT_CONTENT: pAction = new MHUnimplementedAction(pElemAction->GetTagNo()); break;// Text 113 113 case C_GET_TEXT_DATA: pAction = new MHGetTextData; break; 114 114 case C_GET_TOKEN_POSITION: pAction = new MHGetTokenPosition; break; … … 145 145 case C_SET_FILL_COLOUR: pAction = new MHSetFillColour; break; 146 146 case C_SET_FIRST_ITEM: pAction = new MHSetFirstItem; break; 147 147 case C_SET_FONT_REF: pAction = new MHUnimplementedAction(pElemAction->GetTagNo()); break; // Text 148 case C_SET_HIGHLIGHT_STATUS: pAction = new MH UnimplementedAction(pElemAction->GetTagNo()); break; // ?149 case C_SET_INTERACTION_STATUS: pAction = new MH UnimplementedAction(pElemAction->GetTagNo()); break; // ?148 case C_SET_HIGHLIGHT_STATUS: pAction = new MHSetHighlightStatus; break; 149 case C_SET_INTERACTION_STATUS: pAction = new MHSetInteractionStatus; break; 150 150 case C_SET_LABEL: pAction = new MHUnimplementedAction(pElemAction->GetTagNo()); break; // PushButton 151 151 case C_SET_LINE_COLOUR: pAction = new MHSetLineColour; break; 152 152 case C_SET_LINE_STYLE: pAction = new MHSetLineStyle; break; 153 153 case C_SET_LINE_WIDTH: pAction = new MHSetLineWidth; break; 154 154 case C_SET_OVERWRITE_MODE: pAction = new MHUnimplementedAction(pElemAction->GetTagNo()); break; // EntryField 155 155 case C_SET_PALETTE_REF: pAction = new MHUnimplementedAction(pElemAction->GetTagNo()); break; // Visible 156 case C_SET_PORTION: pAction = new MH UnimplementedAction(pElemAction->GetTagNo()); break; // Slider156 case C_SET_PORTION: pAction = new MHSetPortion; break; 157 157 case C_SET_POSITION: pAction = new MHSetPosition; break; 158 case C_SET_SLIDER_VALUE: pAction = new MH UnimplementedAction(pElemAction->GetTagNo()); break; // Slider158 case C_SET_SLIDER_VALUE: pAction = new MHSetSliderValue; break; 159 159 case C_SET_SPEED: pAction = new MHUnimplementedAction(pElemAction->GetTagNo()); break; // ? 160 160 case C_SET_TIMER: pAction = new MHSetTimer; break; 161 161 case C_SET_TRANSPARENCY: pAction = new MHSetTransparency; break; 162 162 case C_SET_VARIABLE: pAction = new MHSetVariable; break; 163 163 case C_SET_VOLUME: pAction = new MHUnimplementedAction(pElemAction->GetTagNo()); break; // ? 164 164 case C_SPAWN: pAction = new MHSpawn; break; 165 case C_STEP: pAction = new MH UnimplementedAction(pElemAction->GetTagNo()); break; // Slider165 case C_STEP: pAction = new MHStep; break; 166 166 case C_STOP: pAction = new MHStop; break; 167 167 case C_STORE_PERSISTENT: pAction = new MHPersistent(":StorePersistent", false); break; 168 168 case C_SUBTRACT: pAction = new MHSubtract; break; … … 184 184 case C_SET_FOCUS_POSITION: pAction = new MHUnimplementedAction(pElemAction->GetTagNo()); break; // HyperText 185 185 case C_SET_BITMAP_DECODE_OFFSET: pAction = new MHSetBitmapDecodeOffset; break; 186 186 case C_GET_BITMAP_DECODE_OFFSET: pAction = new MHGetBitmapDecodeOffset; break; 187 case C_SET_SLIDER_PARAMETERS: pAction = new MH UnimplementedAction(pElemAction->GetTagNo()); break; // ?187 case C_SET_SLIDER_PARAMETERS: pAction = new MHSetSliderParameters; break; 188 188 189 189 default: 190 190 MHLOG(MHLogWarning, QString("Unknown action %1").arg(pElemAction->GetTagNo())); -
libs/libmythfreemheg/Engine.cpp
1 1 /* Engine.cpp 2 2 3 Copyright (C) David C. J. Matthews 2004 dm at prolingua.co.uk3 Copyright (C) David C. J. Matthews 2004, 2008 dm at prolingua.co.uk 4 4 5 5 This program is free software; you can redistribute it and/or 6 6 modify it under the terms of the GNU General Public License … … 31 31 #include "ASN1Codes.h" 32 32 #include "Logging.h" 33 33 #include "freemheg.h" 34 #include "Visible.h" // For MHInteractible 34 35 35 36 #include <stdio.h> 36 37 #include <stdlib.h> … … 50 51 m_ExternContentTable.setAutoDelete(true); 51 52 52 53 m_fBooting = true; 54 m_Interacting = 0; 53 55 } 54 56 55 57 MHEngine::~MHEngine() … … 307 309 pApp->m_pCurrentScene = NULL; 308 310 } 309 311 312 m_Interacting = 0; 310 313 311 314 // Switch to the new scene. 312 315 CurrentApp()->m_pCurrentScene = (MHScene*) pProgram; … … 604 607 { 605 608 MHScene *pScene = CurrentScene(); 606 609 if (! pScene) return; 607 EventTriggered(pScene, EventUserInput, nCode); 610 // Various keys generate engine events as well as user events. 611 // These are generated before the user events and even if there 612 // is an interactible. 613 switch (nCode) 614 { 615 case 104: 616 case 105: // Text key 617 EventTriggered(pScene, EventEngineEvent, 4); 618 break; 619 case 16: // Text Exit/Cancel key 620 case 100: // Red 621 case 101: // Green 622 case 102: // Yellow 623 case 103: // Blue 624 EventTriggered(pScene, EventEngineEvent, nCode); 625 break; 626 } 627 628 // If we are interacting with an interactible send the key 629 // there otherwise generate a user event. 630 if (m_Interacting) 631 m_Interacting->KeyEvent(this, nCode); 632 else EventTriggered(pScene, EventUserInput, nCode); 608 633 } 609 634 610 635 // Called by an ingredient wanting external content. -
libs/libmythfreemheg/ParseText.cpp
1 1 /* ParseText.cpp 2 2 3 Copyright (C) David C. J. Matthews 2004 dm at prolingua.co.uk3 Copyright (C) David C. J. Matthews 2004, 2008 dm at prolingua.co.uk 4 4 5 5 This program is free software; you can redistribute it and/or 6 6 modify it under the terms of the GNU General Public License … … 536 536 if (m_nInt > 0) return; 537 537 m_nInt = MHText::GetStartCorner(buff); 538 538 if (m_nInt > 0) return; 539 m_nInt = MHSlider::GetOrientation(buff); 540 if (m_nInt > 0) return; 541 m_nInt = MHSlider::GetStyle(buff); 542 if (m_nInt > 0) return; 539 543 540 544 // Check the colour table. If it's there generate a string containing the colour info. 541 545 for (int i = 0; i < (int)(sizeof(colourTable)/sizeof(colourTable[0])); i++) { -
libs/libmythfreemheg/Text.cpp
1 1 /* Text.cpp 2 2 3 Copyright (C) David C. J. Matthews 2004 dm at prolingua.co.uk3 Copyright (C) David C. J. Matthews 2004, 2008 dm at prolingua.co.uk 4 4 5 5 This program is free software; you can redistribute it and/or 6 6 modify it under the terms of the GNU General Public License … … 463 463 pNewLine->m_Items.Append(pNewItem); 464 464 pNewItem->m_Unicode = pItem->m_Unicode.mid(nNewStart, nNewWidth); 465 465 pNewItem->m_nUnicode = nNewWidth; 466 // Move any remaining items, e.g. in a different colour, from this line onto the new line. 467 while (pLine->m_Items.Size() > j+1) { 468 pNewLine->m_Items.Append(pLine->m_Items.GetAt(j+1)); 469 pLine->m_Items.RemoveAt(j+1); 470 } 466 471 } 467 472 // Remove any spaces at the end of the old section. If we don't do that and 468 473 // we are centering or right aligning the text we'll get it wrong. … … 534 539 } 535 540 536 541 537 MHHyperText::MHHyperText() 542 MHHyperText::MHHyperText(): MHInteractible(this) 538 543 { 539 544 540 545 } -
libs/libmythfreemheg/Root.h
176 176 virtual void SetVideoDecodeOffset(int /*newXOffset*/, int /*newYOffset*/, MHEngine *) { InvalidAction("SetVideoDecodeOffset"); } 177 177 virtual void GetVideoDecodeOffset(MHRoot * /*pXOffset*/, MHRoot */*pYOffset*/, MHEngine *) { InvalidAction("GetVideoDecodeOffset"); } 178 178 179 // Actions on Interactibles. 180 virtual void SetInteractionStatus(bool /*newStatus*/, MHEngine *) { InvalidAction("SetInteractionStatus"); } 181 virtual bool GetInteractionStatus(void) { InvalidAction("GetInteractionStatus"); return false; } 182 virtual void SetHighlightStatus(bool /*newStatus*/, MHEngine *engine) { InvalidAction("SetHighlightStatus"); } 183 virtual bool GetHighlightStatus(void) { InvalidAction("GetHighlightStatus"); return false; } 184 185 // Actions on Sliders. 186 virtual void Step(int /*nbSteps*/, MHEngine */*engine*/) { InvalidAction("Step"); } 187 virtual void SetSliderValue(int /*nbSteps*/, MHEngine */*engine*/) { InvalidAction("SetSliderValue"); } 188 virtual int GetSliderValue(void) { InvalidAction("GetSliderValue"); return 0; } 189 virtual void SetPortion(int /*newPortion*/, MHEngine */*engine*/) { InvalidAction("SetPortion"); } 190 virtual int GetPortion(void) { InvalidAction("GetPortion"); return 0; } 191 // Additional action defined in UK MHEG. 192 virtual void SetSliderParameters(int /*newMin*/, int /*newMax*/, int /*newStep*/, MHEngine */*engine*/) 193 { InvalidAction("SetSliderParameters"); } 194 179 195 protected: 180 196 181 197 void InvalidAction(const char *actionName); -
libs/libmythfreemheg/BaseActions.h
1 1 /* BaseActions.h 2 2 3 Copyright (C) David C. J. Matthews 2004 dm at prolingua.co.uk3 Copyright (C) David C. J. Matthews 2004, 2008 dm at prolingua.co.uk 4 4 5 5 This program is free software; you can redistribute it and/or 6 6 modify it under the terms of the GNU General Public License … … 73 73 MHGenericInteger m_Argument1, m_Argument2; 74 74 }; 75 75 76 // Base class for actions with three integers. Used for SetSliderParameters 77 class MHActionInt3: public MHElemAction 78 { 79 public: 80 MHActionInt3(const char *name): MHElemAction(name) {} 81 virtual void Initialise(MHParseNode *p, MHEngine *engine); 82 virtual void PrintArgs(FILE *fd, int nTabs) const; 83 virtual void Perform(MHEngine *engine); 84 virtual void CallAction(MHEngine *engine, MHRoot *pTarget, int nArg1, int nArg2, int nArg3) = 0; 85 protected: 86 MHGenericInteger m_Argument1, m_Argument2, m_Argument3; 87 }; 88 76 89 // Base class for actions with four integers. Used in the DynamicLineArt class 77 90 class MHActionInt4: public MHElemAction 78 91 { … … 139 152 }; 140 153 141 154 155 // Base class for actions with a single boolean argument. 156 class MHActionBool: public MHElemAction 157 { 158 public: 159 MHActionBool(const char *name): MHElemAction(name) {} 160 virtual void Initialise(MHParseNode *p, MHEngine *engine); 161 virtual void PrintArgs(FILE *fd, int) const { m_Argument.PrintMe(fd, 0); } 162 virtual void Perform(MHEngine *engine); 163 virtual void CallAction(MHEngine *engine, MHRoot *pTarget, bool fArg) = 0; 164 protected: 165 MHGenericBoolean m_Argument; 166 }; 167 142 168 #endif -
libs/libmythfreemheg/Visible.h
1 1 /* Visible.h 2 2 3 Copyright (C) David C. J. Matthews 2004 dm at prolingua.co.uk3 Copyright (C) David C. J. Matthews 2004, 2008 dm at prolingua.co.uk 4 4 5 5 This program is free software; you can redistribute it and/or 6 6 modify it under the terms of the GNU General Public License … … 124 124 virtual MHIngredient *Clone(MHEngine *) { return new MHRectangle(*this); } // Create a clone of this ingredient. 125 125 }; 126 126 127 // The Interactible class is described as a "mix-in" class. It is used 128 // in various classes which complicates inheritance. 127 129 class MHInteractible 128 130 { 129 131 public: 130 MHInteractible( );132 MHInteractible(MHVisible *parent); 131 133 virtual ~MHInteractible(); 132 virtual void Initialise(MHParseNode *p, MHEngine *engine); 133 virtual void PrintMe(FILE *fd, int nTabs) const; 134 void Initialise(MHParseNode *p, MHEngine *engine); 135 void PrintMe(FILE *fd, int nTabs) const; 136 137 virtual void Interaction(MHEngine *engine); 138 139 // This is called whenever a key is pressed while this 140 // interactible is set to interactive. 141 virtual void KeyEvent(MHEngine */*engine*/, int /*nCode*/) {} 142 virtual void InteractionCompleted(MHEngine */*engine*/) {} 143 144 void InteractSetInteractionStatus(bool newStatus, MHEngine *engine); 145 bool InteractGetInteractionStatus(void) { return m_fInteractionStatus; } 146 void InteractSetHighlightStatus(bool newStatus, MHEngine *engine); 147 bool InteractGetHighlightStatus(void) { return m_fHighlightStatus; } 148 // InteractDeactivation should be applied in every Deactivation action 149 // of derived classes. 150 void InteractDeactivation(void) { m_fInteractionStatus = false; } 151 152 protected: 153 // Exchanged attributes 154 bool m_fEngineResp; 155 MHColour m_highlightRefColour; 156 // Internal attributes 157 bool m_fHighlightStatus; 158 bool m_fInteractionStatus; 159 160 private: 161 MHVisible *m_parent; 134 162 }; 135 163 136 164 class MHSlider : public MHVisible, public MHInteractible … … 141 169 virtual const char *ClassName() { return "Slider"; } 142 170 virtual void Initialise(MHParseNode *p, MHEngine *engine); 143 171 virtual void PrintMe(FILE *fd, int nTabs) const; 144 virtual void Display(MHEngine *) {} // Not (yet?) supported 172 virtual void Display(MHEngine *); 173 virtual void Preparation(MHEngine *engine); 174 175 virtual void Interaction(MHEngine *engine); 176 virtual void InteractionCompleted(MHEngine *engine); 177 virtual void KeyEvent(MHEngine *engine, int nCode); 178 179 // Implement the actions in the main inheritance line. 180 virtual void SetInteractionStatus(bool newStatus, MHEngine *engine) 181 { InteractSetInteractionStatus(newStatus, engine); } 182 virtual bool GetInteractionStatus(void) { return InteractGetInteractionStatus(); } 183 virtual void SetHighlightStatus(bool newStatus, MHEngine *engine) 184 { InteractSetHighlightStatus(newStatus, engine); } 185 virtual bool GetHighlightStatus(void) { return InteractGetHighlightStatus(); } 186 virtual void Deactivation(MHEngine *engine) { InteractDeactivation(); } 187 188 // Actions 189 virtual void Step(int nbSteps, MHEngine *engine); 190 virtual void SetSliderValue(int newValue, MHEngine *engine); 191 virtual int GetSliderValue(void) { return slider_value; } 192 virtual void SetPortion(int newPortion, MHEngine *engine); 193 virtual int GetPortion(void) { return portion; } 194 // Additional action defined in UK MHEG. 195 virtual void SetSliderParameters(int newMin, int newMax, int newStep, MHEngine *engine); 196 197 // Enumerated type lookup functions for the text parser. 198 static int GetOrientation(const char *str); 199 static int GetStyle(const char *str); 200 protected: 201 void Increment(MHEngine *engine); 202 void Decrement(MHEngine *engine); 203 204 // Exchanged attributes 205 // Orientation and direction of increasing value. 206 enum SliderOrientation { SliderLeft = 1, SliderRight, SliderUp, SliderDown } 207 m_orientation; 208 int initial_value, initial_portion; 209 int orig_max_value, orig_min_value, orig_step_size; 210 // Style of slider. Normal represents a mark on a scale, 211 // Thermometer a range from the start up to the mark and Proportional 212 // a range from the slider to the portion. 213 enum SliderStyle { SliderNormal = 1, SliderThermo, SliderProp } 214 m_style; 215 MHColour m_sliderRefColour; 216 // Internal attributes 217 // In UK MHEG min_value, max_value and step_size can be changed. 218 int max_value, min_value, step_size; 219 int slider_value, portion; 145 220 }; 146 221 147 222 class MHEntryField : public MHVisible, public MHInteractible … … 153 228 virtual void Initialise(MHParseNode *p, MHEngine *engine); 154 229 virtual void PrintMe(FILE *fd, int nTabs) const; 155 230 virtual void Display(MHEngine *) {} // Not (yet?) supported 231 232 // Implement the actions in the main inheritance line. 233 virtual void SetInteractionStatus(bool newStatus, MHEngine *engine) 234 { InteractSetInteractionStatus(newStatus, engine); } 235 virtual bool GetInteractionStatus(void) { return InteractGetInteractionStatus(); } 236 virtual void SetHighlightStatus(bool newStatus, MHEngine *engine) 237 { InteractSetHighlightStatus(newStatus, engine); } 238 virtual bool GetHighlightStatus(void) { return InteractGetHighlightStatus(); } 239 virtual void Deactivation(MHEngine *engine) { InteractDeactivation(); } 156 240 }; 157 241 158 242 // Button - not needed for UK MHEG. … … 311 395 virtual void CallAction(MHEngine *engine, MHRoot *pTarget, int nArg) { pTarget->SetLineStyle(nArg, engine); }; 312 396 }; 313 397 398 class MHSetInteractionStatus: public MHActionBool 399 { 400 public: 401 MHSetInteractionStatus(): MHActionBool("SetInteractionStatus") {} 402 virtual void CallAction(MHEngine *engine, MHRoot *pTarget, bool newStatus) 403 { Target(engine)->SetInteractionStatus(newStatus, engine); } 404 }; 405 406 class MHGetInteractionStatus: public MHActionObjectRef 407 { 408 public: 409 MHGetInteractionStatus(): MHActionObjectRef(":GetInteractionStatus") {} 410 virtual void CallAction(MHEngine *, MHRoot *pTarget, MHRoot *pResult) 411 { pResult->SetVariableValue(pTarget->GetInteractionStatus());} 412 }; 413 414 class MHSetHighlightStatus: public MHActionBool 415 { 416 public: 417 MHSetHighlightStatus(): MHActionBool("SetHighlightStatus") {} 418 virtual void CallAction(MHEngine *engine, MHRoot *pTarget, bool newStatus) 419 { Target(engine)->SetHighlightStatus(newStatus, engine); } 420 }; 421 422 class MHGetHighlightStatus: public MHActionObjectRef 423 { 424 public: 425 MHGetHighlightStatus(): MHActionObjectRef(":GetHighlightStatus") {} 426 virtual void CallAction(MHEngine *, MHRoot *pTarget, MHRoot *pResult) 427 { pResult->SetVariableValue(pTarget->GetHighlightStatus());} 428 }; 429 430 class MHStep: public MHActionInt 431 { 432 public: 433 MHStep(): MHActionInt(":Step") {} 434 virtual void CallAction(MHEngine *engine, MHRoot *pTarget, int nArg) { pTarget->Step(nArg, engine); }; 435 }; 436 437 class MHSetSliderValue: public MHActionInt 438 { 439 public: 440 MHSetSliderValue(): MHActionInt(":SetSliderValue") {} 441 virtual void CallAction(MHEngine *engine, MHRoot *pTarget, int nArg) { pTarget->SetSliderValue(nArg, engine); }; 442 }; 443 444 class MHGetSliderValue: public MHActionObjectRef 445 { 446 public: 447 MHGetSliderValue(): MHActionObjectRef(":GetSliderValue") {} 448 virtual void CallAction(MHEngine *, MHRoot *pTarget, MHRoot *pResult) 449 { pResult->SetVariableValue(pTarget->GetSliderValue());} 450 }; 451 452 class MHSetPortion: public MHActionInt 453 { 454 public: 455 MHSetPortion(): MHActionInt(":SetPortion") {} 456 virtual void CallAction(MHEngine *engine, MHRoot *pTarget, int nArg) { pTarget->SetPortion(nArg, engine); }; 457 }; 458 459 class MHGetPortion: public MHActionObjectRef 460 { 461 public: 462 MHGetPortion(): MHActionObjectRef(":GetPortion") {} 463 virtual void CallAction(MHEngine *, MHRoot *pTarget, MHRoot *pResult) 464 { pResult->SetVariableValue(pTarget->GetPortion());} 465 }; 466 467 class MHSetSliderParameters: public MHActionInt3 468 { 469 public: 470 MHSetSliderParameters(): MHActionInt3(":SetSliderParameters") {} 471 virtual void CallAction(MHEngine *engine, MHRoot *pTarget, int newMin, int newMax, int newStep) 472 { pTarget->SetSliderParameters(newMin, newMax, newStep, engine); }; 473 }; 474 314 475 #endif -
libs/libmythfreemheg/Engine.h
1 1 /* Engine.h 2 2 3 Copyright (C) David C. J. Matthews 2004 dm at prolingua.co.uk3 Copyright (C) David C. J. Matthews 2004, 2008 dm at prolingua.co.uk 4 4 5 5 This program is free software; you can redistribute it and/or 6 6 modify it under the terms of the GNU General Public License … … 63 63 MHIngredient *m_pRequester; 64 64 }; 65 65 66 class MHInteractible; 67 66 68 class MHEngine: public MHEG { 67 69 public: 68 70 MHEngine(MHContext *context); … … 148 150 149 151 static const char *MHEGEngineProviderIdString; 150 152 153 // Interaction: Set if an Interactible has the focus and is receiving key presses. 154 MHInteractible *GetInteraction(void) { return m_Interacting; } 155 void SetInteraction(MHInteractible *p) { m_Interacting = p; } 156 151 157 protected: 152 158 void CheckLinks(const MHObjectRef &sourceRef, enum EventType ev, const MHUnion &un); 153 159 MHGroup *ParseProgram(QByteArray &text); … … 187 193 188 194 MHContext *m_Context; // Pointer to the context providing drawing and other operations 189 195 bool m_fBooting; 196 197 MHInteractible *m_Interacting; // Set to current interactive object if any. 190 198 }; 191 199 192 200 #endif -
libs/libmythfreemheg/Bitmap.cpp
1 1 /* Bitmap.cpp 2 2 3 Copyright (C) David C. J. Matthews 2004 dm at prolingua.co.uk3 Copyright (C) David C. J. Matthews 2004, 2008 dm at prolingua.co.uk 4 4 5 5 This program is free software; you can redistribute it and/or 6 6 modify it under the terms of the GNU General Public License … … 111 111 if (nCHook == 4) { // PNG. 112 112 m_pContent->CreateFromPNG(data, length); 113 113 } 114 else if (nCHook == 2) { // MPEG I-frame. 114 // CHook 5 seems to be used by the BBC on Freesat for an MPEG I-frame for the 115 // background but enabling it here results in it overlaying the video. 116 // Presumably it is not simply the same as CHook 2. 117 else if (nCHook == 2 /* ||nCHook == 5 */) { // MPEG I-frame. 115 118 m_pContent->CreateFromMPEG(data, length); 116 119 } 117 120 -
libs/libmythfreemheg/Text.h
90 90 void CreateContent(const unsigned char *p, int s, MHEngine *engine); 91 91 }; 92 92 93 class MHHyperText : public MHText, public 93 class MHHyperText : public MHText, public MHInteractible 94 94 { 95 95 public: 96 96 MHHyperText(); … … 98 98 virtual ~MHHyperText(); 99 99 virtual void Initialise(MHParseNode *p, MHEngine *engine); 100 100 virtual void PrintMe(FILE *fd, int nTabs) const; 101 102 // Implement the actions in the main inheritance line. 103 virtual void SetInteractionStatus(bool newStatus, MHEngine *engine) 104 { InteractSetInteractionStatus(newStatus, engine); } 105 virtual bool GetInteractionStatus(void) { return InteractGetInteractionStatus(); } 106 virtual void SetHighlightStatus(bool newStatus, MHEngine *engine) 107 { InteractSetHighlightStatus(newStatus, engine); } 108 virtual bool GetHighlightStatus(void) { return InteractGetHighlightStatus(); } 109 virtual void Deactivation(MHEngine *engine) { InteractDeactivation(); } 101 110 }; 102 111 103 112 // Get Text Data - get the data out of a text object. -
libs/libmythfreemheg/Programs.cpp
490 490 } 491 491 492 492 else if (m_Name.Equal("DBG")) { // Debug - optional 493 MHERROR("Debug ResidentProgram is not implemented"); 493 QString message = "DEBUG: "; 494 for (int i = 0; i < args.Size(); i++) { 495 MHUnion un; 496 un.GetValueFrom(*(args.GetAt(i)), engine); 497 switch (un.m_Type) { 498 case MHUnion::U_Int: 499 message.append(QString("%1").arg(un.m_nIntVal)); 500 break; 501 case MHParameter::P_Bool: 502 message.append(un.m_fBoolVal ? "True" : "False"); 503 break; 504 case MHParameter::P_String: 505 message.append(QString::fromUtf8((const char *)un.m_StrVal.Bytes(), un.m_StrVal.Size())); 506 break; 507 case MHParameter::P_ObjRef: 508 message.append(un.m_ObjRefVal.Printable()); 509 break; 510 case MHParameter::P_ContentRef: 511 message.append(un.m_ContentRefVal.Printable()); 512 break; 513 case MHParameter::P_Null: 514 break; 515 } 516 } 517 MHLOG(MHLogNotifications, message); 494 518 } 495 519 496 520 else { -
libs/libmythfreemheg/BaseActions.cpp
1 1 /* BaseActions.cpp 2 2 3 Copyright (C) David C. J. Matthews 2004 dm at prolingua.co.uk3 Copyright (C) David C. J. Matthews 2004, 2008 dm at prolingua.co.uk 4 4 5 5 This program is free software; you can redistribute it and/or 6 6 modify it under the terms of the GNU General Public License … … 87 87 m_ResultVar2.Initialise(p->GetArgN(2), engine); 88 88 } 89 89 90 void MHActionInt3::Initialise(MHParseNode *p, MHEngine *engine) 91 { 92 MHElemAction::Initialise(p, engine); 93 m_Argument1.Initialise(p->GetArgN(1), engine); 94 m_Argument2.Initialise(p->GetArgN(2), engine); 95 m_Argument3.Initialise(p->GetArgN(3), engine); 96 } 97 98 void MHActionInt3::PrintArgs(FILE *fd, int /*nTabs*/) const 99 { 100 m_Argument1.PrintMe(fd, 0); 101 m_Argument2.PrintMe(fd, 0); 102 m_Argument3.PrintMe(fd, 0); 103 } 104 105 void MHActionInt3::Perform(MHEngine *engine) 106 { 107 CallAction(engine, Target(engine), m_Argument1.GetValue(engine), m_Argument2.GetValue(engine), m_Argument3.GetValue(engine)); 108 } 109 90 110 void MHActionInt4::Initialise(MHParseNode *p, MHEngine *engine) 91 111 { 92 112 MHElemAction::Initialise(p, engine); … … 160 180 { 161 181 CallAction(engine, Target(engine), engine->FindObject(m_ResultVar1), engine->FindObject(m_ResultVar2)); 162 182 } 183 184 void MHActionBool::Initialise(MHParseNode *p, MHEngine *engine) 185 { 186 MHElemAction::Initialise(p, engine); 187 m_Argument.Initialise(p->GetArgN(1), engine); 188 } 189 190 191 void MHActionBool::Perform(MHEngine *engine) 192 { 193 CallAction(engine, Target(engine), m_Argument.GetValue(engine)); 194 } -
libs/libmythfreemheg/Link.cpp
1 1 /* Link.cpp 2 2 3 Copyright (C) David C. J. Matthews 2004 dm at prolingua.co.uk3 Copyright (C) David C. J. Matthews 2004, 2008 dm at prolingua.co.uk 4 4 5 5 This program is free software; you can redistribute it and/or 6 6 modify it under the terms of the GNU General Public License … … 76 76 m_LinkEffect.Initialise(pLinkEffect, engine); 77 77 } 78 78 79 static c har *rchEventType[] =79 static const char *rchEventType[] = 80 80 { 81 81 "IsAvailable", 82 82 "ContentAvailable", -
libs/libmythfreemheg/TokenGroup.cpp
54 54 for (int i = 0; i < m_ActionSlots.Size(); i++) { 55 55 PrintTabs(fd, nTabs+2); fprintf(fd, "(\n"); 56 56 MHActionSequence *pActions = m_ActionSlots.GetAt(i); 57 if (pActions->Size() == 0) fprintf(fd, "NULL\n"); 57 if (pActions->Size() == 0) 58 { PrintTabs(fd, nTabs+2); fprintf(fd, "NULL\n"); } 58 59 else pActions->PrintMe(fd, nTabs+2); 59 60 PrintTabs(fd, nTabs+2); fprintf(fd, ")\n"); 60 61 } -
libs/libmythfreemheg/Visible.cpp
345 345 } 346 346 347 347 348 MHInteractible::MHInteractible( )348 MHInteractible::MHInteractible(MHVisible *parent): m_parent(parent) 349 349 { 350 350 m_fEngineResp = true; 351 m_fHighlightStatus = false; 352 m_fInteractionStatus = false; 351 353 } 352 354 353 355 MHInteractible::~MHInteractible() … … 355 357 356 358 } 357 359 358 void MHInteractible::Initialise(MHParseNode * /*p*/, MHEngine */*engine*/)360 void MHInteractible::Initialise(MHParseNode *p, MHEngine *engine) 359 361 { 362 // Engine Resp - optional 363 MHParseNode *pEngineResp = p->GetNamedArg(C_ENGINE_RESP); 364 if (pEngineResp) m_fEngineResp = pEngineResp->GetArgN(0)->GetBoolValue(); 365 // Highlight colour. 366 MHParseNode *phlCol = p->GetNamedArg(C_HIGHLIGHT_REF_COLOUR); 367 if (phlCol) m_highlightRefColour.Initialise(phlCol->GetArgN(0), engine); 368 else engine->GetDefaultHighlightRefColour(m_highlightRefColour); 369 m_fHighlightStatus = false; 370 m_fInteractionStatus = false; 360 371 } 361 372 362 void MHInteractible::PrintMe(FILE * /*fd*/, int /*nTabs*/) const373 void MHInteractible::PrintMe(FILE *fd, int nTabs) const 363 374 { 375 if (! m_fEngineResp) { PrintTabs(fd, nTabs); fprintf(fd, ":EngineResp false\n"); } 376 377 if (m_highlightRefColour.IsSet()) { 378 PrintTabs(fd, nTabs); 379 fprintf(fd, ":HighlightRefColour "); 380 m_highlightRefColour.PrintMe(fd, nTabs+1); 381 fprintf(fd, "\n"); 382 } 364 383 } 365 384 366 MHSlider::MHSlider()385 void MHInteractible::Interaction(MHEngine *engine) 367 386 { 387 m_fInteractionStatus = true; 388 engine->SetInteraction(this); 389 // The MHEG standard says: "generate visual feedback" here 390 // but it appears that any visual feedback is controlled only 391 // by the highlight status combined with engine-resp. 392 } 368 393 394 void MHInteractible::InteractSetInteractionStatus(bool newStatus, MHEngine *engine) 395 { 396 if (newStatus) { // Turning interaction on. 397 if (engine->GetInteraction() == 0) // No current interactible 398 Interaction(engine); // virtual function 399 } 400 else { // Turning interaction off. 401 if (m_fInteractionStatus) { 402 m_fInteractionStatus = false; 403 engine->SetInteraction(0); 404 InteractionCompleted(engine); // Interaction is interrupted. 405 engine->EventTriggered(m_parent, EventInteractionCompleted); 406 } 407 } 369 408 } 370 409 371 MHSlider::~MHSlider()410 void MHInteractible::InteractSetHighlightStatus(bool newStatus, MHEngine *engine) 372 411 { 412 if (newStatus == m_fHighlightStatus) return; 413 m_fHighlightStatus = newStatus; 414 // If active redraw to show change of status. 415 if (m_parent->GetRunningStatus() && m_fEngineResp) 416 engine->Redraw(m_parent->GetVisibleArea()); 417 // Generate the event for the change of highlight status. 418 engine->EventTriggered(m_parent, m_fHighlightStatus ? EventHighlightOn: EventHighlightOff); 419 } 373 420 421 MHSlider::MHSlider(): MHInteractible(this) 422 { 423 m_orientation = SliderLeft; 424 orig_max_value = -1; 425 orig_min_value = initial_value = orig_step_size = 1; 426 initial_portion = 0; 427 m_style = SliderNormal; 374 428 } 375 429 430 MHSlider::~MHSlider() 431 { 432 } 433 376 434 void MHSlider::Initialise(MHParseNode *p, MHEngine *engine) 377 435 { 378 436 MHVisible::Initialise(p, engine); 379 437 MHInteractible::Initialise(p, engine); 380 // 438 // 439 MHParseNode *pOrientation = p->GetNamedArg(C_ORIENTATION); 440 if (pOrientation) 441 m_orientation = (enum SliderOrientation)pOrientation->GetArgN(0)->GetEnumValue(); 442 // This is not optional. 443 444 MHParseNode *pMin = p->GetNamedArg(C_MIN_VALUE); 445 if (pMin) orig_min_value = pMin->GetArgN(0)->GetIntValue(); 446 else orig_min_value = 1; 447 448 MHParseNode *pMax = p->GetNamedArg(C_MAX_VALUE); 449 if (pMax) orig_max_value = pMax->GetArgN(0)->GetIntValue(); 450 else orig_max_value = orig_min_value-1; // Unset 451 452 MHParseNode *pInit = p->GetNamedArg(C_INITIAL_VALUE); 453 if (pInit) initial_value = pInit->GetArgN(0)->GetIntValue(); 454 else initial_value = orig_min_value; // Default is min_value 455 456 MHParseNode *pPortion = p->GetNamedArg(C_INITIAL_PORTION); 457 if (pPortion) initial_portion = pPortion->GetArgN(0)->GetIntValue(); 458 else initial_portion = orig_min_value-1; // Unset 459 460 MHParseNode *pStep = p->GetNamedArg(C_STEP_SIZE); 461 if (pStep) orig_step_size = pStep->GetArgN(0)->GetIntValue(); 462 else orig_step_size = 1; // Unset 463 464 MHParseNode *pStyle = p->GetNamedArg(C_SLIDER_STYLE); 465 if (pStyle) m_style = (enum SliderStyle)pStyle->GetArgN(0)->GetEnumValue(); 466 else m_style = SliderNormal; 467 468 MHParseNode *pslCol = p->GetNamedArg(C_SLIDER_REF_COLOUR); 469 if (pslCol) m_sliderRefColour.Initialise(pslCol->GetArgN(0), engine); 470 else engine->GetDefaultSliderRefColour(m_sliderRefColour); 381 471 } 382 472 473 static const char *rchOrientation[] = 474 { 475 "left", // 1 476 "right", 477 "up", 478 "down" // 4 479 }; 480 481 // Look up the Orientation. Returns zero if it doesn't match. Used in the text parser only. 482 int MHSlider::GetOrientation(const char *str) 483 { 484 for (int i = 0; i < (int)(sizeof(rchOrientation)/sizeof(rchOrientation[0])); i++) { 485 if (strcasecmp(str, rchOrientation[i]) == 0) return (i+1); // Numbered from 1 486 } 487 return 0; 488 } 489 490 static const char *rchStyle[] = 491 { 492 "normal", // 1 493 "thermometer", 494 "proportional" // 3 495 }; 496 497 int MHSlider::GetStyle(const char *str) 498 { 499 for (int i = 0; i < (int)(sizeof(rchStyle)/sizeof(rchStyle[0])); i++) { 500 if (strcasecmp(str, rchStyle[i]) == 0) return (i+1); // Numbered from 1 501 } 502 return 0; 503 } 504 383 505 void MHSlider::PrintMe(FILE *fd, int nTabs) const 384 506 { 385 507 PrintTabs(fd, nTabs); fprintf(fd, "{:Slider "); 386 MHVisible::PrintMe(fd, nTabs );508 MHVisible::PrintMe(fd, nTabs+1); 387 509 MHInteractible::PrintMe(fd, nTabs+1); 388 fprintf(fd, "****TODO\n"); 510 511 PrintTabs(fd, nTabs); fprintf(fd, ":Orientation %s\n", rchOrientation[m_orientation-1]); 512 513 if (initial_value >= orig_min_value) { 514 PrintTabs(fd, nTabs+1); fprintf(fd, ":InitialValue %d\n", initial_value); 515 } 516 517 if (orig_min_value != 1) { 518 PrintTabs(fd, nTabs+1); fprintf(fd, ":MinValue %d\n", orig_min_value); 519 } 520 521 if (orig_max_value > orig_min_value) { 522 PrintTabs(fd, nTabs+1); fprintf(fd, ":MaxValue %d\n", orig_max_value); 523 } 524 525 if (initial_portion >= orig_min_value) { 526 PrintTabs(fd, nTabs+1); fprintf(fd, ":InitialPortion %d\n", initial_portion); 527 } 528 529 if (orig_step_size != 1) { 530 PrintTabs(fd, nTabs+1); fprintf(fd, ":StepSize %d\n", orig_step_size); 531 } 532 533 if (m_style != SliderNormal) 534 { 535 PrintTabs(fd, nTabs+1); 536 fprintf(fd, ":SliderStyle %s\n", rchStyle[m_style-1]); 537 } 538 539 if (m_sliderRefColour.IsSet()) { 540 PrintTabs(fd, nTabs+1); 541 fprintf(fd, ":SliderRefColour "); 542 m_sliderRefColour.PrintMe(fd, nTabs+2); 543 fprintf(fd, "\n"); 544 } 545 389 546 PrintTabs(fd, nTabs); fprintf(fd, "}\n"); 390 547 } 391 548 392 MHEntryField::MHEntryField() 549 // The MHEG standard doesn't define where the internal values are 550 // initialised. Assume it's during preparation. 551 void MHSlider::Preparation(MHEngine *engine) 393 552 { 553 MHVisible::Preparation(engine); 554 max_value = orig_max_value; 555 min_value = orig_min_value; 556 step_size = orig_step_size; 557 slider_value = initial_value; 558 portion = initial_portion; 559 } 394 560 561 void MHSlider::Display(MHEngine *engine) 562 { 563 MHContext *d = engine->GetContext(); 564 MHRgba colour; 565 if (m_fHighlightStatus && m_fEngineResp) 566 colour = GetColour(m_highlightRefColour); 567 else colour = GetColour(m_sliderRefColour); 568 569 int major; // Direction of change. 570 if (m_orientation == SliderLeft || m_orientation == SliderRight) 571 major = m_nBoxWidth; 572 else major = m_nBoxHeight; 573 574 if (max_value <= min_value) return; // Avoid divide by zero if error. 575 576 if (m_style == SliderNormal) 577 { 578 // This is drawn as a 9 pixel wide "thumb" at the position. 579 major -= 9; // Width of "thumb" 580 int posn = major * (slider_value-min_value) / (max_value-min_value); 581 switch (m_orientation) 582 { 583 case SliderLeft: 584 d->DrawRect(m_nPosX + posn, m_nPosY, 9, m_nBoxHeight, colour); 585 break; 586 case SliderRight: 587 d->DrawRect(m_nPosX + m_nBoxWidth - posn - 9, m_nPosY, 9, m_nBoxHeight, colour); 588 break; 589 case SliderUp: 590 d->DrawRect(m_nPosX, m_nPosY + m_nBoxHeight - posn - 9, m_nBoxWidth, 9, colour); 591 break; 592 case SliderDown: 593 d->DrawRect(m_nPosX, m_nPosY + posn, m_nBoxWidth, 9, colour); 594 break; 595 } 596 } 597 else { 598 // Thermometer and proportional sliders are drawn as bars. Thermometers 599 // run from the start to the position, proportional sliders from the 600 // position for the "portion". 601 int start = 0; 602 int end = major * (slider_value-min_value) / (max_value-min_value); 603 if (m_style == SliderProp) 604 { 605 start = end; 606 end = major * (slider_value+portion -min_value) / (max_value-min_value); 607 } 608 switch (m_orientation) 609 { 610 case SliderLeft: 611 d->DrawRect(m_nPosX + start, m_nPosY, end-start, m_nBoxHeight, colour); 612 break; 613 case SliderRight: 614 d->DrawRect(m_nPosX + m_nBoxWidth - end, m_nPosY, end-start, m_nBoxHeight, colour); 615 break; 616 case SliderUp: 617 d->DrawRect(m_nPosX, m_nPosY + m_nBoxHeight - end, m_nBoxWidth, end-start, colour); 618 break; 619 case SliderDown: 620 d->DrawRect(m_nPosX, m_nPosY + start, m_nBoxWidth, end-start, colour); 621 break; 622 } 623 624 } 395 625 } 396 626 627 void MHSlider::Interaction(MHEngine *engine) 628 { 629 MHInteractible::Interaction(engine); 630 // All the interaction is handled by KeyEvent. 631 } 632 633 // Called when the interaction has been terminated and we need 634 // to restore the state to non-interacting. 635 void MHSlider::InteractionCompleted(MHEngine *engine) 636 { 637 MHInteractible::InteractionCompleted(engine); 638 // Redraw with the interaction highlighting turned off 639 engine->Redraw(GetVisibleArea()); 640 } 641 642 // Called when a key is pressed. The only keys that have an effect are 643 // the Select and Cancel keys which both terminate the action and the 644 // arrow keys. The effect of the arrow keys depends on the orientation of 645 // the slider. 646 void MHSlider::KeyEvent(MHEngine *engine, int nCode) 647 { 648 switch (nCode) 649 { 650 case 15: // Select key 651 case 16: // Cancel key 652 m_fInteractionStatus = false; 653 engine->SetInteraction(0); 654 InteractionCompleted(engine); // Interaction is interrupted. 655 engine->EventTriggered(this, EventInteractionCompleted); 656 break; 657 658 case 1: // Up 659 if (m_orientation == SliderUp) 660 Increment(engine); 661 else if (m_orientation == SliderDown) 662 Decrement(engine); 663 break; 664 665 case 2: // Down 666 if (m_orientation == SliderUp) 667 Decrement(engine); 668 else if (m_orientation == SliderDown) 669 Increment(engine); 670 break; 671 672 case 3: // Left 673 if (m_orientation == SliderLeft) 674 Increment(engine); 675 else if (m_orientation == SliderRight) 676 Decrement(engine); 677 break; 678 679 case 4: // Right 680 if (m_orientation == SliderLeft) 681 Decrement(engine); 682 else if (m_orientation == SliderRight) 683 Increment(engine); 684 break; 685 686 } 687 } 688 689 void MHSlider::Increment(MHEngine *engine) 690 { 691 if (slider_value+step_size <= max_value) 692 { 693 slider_value += step_size; 694 engine->Redraw(GetVisibleArea()); 695 engine->EventTriggered(this, EventSliderValueChanged); 696 } 697 } 698 699 void MHSlider::Decrement(MHEngine *engine) 700 { 701 if (slider_value-step_size >= min_value) 702 { 703 slider_value -= step_size; 704 engine->Redraw(GetVisibleArea()); 705 engine->EventTriggered(this, EventSliderValueChanged); 706 } 707 } 708 709 void MHSlider::Step(int nbSteps, MHEngine *engine) 710 { 711 step_size = nbSteps; 712 if (m_fRunning) engine->Redraw(GetVisibleArea()); 713 engine->EventTriggered(this, EventSliderValueChanged); 714 } 715 716 void MHSlider::SetSliderValue(int newValue, MHEngine *engine) 717 { 718 slider_value = newValue; 719 if (m_fRunning) engine->Redraw(GetVisibleArea()); 720 engine->EventTriggered(this, EventSliderValueChanged); 721 } 722 723 void MHSlider::SetPortion(int newPortion, MHEngine *engine) 724 { 725 portion = newPortion; 726 if (m_fRunning) engine->Redraw(GetVisibleArea()); 727 engine->EventTriggered(this, EventSliderValueChanged); 728 } 729 730 // Additional action defined in UK MHEG. 731 void MHSlider::SetSliderParameters(int newMin, int newMax, int newStep, MHEngine *engine) 732 { 733 min_value = newMin; 734 max_value = newMax; 735 step_size = newStep; 736 slider_value = newMin; 737 if (m_fRunning) engine->Redraw(GetVisibleArea()); 738 engine->EventTriggered(this, EventSliderValueChanged); 739 } 740 741 742 MHEntryField::MHEntryField(): MHInteractible(this) 743 { 744 745 } 746 397 747 MHEntryField::~MHEntryField() 398 748 { 399 749 -
libs/libmythtv/mhi.h
180 180 181 181 uint m_lastNbiVersion; 182 182 QMemArray<unsigned char> m_nbiData; 183 184 QRect m_videoRect; 183 185 }; 184 186 185 187 // Object for drawing text. -
libs/libmythtv/mhi.cpp
36 36 m_face_loaded(false), m_currentChannel(-1), 37 37 m_isLive(false), m_currentCard(0), 38 38 m_audioTag(-1), m_videoTag(-1), 39 m_tuningTo(-1), m_lastNbiVersion(NBI_VERSION_UNSET) 39 m_tuningTo(-1), m_lastNbiVersion(NBI_VERSION_UNSET), 40 m_videoRect(0, 0, StdDisplayWidth, StdDisplayHeight) 40 41 { 41 42 m_display.setAutoDelete(true); 42 43 m_dsmccQueue.setAutoDelete(true); … … 402 403 { 403 404 m_displayWidth = display.width(); 404 405 m_displayHeight = display.height(); 406 m_videoRect = display; // Assume full screen at this stage. 405 407 } 406 408 407 409 void MHIContext::SetInputRegister(int num) … … 452 454 void MHIContext::AddToDisplay(const QImage &image, int x, int y) 453 455 { 454 456 MHIImageData *data = new MHIImageData; 455 data->m_image = image; 457 // It seems that OSDTypeImage::Load doesn't deal well with images 458 // located on odd pixel boundaries and the resulting display contains 459 // transparent lines. To avoid this we create a new image if either 460 // the x or y offset would be odd and set the extra pixels to transparent. 461 QImage img = image; 462 int xboundary = x & 1; 463 int yboundary = y & 1; 464 465 if (xboundary || yboundary) 466 { 467 int width = img.width(), height = img.height(); 468 if (xboundary) 469 { 470 width++; 471 x--; 472 } 473 if (yboundary) 474 { 475 height++; 476 y--; 477 } 478 img = QImage(width, height, 32); 479 img.setAlphaBuffer(true); 480 QRgb qTransparent = qRgba(0,0,0,0); 481 if (xboundary) 482 { 483 for (int i = 0; i < height; i++) 484 img.setPixel(0, i, qTransparent); 485 } 486 487 if (yboundary) 488 { 489 for (int j = 0; j < width; j++) 490 img.setPixel(j, 0, qTransparent); 491 } 492 493 for (int i = 0; i < height-yboundary; i++) 494 { 495 for (int j = 0; j < width-xboundary; j++) 496 { 497 img.setPixel(j+xboundary, i+yboundary, image.pixel(j,i)); 498 } 499 } 500 } 501 data->m_image = img; 456 502 data->m_x = x; 457 503 data->m_y = y; 458 504 QMutexLocker locker(&m_display_lock); … … 470 516 { 471 517 // tell the video player to resize the video stream 472 518 if (m_parent->GetNVP()) 473 m_parent->GetNVP()->SetVideoResize(videoRect); 519 { 520 QRect vidRect(videoRect.x() * m_displayWidth/StdDisplayWidth, 521 videoRect.y() * m_displayHeight/StdDisplayHeight, 522 videoRect.width() * m_displayWidth/StdDisplayWidth, 523 videoRect.height() * m_displayHeight/StdDisplayHeight); 524 if (m_videoRect != vidRect) 525 { 526 m_parent->GetNVP()->SetVideoResize(vidRect); 527 m_videoRect = vidRect; 528 } 529 } 474 530 475 531 QMutexLocker locker(&m_display_lock); 476 532 QRect displayRect(dispRect.x() * m_displayWidth/StdDisplayWidth, … … 713 769 QRgb qColour = qRgba(colour.red(), colour.green(), 714 770 colour.blue(), colour.alpha()); 715 771 716 // This is a bit of a mess: we should be able to create a rectangle object.717 // Scale the image to the current display size718 772 int scaledWidth = width * GetWidth() / MHIContext::StdDisplayWidth; 719 773 int scaledHeight = height * GetHeight() / MHIContext::StdDisplayHeight; 720 774 QImage qImage(scaledWidth, scaledHeight, 32); 721 775 qImage.setAlphaBuffer(true); 722 776 723 // As far as I can tell this is the only way to draw with an724 // intermediate transparency.725 777 for (int i = 0; i < scaledHeight; i++) 726 778 { 727 779 for (int j = 0; j < scaledWidth; j++) … … 1252 1304 // The UK profile says that MHEG should not contain concave or 1253 1305 // self-crossing polygons but we can get the former at least as 1254 1306 // a result of rounding when drawing ellipses. 1307 typedef struct { int yBottom, yTop, xBottom; float slope; } lineSeg; 1308 1255 1309 void MHIDLA::DrawPoly(bool isFilled, const QPointArray &points) 1256 1310 { 1257 1311 int nPoints = points.size(); … … 1260 1314 1261 1315 if (isFilled) 1262 1316 { 1263 // Polygon filling is done by sketching the outline of 1264 // the polygon in a separate bitmap and then raster scanning 1265 // across this to generate the fill. There are some special 1266 // cases that have to be considered when doing this. Maximum 1267 // and minimum points have to be removed otherwise they will 1268 // turn the scan on but not off again. Horizontal lines are 1269 // suppressed and their ends handled specially. 1270 QRect bounds = points.boundingRect(); 1271 int width = bounds.width()+1, height = bounds.height()+1; 1272 QBitArray boundsMap(width*height); 1273 boundsMap.fill(0); 1274 // Draw the boundaries in the bounds map. This is 1275 // the Bresenham algorithm if the absolute gradient is 1276 // greater than 1 but puts only the centre of each line 1277 // (so there is only one point for each y value) if less. 1278 QPoint last = points[nPoints-1]; // Last point 1279 for (int i = 0; i < nPoints; i++) 1317 QMemArray <lineSeg> lineArray(nPoints); 1318 int nLines = 0; 1319 // Initialise the line segment array. Include all lines 1320 // apart from horizontal. Close the polygon by starting 1321 // with the last point in the array. 1322 int lastX = points[nPoints-1].x(); // Last point 1323 int lastY = points[nPoints-1].y(); 1324 int yMin = lastY, yMax = lastY; 1325 for (int k = 0; k < nPoints; k++) 1280 1326 { 1281 QPoint thisPoint = points[i]; 1282 int x1 = last.x() - bounds.x(); 1283 int y1 = last.y() - bounds.y(); 1284 int x2 = thisPoint.x() - bounds.x(); 1285 int y2 = thisPoint.y() - bounds.y(); 1286 int x, xEnd, y, yEnd; 1287 if (y2 > y1) 1327 int thisX = points[k].x(); 1328 int thisY = points[k].y(); 1329 if (lastY != thisY) 1288 1330 { 1289 x = x1; 1290 y = y1; 1291 xEnd = x2; 1292 yEnd = y2; 1293 } 1294 else 1295 { 1296 x = x2; 1297 y = y2; 1298 xEnd = x1; 1299 yEnd = y1; 1300 } 1301 int dx = abs(xEnd-x), dy = yEnd-y; 1302 int xStep = xEnd >= x ? 1 : -1; 1303 if (abs(y2-y1) > abs(x2-x1)) 1304 { 1305 int error = dy/2; 1306 y++; 1307 for (; y < yEnd; y++) // Exclude endpoints 1331 if (lastY > thisY) 1308 1332 { 1309 boundsMap.toggleBit(x+y*width); 1310 error += dx; 1311 if (error*2 > dy) 1312 { 1313 error -= dy; 1314 x += xStep; 1315 } 1333 lineArray[nLines].yBottom = thisY; 1334 lineArray[nLines].yTop = lastY; 1335 lineArray[nLines].xBottom = thisX; 1316 1336 } 1317 } 1318 else 1319 { 1320 int error = 0; 1321 y++; 1322 for (; y < yEnd; y++) 1337 else 1323 1338 { 1324 boundsMap.toggleBit(x+y*width); 1325 error += dx; 1326 while (error > dy) 1327 { 1328 x += xStep; 1329 error -= dy; 1330 } 1339 lineArray[nLines].yBottom = lastY; 1340 lineArray[nLines].yTop = thisY; 1341 lineArray[nLines].xBottom = lastX; 1331 1342 } 1343 lineArray[nLines++].slope = 1344 (float)(thisX-lastX) / (float)(thisY-lastY); 1332 1345 } 1333 QPoint nextPoint = points[(i+1) % nPoints]; 1334 int nextY = nextPoint.y() - bounds.y(); 1335 int turn = (y2 - y1) * (nextY - y2); 1336 if (turn > 0) // Not a max or min 1337 boundsMap.toggleBit(x2+y2*width); 1338 else if (turn == 0) // Previous or next line is horizontal 1339 { 1340 // We only draw a point at the beginning or end of a horizontal 1341 // line if it turns clockwise. This means that the fill 1342 // will be different depending on the direction the polygon was 1343 // drawn but that will be tidied up when we draw the lines round. 1344 if (y1 == y2) 1345 { 1346 if ((x2-x1) * (nextY - y2) > 0) 1347 boundsMap.toggleBit(x2+y2*width); 1348 } 1349 else if ((nextPoint.x() - bounds.x() - x2) * (y2 - y1) < 0) 1350 // Next line is horizontal - draw point if turn is clockwise. 1351 boundsMap.toggleBit(x2+y2*width); 1352 } 1353 last = thisPoint; 1346 if (thisY < yMin) 1347 yMin = thisY; 1348 if (thisY > yMax) 1349 yMax = thisY; 1350 lastX = thisX; 1351 lastY = thisY; 1354 1352 } 1353 1354 // Find the intersections of each line in the line segment array 1355 // with the scan line. Because UK MHEG says that figures should be 1356 // convex we only need to consider two intersections. 1355 1357 QRgb fillColour = qRgba(m_fillColour.red(), m_fillColour.green(), 1356 1358 m_fillColour.blue(), m_fillColour.alpha()); 1357 // Now scan the bounds map and use this to fill the polygon. 1358 for (int j = 0; j < bounds.height(); j++) 1359 for (int y = yMin; y < yMax; y++) 1359 1360 { 1360 bool penDown = false;1361 for (int k = 0; k < bounds.width(); k++)1361 int crossings = 0, xMin = 0, xMax = 0; 1362 for (int l = 0; l < nLines; l++) 1362 1363 { 1363 if (boundsMap.testBit(k+j*width)) 1364 penDown = ! penDown; 1365 else if (penDown && k+bounds.x() >= 0 && j+bounds.y() >= 0 && 1366 k+bounds.x() < m_width && j+bounds.y() < m_height) 1367 m_image.setPixel(k+bounds.x(), j+bounds.y(), fillColour); 1364 if (y >= lineArray[l].yBottom && y < lineArray[l].yTop) 1365 { 1366 int x = (int)round((float)(y - lineArray[l].yBottom) * 1367 lineArray[l].slope) + lineArray[l].xBottom; 1368 if (crossings == 0 || x < xMin) 1369 xMin = x; 1370 if (crossings == 0 || x > xMax) 1371 xMax = x; 1372 crossings++; 1373 } 1368 1374 } 1375 if (crossings == 2) 1376 { 1377 for (int x = xMin; x <= xMax; x++) 1378 m_image.setPixel(x, y, fillColour); 1379 } 1369 1380 } 1370 1381 1371 1382 // Draw the boundary 1372 last = points[nPoints-1]; // Last point1383 QPoint last = points[nPoints-1]; // Last point 1373 1384 for (int i = 0; i < nPoints; i++) 1374 1385 { 1375 1386 DrawLine(points[i].x(), points[i].y(), last.x(), last.y()); … … 1394 1405 return; 1395 1406 // Construct an image the size of the bounding box and tile the 1396 1407 // bitmap over this. 1397 QImage tiledImage = QImage(rect.width(), rect.height(), 1398 m_image.depth()); 1408 QImage tiledImage = QImage(rect.width(), rect.height(), 32); 1399 1409 1400 1410 for (int i = 0; i < rect.width(); i += m_image.width()) 1401 1411 { … … 1536 1546 1537 1547 m_image = m_image.smoothScale(newWidth, newHeight); 1538 1548 } 1549 1550